mirror of
https://github.com/Rogiel/star-replay
synced 2025-12-06 06:32:46 +00:00
Initial commit
This commit is contained in:
51
bin/Template/Event.php
Normal file
51
bin/Template/Event.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2016, Rogiel Sulzbach
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace Rogiel\StarReplay\Event\{Type};
|
||||
|
||||
class {Name} extends Abstract{Type}Event {{
|
||||
|
||||
{Fields}
|
||||
|
||||
/**
|
||||
* @return string the event name
|
||||
*/
|
||||
public function getEventName() {{
|
||||
return "{FullName}";
|
||||
}}
|
||||
|
||||
/**
|
||||
* @return string a string representation of the event
|
||||
*/
|
||||
public function __toString() {{
|
||||
return $this->getEventName()."{{ {ToString} }}";
|
||||
}}
|
||||
|
||||
{Getters}
|
||||
|
||||
}}
|
||||
122
bin/Template/Version.php
Normal file
122
bin/Template/Version.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2016, Rogiel Sulzbach
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace Rogiel\StarReplay\Version;
|
||||
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Tree;
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\ArrayNode;
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\BitArrayNode;
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\BlobNode;
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\BooleanNode;
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\ChoiceNode;
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\IntegerNode;
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\FourCCNode;
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\NullNode;
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\OptionalNode;
|
||||
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\StructNode;
|
||||
|
||||
class Version{Version} extends AbstractVersion {{
|
||||
|
||||
public static $TREE;
|
||||
public static $GAME_EVENT_MAPPING;
|
||||
public static $MESSAGE_EVENT_MAPPING;
|
||||
public static $TRACKER_EVENT_MAPPING;
|
||||
|
||||
public function getVersion() {{
|
||||
return {Version};
|
||||
}}
|
||||
|
||||
public function getTree() {{
|
||||
return self::$TREE;
|
||||
}}
|
||||
|
||||
public function getGameEventMapping() {{
|
||||
return self::$GAME_EVENT_MAPPING;
|
||||
}}
|
||||
|
||||
public function getMessageEventMapping() {{
|
||||
return self::$MESSAGE_EVENT_MAPPING;
|
||||
}}
|
||||
|
||||
public function getTrackerEventMapping() {{
|
||||
return self::$TRACKER_EVENT_MAPPING;
|
||||
}}
|
||||
|
||||
public function getReplayHeaderNode() {{
|
||||
return self::$TREE->getNode({HeaderNode});
|
||||
}}
|
||||
|
||||
public function getReplayInitDataNode() {{
|
||||
return self::$TREE->getNode({InitDataNode});
|
||||
}}
|
||||
|
||||
public function getGameDetailsNode() {{
|
||||
return self::$TREE->getNode({GameDetailsNode});
|
||||
}}
|
||||
|
||||
public function getGameEventHeaderNode() {{
|
||||
return new StructNode(
|
||||
[
|
||||
'timestamp' => ['type' => {TimestampNode}],
|
||||
'user' => ['type' => {UserNode}],
|
||||
'event' => ['type' => {GameEventNode}]
|
||||
],
|
||||
'Rogiel\StarReplay\Metadata\Event\Header',
|
||||
true
|
||||
);
|
||||
}}
|
||||
|
||||
public function getMessageEventHeaderNode() {{
|
||||
return new StructNode(
|
||||
[
|
||||
'timestamp' => ['type' => {TimestampNode}],
|
||||
'user' => ['type' => {UserNode}],
|
||||
'event' => ['type' => {MessageEventNode}]
|
||||
],
|
||||
'Rogiel\StarReplay\Metadata\Event\Header',
|
||||
true
|
||||
);
|
||||
}}
|
||||
|
||||
public function getTrackerEventHeaderNode() {{
|
||||
return new StructNode(
|
||||
[
|
||||
'timestamp' => ['type' => {TimestampNode}],
|
||||
'event' => ['type' => {TrackerEventNode}]
|
||||
],
|
||||
'Rogiel\StarReplay\Metadata\Event\Header',
|
||||
true
|
||||
);
|
||||
}}
|
||||
|
||||
}}
|
||||
|
||||
Version{Version}::$TREE = new Tree({Tree});
|
||||
Version{Version}::$GAME_EVENT_MAPPING = {GameEvents};
|
||||
Version{Version}::$MESSAGE_EVENT_MAPPING = {MessageEvents};
|
||||
Version{Version}::$TRACKER_EVENT_MAPPING = {TrackerEvents};
|
||||
37
bin/Template/Versions.php
Normal file
37
bin/Template/Versions.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2016, Rogiel Sulzbach
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace Rogiel\StarReplay\Version;
|
||||
|
||||
class Versions {{
|
||||
|
||||
public static function getVersions() {{
|
||||
return {Versions};
|
||||
}}
|
||||
|
||||
}}
|
||||
148
bin/class_mapping.py
Normal file
148
bin/class_mapping.py
Normal file
@@ -0,0 +1,148 @@
|
||||
|
||||
def find_struct_field(protocol, struct, field_name):
|
||||
for field in struct[1][0]:
|
||||
if field[0] == field_name:
|
||||
return field
|
||||
return None
|
||||
|
||||
def set_class(mapping, protocol, field, class_name):
|
||||
if field == None:
|
||||
return
|
||||
|
||||
if protocol.typeinfos[field[1]][0] == '_optional':
|
||||
mapping[protocol.typeinfos[field[1]][0][1]] = class_name
|
||||
mapping[field[1]] = class_name
|
||||
|
||||
def detect_class_types(protocol):
|
||||
mapping = {}
|
||||
|
||||
mapping[protocol.replay_header_typeid] = 'Rogiel\StarReplay\Metadata\Header\Header'
|
||||
replay_header = protocol.typeinfos[protocol.replay_header_typeid]
|
||||
for f in replay_header[1][0]:
|
||||
if f[0] == "m_version":
|
||||
mapping[f[1]] = 'Rogiel\StarReplay\Metadata\Header\Version'
|
||||
if f[0] == "m_ngdpRootKey":
|
||||
mapping[f[1]] = 'Rogiel\StarReplay\Metadata\Header\Hash'
|
||||
|
||||
mapping[protocol.game_details_typeid] = 'Rogiel\StarReplay\Metadata\Match\MatchInformation'
|
||||
game_info = protocol.typeinfos[protocol.game_details_typeid]
|
||||
for f in game_info[1][0]:
|
||||
if f[0] == "m_playerList":
|
||||
playerList = f[1]
|
||||
playerList = protocol.typeinfos[playerList][1][0]
|
||||
mapping[playerList] = 'Rogiel\StarReplay\Metadata\Match\PlayerList'
|
||||
|
||||
playerList = protocol.typeinfos[playerList][1][1]
|
||||
mapping[playerList] = 'Rogiel\StarReplay\Entity\Player'
|
||||
|
||||
for t in protocol.typeinfos[playerList][1][0]:
|
||||
if t[0] == "m_toon":
|
||||
mapping[t[1]] = 'Rogiel\StarReplay\Entity\Toon'
|
||||
if t[0] == "m_color":
|
||||
mapping[t[1]] = 'Rogiel\StarReplay\Entity\Color'
|
||||
|
||||
if f[0] == "m_thumbnail":
|
||||
mapping[f[1]] = 'Rogiel\StarReplay\Entity\Thumbnail'
|
||||
|
||||
mapping[protocol.replay_initdata_typeid] = 'Rogiel\StarReplay\Metadata\Init\InitData'
|
||||
game_info = protocol.typeinfos[protocol.replay_initdata_typeid]
|
||||
for f in game_info[1][0]:
|
||||
if f[0] == "m_syncLobbyState":
|
||||
mapping[f[1]] = 'Rogiel\StarReplay\Metadata\Init\SyncLobbyState'
|
||||
for t in protocol.typeinfos[f[1]][1][0]:
|
||||
if t[0] == "m_userInitialData":
|
||||
mapping[t[1]] = 'Rogiel\StarReplay\Metadata\Init\UserInitialDataCollection'
|
||||
mapping[protocol.typeinfos[t[1]][1][1]] = 'Rogiel\StarReplay\Metadata\Init\UserInitialData'
|
||||
if t[0] == "m_gameDescription":
|
||||
mapping[t[1]] = 'Rogiel\StarReplay\Metadata\Init\GameDescription'
|
||||
for r in protocol.typeinfos[t[1]][1][0]:
|
||||
if r[0] == "m_gameOptions":
|
||||
mapping[r[1]] = 'Rogiel\StarReplay\Metadata\Init\GameOptions'
|
||||
|
||||
if t[0] == "m_lobbyState":
|
||||
mapping[t[1]] = 'Rogiel\StarReplay\Metadata\Init\LobbyState'
|
||||
|
||||
for index, type in enumerate(protocol.typeinfos):
|
||||
if type[0] == '_struct':
|
||||
for field in type[1][0]:
|
||||
if field[0] == 'x':
|
||||
mapping[index] = 'Rogiel\StarReplay\Entity\Point'
|
||||
|
||||
|
||||
for event in protocol.game_event_types.iteritems():
|
||||
event_name = event[1][1][11:]
|
||||
mapping[event[1][0]] = 'Rogiel\StarReplay\Event\Game\{0}'.format(event_name)
|
||||
if event_name == 'TriggerSoundLengthSyncEvent':
|
||||
sync_info = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_syncInfo')
|
||||
mapping[sync_info[1]] = 'Rogiel\StarReplay\Event\Game\Entity\SoundLengthSync'
|
||||
|
||||
if event_name == 'BankSignatureEvent':
|
||||
signature = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_signature')
|
||||
mapping[signature[1]] = 'Rogiel\StarReplay\Event\Game\Entity\BankSignature'
|
||||
|
||||
if event_name == 'ResourceRequestEvent':
|
||||
resources = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_resources')
|
||||
mapping[resources[1]] = 'Rogiel\StarReplay\Event\Game\Entity\ResourceRequest'
|
||||
|
||||
if event_name == 'SelectionDeltaEvent':
|
||||
delta = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_delta')
|
||||
struct = protocol.typeinfos[delta[1]]
|
||||
mapping[delta[1]] = 'Rogiel\StarReplay\Event\Game\Entity\SelectionDelta'
|
||||
|
||||
m_addSubgroups = find_struct_field(protocol, struct, 'm_addSubgroups')
|
||||
if m_addSubgroups:
|
||||
list = protocol.typeinfos[m_addSubgroups[1]]
|
||||
mapping[list[1][1]] = 'Rogiel\StarReplay\Event\Game\Entity\SubgroupUnit'
|
||||
|
||||
if event_name == 'ControlGroupUpdateEvent':
|
||||
mask = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_mask')
|
||||
mask = protocol.typeinfos[mask[1]]
|
||||
if mask[0] == '_choice':
|
||||
for choice in mask[1][1].iteritems():
|
||||
if choice[1][0] == 'Mask':
|
||||
mapping[choice[1][1]] = 'Rogiel\StarReplay\Event\Game\Entity\ControlGroupUpdateMask'
|
||||
if choice[1][0] == 'OneIndices':
|
||||
mapping[choice[1][1]] = 'Rogiel\StarReplay\Event\Game\Entity\ControlGroupUpdateOneIndices'
|
||||
if choice[1][0] == 'ZeroIndices':
|
||||
mapping[choice[1][1]] = 'Rogiel\StarReplay\Event\Game\Entity\ControlGroupUpdateZeroIndices'
|
||||
|
||||
# print protocol.typeinfos[mask[1]][1][0]
|
||||
# mask = protocol.typeinfos[protocol.typeinfos[mask[1]][1][0]]
|
||||
# if mask[0] == '_optional':
|
||||
# print mask
|
||||
# exit()
|
||||
# for key, option in protocol.typeinfos[mask[1]][2].iteritems():
|
||||
# print option
|
||||
# exit()
|
||||
|
||||
if event_name == 'CmdEvent':
|
||||
abil = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_abil')
|
||||
if abil:
|
||||
mapping[protocol.typeinfos[abil[1]][1][0]] = 'Rogiel\StarReplay\Event\Game\Entity\Ability'
|
||||
data = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_data')
|
||||
if data:
|
||||
for i, opt in protocol.typeinfos[data[1]][1][1].iteritems():
|
||||
if opt[0] == 'TargetUnit':
|
||||
mapping[opt[1]] = 'Rogiel\StarReplay\Event\Game\Entity\TargetUnit'
|
||||
|
||||
for event in protocol.message_event_types.iteritems():
|
||||
event_name = event[1][1][11:]
|
||||
mapping[event[1][0]] = 'Rogiel\StarReplay\Event\Message\{0}'.format(event_name)
|
||||
|
||||
if hasattr(protocol, 'tracker_event_types'):
|
||||
for event in protocol.tracker_event_types.iteritems():
|
||||
if event[1][1] == "NNet.Replay.Tracker.SPlayerStatsEvent":
|
||||
for type in protocol.typeinfos[event[1][0]][1][0]:
|
||||
if type[0] == "m_stats":
|
||||
mapping[type[1]] = 'Rogiel\StarReplay\Event\Tracker\PlayerStats'
|
||||
|
||||
if event[1][1] == "NNet.Replay.Tracker.SUnitPositionsEvent":
|
||||
for type in protocol.typeinfos[event[1][0]][1][0]:
|
||||
if type[0] == "m_items":
|
||||
mapping[type[1]] = 'Rogiel\StarReplay\Event\Tracker\UnitPositions'
|
||||
|
||||
event_name = event[1][1][21:]
|
||||
mapping[event[1][0]] = 'Rogiel\StarReplay\Event\Tracker\{0}'.format(event_name)
|
||||
|
||||
|
||||
return mapping
|
||||
167
bin/generator.py
Executable file
167
bin/generator.py
Executable file
@@ -0,0 +1,167 @@
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
|
||||
import tree as tree_generator
|
||||
import template as template_generator
|
||||
import class_mapping
|
||||
|
||||
sys.path.append('../s2protocol/')
|
||||
|
||||
current_path = os.path.dirname(os.path.realpath(__file__))
|
||||
output_directory = current_path + "/../src/Version"
|
||||
|
||||
all_versions = []
|
||||
protocols = glob.glob("../s2protocol/protocol*.py")
|
||||
for protocolFile in protocols:
|
||||
protocolBaseName = os.path.basename(protocolFile)
|
||||
protocolName = protocolBaseName[:-3]
|
||||
version = protocolBaseName[8:-3]
|
||||
all_versions.append(version)
|
||||
|
||||
protocol = __import__(protocolName)
|
||||
classes = class_mapping.detect_class_types(protocol)
|
||||
events = template_generator.generate_game_event_template(protocol)
|
||||
message_events = template_generator.generate_message_event_template(protocol)
|
||||
tracker_events = template_generator.generate_tracker_event_template(protocol)
|
||||
tree = tree_generator.generate_tree(protocol, classes)
|
||||
|
||||
if hasattr(protocol, 'replay_userid_typeid'):
|
||||
useridNode = protocol.replay_userid_typeid
|
||||
else:
|
||||
useridNode = protocol.replay_playerid_typeid
|
||||
|
||||
if hasattr(protocol, 'tracker_eventid_typeid'):
|
||||
tracker_eventid_typeid = protocol.tracker_eventid_typeid
|
||||
else:
|
||||
tracker_eventid_typeid = 'NULL'
|
||||
|
||||
template_vars = {
|
||||
'Version': version,
|
||||
'Tree': tree,
|
||||
'TimestampNode': protocol.svaruint32_typeid,
|
||||
'UserNode': useridNode,
|
||||
'GameEventNode': protocol.game_eventid_typeid,
|
||||
'MessageEventNode': protocol.message_eventid_typeid,
|
||||
'TrackerEventNode': tracker_eventid_typeid,
|
||||
'GameEvents': events,
|
||||
'MessageEvents': message_events,
|
||||
'TrackerEvents': tracker_events,
|
||||
'HeaderNode': protocol.replay_header_typeid,
|
||||
'GameDetailsNode': protocol.game_details_typeid,
|
||||
'InitDataNode': protocol.replay_initdata_typeid
|
||||
}
|
||||
|
||||
if not os.path.exists(output_directory):
|
||||
os.makedirs(output_directory)
|
||||
|
||||
template_generator.parse_template(current_path + "/Template/Version.php",
|
||||
"{0}/Version{1}.php".format(output_directory, version), template_vars)
|
||||
|
||||
all_versions_generated = "[\n"
|
||||
for version in all_versions:
|
||||
all_versions_generated += "\t\t\t{0} => 'Rogiel\StarReplay\Version\Version{0}',\n".format(version)
|
||||
all_versions_generated = all_versions_generated[:-2] + "\n\t\t]"
|
||||
template_vars = {
|
||||
'Versions': all_versions_generated,
|
||||
}
|
||||
template_generator.parse_template(current_path + "/Template/Versions.php", "{0}/Versions.php".format(output_directory), template_vars)
|
||||
|
||||
def extract_field_type(field):
|
||||
field_type = classes.get(field)
|
||||
if field_type:
|
||||
field_type = "\\"+field_type
|
||||
else:
|
||||
field_type_struct = protocol.typeinfos[field]
|
||||
if(field_type_struct[0] == '_int'):
|
||||
field_type = "integer"
|
||||
elif(field_type_struct[0] == '_blob'):
|
||||
field_type = "string"
|
||||
elif(field_type_struct[0] == '_array'):
|
||||
field_type = "array"
|
||||
elif(field_type_struct[0] == '_null'):
|
||||
field_type = "null"
|
||||
elif(field_type_struct[0] == '_bool'):
|
||||
field_type = "boolean"
|
||||
elif(field_type_struct[0] == '_struct'):
|
||||
logging.warn("Non mapped struct: %s. Falling back to array.", field_type_struct)
|
||||
field_type = "struct"
|
||||
elif(field_type_struct[0] == '_choice'):
|
||||
field_type = ""
|
||||
for choice in protocol.typeinfos[field][1][1].iteritems():
|
||||
field_type += "{0}|".format(extract_field_type(choice[1][1]))
|
||||
field_type = field_type[:-1]
|
||||
elif(field_type_struct[0] == '_optional'):
|
||||
field_type = "null|{0}".format(extract_field_type(protocol.typeinfos[field][1][0]))
|
||||
elif(field_type_struct[0] == '_bitarray'):
|
||||
field_type = "integer"
|
||||
elif(field_type_struct[0] == '_fourcc'):
|
||||
field_type = "integer"
|
||||
else:
|
||||
logging.error("Unknown type for field: %s. Ignoring type mapping.", field_type_struct)
|
||||
return field_type
|
||||
|
||||
|
||||
def parse_event_template(event, type, prefix, input, output_directory):
|
||||
event_name = event["event"][1][1][len(prefix):]
|
||||
full_name = event["event"][1][1]
|
||||
|
||||
fields = ""
|
||||
to_string = ""
|
||||
getters = ""
|
||||
for field in event["type"][1][0]:
|
||||
field_name = field[0][2:]
|
||||
camel_field_name = template_generator.capital_first_letter(field_name)
|
||||
field_type = extract_field_type(field[1])
|
||||
|
||||
if field_type:
|
||||
fields += "\t/** @var {0} */\n".format(field_type)
|
||||
fields += "\tpublic ${0};\n\n".format(field_name)
|
||||
|
||||
# if protocol.typeinfos[field[1]][0] == '_array':
|
||||
# exit()
|
||||
|
||||
to_string += "{0} = $this->{0}, ".format(field_name)
|
||||
if field_type:
|
||||
getters += "\t/** @return {0} */\n".format(field_type)
|
||||
getters += "\tpublic function get{0}() {{ return $this->{1}; }}\n\n".format(camel_field_name, field_name)
|
||||
|
||||
template_vars = {
|
||||
'Name': event_name,
|
||||
'FullName': full_name,
|
||||
'Type': type,
|
||||
'Fields': fields.rstrip('\n'),
|
||||
'ToString': to_string[:-2],
|
||||
'Getters': getters.rstrip('\n')
|
||||
}
|
||||
|
||||
template_generator.parse_template(input, "{0}/{1}.php".format(output_directory, event_name), template_vars)
|
||||
|
||||
for name, event in template_generator.all_game_events.iteritems():
|
||||
current_path = os.path.dirname(os.path.realpath(__file__))
|
||||
output_directory = current_path + "/../src/Event/Game"
|
||||
|
||||
if not os.path.exists(output_directory):
|
||||
os.makedirs(output_directory)
|
||||
|
||||
parse_event_template(event, 'Game', 'NNet.Game.S', current_path + "/Template/Event.php", output_directory)
|
||||
|
||||
for name, event in template_generator.all_message_events.iteritems():
|
||||
current_path = os.path.dirname(os.path.realpath(__file__))
|
||||
output_directory = current_path + "/../src/Event/Message"
|
||||
|
||||
if not os.path.exists(output_directory):
|
||||
os.makedirs(output_directory)
|
||||
|
||||
parse_event_template(event, 'Message', 'NNet.Game.S', current_path + "/Template/Event.php", output_directory)
|
||||
|
||||
for name, event in template_generator.all_tracker_events.iteritems():
|
||||
current_path = os.path.dirname(os.path.realpath(__file__))
|
||||
output_directory = current_path + "/../src/Event/Tracker"
|
||||
|
||||
if not os.path.exists(output_directory):
|
||||
os.makedirs(output_directory)
|
||||
|
||||
parse_event_template(event, 'Tracker', 'NNet.Replay.Tracker.S', current_path + "/Template/Event.php", output_directory)
|
||||
|
||||
67
bin/template.py
Normal file
67
bin/template.py
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
|
||||
all_game_events = {}
|
||||
def generate_game_event_template(protocol):
|
||||
generated = "[\n"
|
||||
for event in protocol.game_event_types.iteritems():
|
||||
name = event[1][1][11:]
|
||||
all_game_events[name] = {}
|
||||
all_game_events[name]["event"] = event
|
||||
all_game_events[name]["type"] = protocol.typeinfos[event[1][0]]
|
||||
template_vars = {
|
||||
'ID': event[0],
|
||||
'Name': name,
|
||||
'Node': event[1][0],
|
||||
}
|
||||
generated += "\t{ID} => {Node},\n".format(**template_vars)
|
||||
generated += "]"
|
||||
return generated
|
||||
|
||||
all_message_events = {}
|
||||
def generate_message_event_template(protocol):
|
||||
generated = "[\n"
|
||||
for event in protocol.message_event_types.iteritems():
|
||||
name = event[1][1][11:]
|
||||
all_message_events[name] = {}
|
||||
all_message_events[name]["event"] = event
|
||||
all_message_events[name]["type"] = protocol.typeinfos[event[1][0]]
|
||||
template_vars = {
|
||||
'ID': event[0],
|
||||
'Name': name,
|
||||
'Node': event[1][0],
|
||||
}
|
||||
generated += "\t{ID} => {Node},\n".format(**template_vars)
|
||||
generated += "]"
|
||||
return generated
|
||||
|
||||
all_tracker_events = {}
|
||||
def generate_tracker_event_template(protocol):
|
||||
if hasattr(protocol, 'tracker_event_types'):
|
||||
generated = "[\n"
|
||||
for event in protocol.tracker_event_types.iteritems():
|
||||
name = event[1][1][11:]
|
||||
all_tracker_events[name] = {}
|
||||
all_tracker_events[name]["event"] = event
|
||||
all_tracker_events[name]["type"] = protocol.typeinfos[event[1][0]]
|
||||
template_vars = {
|
||||
'ID': event[0],
|
||||
'Name': name,
|
||||
'Node': event[1][0],
|
||||
}
|
||||
generated += "\t{ID} => {Node},\n".format(**template_vars)
|
||||
generated += "]"
|
||||
return generated
|
||||
else:
|
||||
return "NULL"
|
||||
|
||||
|
||||
|
||||
def parse_template(input_file, output_file, vars):
|
||||
print(output_file)
|
||||
with open(input_file, 'r') as ftemp:
|
||||
templateString = ftemp.read()
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(templateString.format(**vars))
|
||||
|
||||
def capital_first_letter(s):
|
||||
return s[0].upper() + s[1:]
|
||||
111
bin/tree.py
Normal file
111
bin/tree.py
Normal file
@@ -0,0 +1,111 @@
|
||||
|
||||
def generate_integer(bounds, className):
|
||||
generated = "new IntegerNode({0}, {1}".format(bounds[0][1], bounds[0][0])
|
||||
if className:
|
||||
generated += ", '{0}'".format(className)
|
||||
return generated + ")"
|
||||
|
||||
def generate_choice(tagger, choices, className):
|
||||
generated = "new ChoiceNode(new IntegerNode({0}), [\n".format(tagger[1])
|
||||
for index, choice in choices.iteritems():
|
||||
generated += "\t{tag} => {index},\n".format(tag = index, index = choice[1])
|
||||
generated += "]"
|
||||
if className:
|
||||
generated += ", '{0}'".format(className)
|
||||
return generated + ")"
|
||||
|
||||
def generate_struct(members, className):
|
||||
generated = "new StructNode([\n"
|
||||
for member in members[0]:
|
||||
if member:
|
||||
member_name = member[0]
|
||||
if member_name.startswith('m_'):
|
||||
member_name = member[0][2:]
|
||||
generated += "\t\"{name}\" => array('type' => {index}, 'tag' => {tag}),\n".format(name = member_name, index = member[1], tag = member[2])
|
||||
|
||||
generated += "]"
|
||||
if className:
|
||||
generated += ",\n\t'{0}'\n".format(className)
|
||||
generated += ")"
|
||||
return generated
|
||||
|
||||
def generate_optional(bounds, className):
|
||||
generated = "new OptionalNode({0}".format(bounds[0])
|
||||
if className:
|
||||
generated += ", '{0}'".format(className)
|
||||
return generated + ")"
|
||||
|
||||
def generate_blob(bounds, className):
|
||||
generated = "new BlobNode(new IntegerNode({0}, {1})".format(bounds[0][1], bounds[0][0])
|
||||
if className:
|
||||
generated += ", '{0}'".format(className)
|
||||
return generated + ")"
|
||||
|
||||
def generate_bool(className):
|
||||
generated = "new BooleanNode("
|
||||
if className:
|
||||
generated += ", '{0}'".format(className)
|
||||
return generated + ")"
|
||||
|
||||
def generate_array(bounds, className):
|
||||
generated = "new ArrayNode(\n"
|
||||
generated += "\tnew IntegerNode({size}, {constant}),\n".format(size=bounds[0][1], constant=bounds[0][0])
|
||||
generated += "\t{0}".format(bounds[1])
|
||||
|
||||
if className:
|
||||
generated += ",\n\t'{0}'\n".format(className)
|
||||
|
||||
generated += "\n)"
|
||||
return generated
|
||||
|
||||
def generate_bitarray(bounds, className):
|
||||
generated = "new BitArrayNode(\n"
|
||||
generated += "\tnew IntegerNode({size}, {constant})\n".format(size=bounds[0][1], constant=bounds[0][0])
|
||||
if className:
|
||||
generated += ",\n\t'{0}'".format(className)
|
||||
generated += ")"
|
||||
return generated
|
||||
|
||||
def generate_null(className):
|
||||
return "new NullNode()"
|
||||
|
||||
def generate_fourcc(className):
|
||||
generated = "new FourCCNode("
|
||||
if className:
|
||||
generated += ", '{0}'".format(className)
|
||||
generated += ")"
|
||||
return generated
|
||||
|
||||
def generate_tree(protocol, classes):
|
||||
nodes = []
|
||||
for index, typeinfo in enumerate(protocol.typeinfos):
|
||||
if typeinfo[0] == "_int":
|
||||
generated = generate_integer(typeinfo[1], classes.get(index))
|
||||
elif typeinfo[0] == "_choice":
|
||||
generated = generate_choice(typeinfo[1][0], typeinfo[1][1], classes.get(index))
|
||||
elif typeinfo[0] == "_struct":
|
||||
generated = generate_struct(typeinfo[1], classes.get(index))
|
||||
elif typeinfo[0] == "_optional":
|
||||
generated = generate_optional(typeinfo[1], classes.get(index))
|
||||
elif typeinfo[0] == "_blob":
|
||||
generated = generate_blob(typeinfo[1], classes.get(index))
|
||||
elif typeinfo[0] == "_bool":
|
||||
generated = generate_bool(classes.get(index))
|
||||
elif typeinfo[0] == "_array":
|
||||
generated = generate_array(typeinfo[1], classes.get(index))
|
||||
elif typeinfo[0] == "_bitarray":
|
||||
generated = generate_bitarray(typeinfo[1], classes.get(index))
|
||||
elif typeinfo[0] == "_fourcc":
|
||||
generated = generate_fourcc(classes.get(index))
|
||||
elif typeinfo[0] == "_null":
|
||||
generated = generate_null(classes.get(index))
|
||||
else:
|
||||
print "Node %s unknown!" % typeinfo[0]
|
||||
exit()
|
||||
nodes.append(generated)
|
||||
|
||||
tree = "[\n"
|
||||
for index, node in enumerate(nodes):
|
||||
tree += "{index} => {code},\n".format(index=index, code = node)
|
||||
tree += "]\n"
|
||||
return tree
|
||||
Reference in New Issue
Block a user