Skip to content

Instantly share code, notes, and snippets.

@pollend
Last active July 12, 2021 05:27
Show Gist options
  • Save pollend/ae35444ce77b1690b18fe18be3852c59 to your computer and use it in GitHub Desktop.
Save pollend/ae35444ce77b1690b18fe18be3852c59 to your computer and use it in GitHub Desktop.
option java_package = "org.terasology.protobuf";
option java_outer_classname = "EntityData";
option optimize_for = SPEED;
message Value {
repeated double double = 1 [packed=true];
repeated float float = 2 [packed=true];
repeated sint32 integer = 3 [packed=true];
repeated sint64 long = 4 [packed=true];
repeated bool boolean = 5 [packed=true];
repeated string string = 6;
optional bytes bytes = 7;
repeated Value value = 8;
repeated NameValue name_value = 9; // For string maps
// repeated ValuePair value_value = 10; // For other maps
extensions 5000 to max;
}
/*
message ValuePair {
optional Value key = 1;
optional Value value = 2;
}
*/
message NameValue {
optional string name = 1;
optional Value value = 2;
optional int32 name_index = 3;
}
message Component {
optional int32 type_index = 1; // Index of the type, if contained in a world with component_classes table
optional string type = 15; // The name of the type. Not needed if index provided
repeated NameValue field = 2;
extensions 5000 to max;
}
message Entity {
optional int64 id = 1;
repeated Component component = 2;
repeated int32 removed_component_index = 3 [packed=true];
optional string parent_prefab = 4;
optional bool alwaysRelevant = 5;
optional int64 owner = 6;
repeated string removed_component = 15;
enum Scope {
GLOBAL = 0;
SECTOR = 1;
CHUNK = 2;
}
optional Scope scope = 7;
extensions 5000 to max;
}
message PackedEntity {
optional int64 id = 1;
repeated int32 componentId = 2 [packed=true];
optional bytes componentFieldCounts = 3;
optional bytes fieldIds = 4;
repeated Value fieldValue = 5;
repeated int32 removedComponent = 6 [packed=true];
optional int64 owner = 7;
optional string parentPrefabUri = 16;
extensions 5000 to max;
}
message Prefab {
optional int32 name_index = 1;
repeated Component component = 2;
repeated int32 deprecated = 3 [packed=true];
optional bool persisted = 4 [default=true];
repeated string removedComponent = 5;
optional bool alwaysRelevant = 6;
optional string name = 15;
optional string parent_name = 16;
extensions 5000 to max;
}
message Event {
optional int32 type = 1;
optional bytes fieldIds = 2;
repeated Value fieldValue = 3;
extensions 5000 to max;
}
message EntityStore {
repeated Entity entity = 1;
repeated string component_class = 3;
// These are paired, with entityNamed referencing entity id
repeated string entityName = 2;
repeated int64 entityNamed = 4 [packed = true];
extensions 5000 to max;
}
enum StoreType {
PlayerStoreType = 1;
ChunkStoreType = 2;
}
message PlayerStore {
optional EntityStore store = 1;
optional float characterPosX = 15;
optional float characterPosY = 16;
optional float characterPosZ = 17;
optional bool hasCharacter = 18;
extensions 5000 to max;
}
message ChunkStore {
optional EntityStore store = 1;
optional sint32 x = 2;
optional sint32 y = 3;
optional sint32 z = 4;
optional int32 deprecated_data_3 = 5;
optional bytes deprecated_data_4 = 6;
optional bytes deprecated_data_1 = 7;
optional bytes deprecated_data_2 = 8;
optional bytes deprecated_data_5 = 9;
optional RunLengthEncoding8 deprecated_data_6 = 11;
optional RunLengthEncoding16 deprecated_data_7 = 12;
optional RunLengthEncoding16 block_data = 10;
repeated RunLengthEncoding16 extra_data = 13;
extensions 5000 to max;
}
message RunLengthEncoding16 {
repeated sint32 runLengths = 1 [packed=true];
repeated sint32 values = 2 [packed=true];
extensions 5000 to max;
}
message RunLengthEncoding8 {
repeated sint32 runLengths = 1 [packed=true];
optional bytes values = 2;
extensions 5000 to max;
}
message GlobalStore {
repeated Entity entity = 1;
repeated Prefab prefab = 2;
repeated string component_class = 3;
optional int64 next_entity_id = 16;
repeated int64 deprecated_data_17 = 17 [packed=true];
repeated string prefab_name = 18; // Table of prefabs, the index of which corresponds to Prefab's type_index
// deprecated repeated entityStoreMetadata deprecated_data_19 = 19;
extensions 5000 to max;
}
import "EntityData.proto";
option java_package = "org.terasology.protobuf";
option java_outer_classname = "NetData";
option optimize_for = SPEED;
message NetMessage {
repeated ChunkStore chunkInfo = 2;
repeated InvalidateChunkMessage invalidateChunk = 3;
repeated BlockChangeMessage blockChange = 4;
repeated CreateEntityMessage createEntity = 5;
repeated RemoveEntityMessage removeEntity = 6;
repeated UpdateEntityMessage updateEntity = 7;
repeated EventMessage event = 8;
optional int64 time = 9;
repeated ExtraDataChangeMessage extraDataChange = 11;
optional ServerInfoRequest serverInfoRequest = 15;
optional ServerInfoMessage serverInfo = 16;
repeated BlockFamilyRegisteredMessage blockFamilyRegistered = 17;
optional JoinMessage join = 18;
repeated ModuleRequest moduleRequest = 19;
optional ModuleDataHeader moduleDataHeader = 20;
optional ModuleData moduleData = 21;
optional JoinCompleteMessage joinComplete = 22;
// Authentication
optional HandshakeHello handshakeHello = 100;
optional NewIdentityRequest newIdentityRequest = 101;
optional ProvisionIdentity provisionIdentity = 102;
optional HandshakeVerification handshakeVerification = 103;
extensions 5000 to max;
}
message HandshakeHello {
optional bytes random = 1;
optional Certificate certificate = 2;
optional sint64 timestamp = 3;
extensions 5000 to max;
}
message NewIdentityRequest {
optional bytes preMasterSecret = 1;
optional bytes random = 2;
extensions 5000 to max;
}
message ProvisionIdentity {
optional bytes encryptedCertificates = 1;
extensions 5000 to max;
}
message CertificateSet {
optional Certificate publicCertificate = 1;
optional bytes privateExponent = 2;
extensions 5000 to max;
}
message HandshakeVerification {
optional bytes signature = 1;
extensions 5000 to max;
}
message Certificate {
optional string id = 1;
optional bytes modulus = 2;
optional bytes exponent = 3;
optional bytes signature = 4;
extensions 5000 to max;
}
message BlockFamilyRegisteredMessage {
repeated string blockUri = 1;
repeated int32 blockId = 2;
extensions 5000 to max;
}
message InvalidateChunkMessage {
optional Vector3iData pos = 1;
extensions 5000 to max;
}
message BlockChangeMessage {
optional Vector3iData pos = 1;
optional int32 newBlock = 2;
extensions 5000 to max;
}
message ExtraDataChangeMessage {
optional int32 index = 1;
optional Vector3iData pos = 2;
optional int32 newData = 3;
extensions 5000 to max;
}
message Vector3iData {
optional int32 x = 1;
optional int32 y = 2;
optional int32 z = 3;
}
message ServerInfoRequest {
extensions 5000 to max;
}
message JoinMessage {
optional string name = 1;
optional string version = 2;
optional sint32 viewDistanceLevel = 3;
optional Color color = 4;
extensions 5000 to max;
}
message Color {
optional uint32 rgba = 1;
}
message JoinCompleteMessage {
optional int32 clientId = 1;
extensions 5000 to max;
}
message ServerInfoMessage {
repeated ModuleInfo module = 1;
repeated sint32 blockId = 2 [packed=true];
repeated string blockName = 3;
repeated SerializationInfo component = 4;
repeated SerializationInfo event = 5;
repeated int32 assetId = 6 [packed=true];
repeated string assetUri = 7;
repeated string registerBlockFamily = 8;
repeated WorldInfo worldInfo = 9;
optional string errorMessage = 12;
optional string version = 15;
optional string gameName = 16;
optional int64 time = 17;
optional float reflectionHeight = 18;
optional string MOTD = 19;
optional int32 onlinePlayersAmount = 20;
extensions 5000 to max;
}
message WorldInfo {
optional string title = 1;
optional int64 time = 2;
extensions 5000 to max;
}
message SerializationInfo {
optional string name = 1;
optional int32 id = 2;
repeated string fieldName = 3;
optional bytes fieldIds = 4;
extensions 5000 to max;
}
message ModuleInfo {
optional string moduleId = 1;
optional string moduleVersion = 2;
extensions 5000 to max;
}
message ModuleRequest {
optional string moduleId = 1;
extensions 5000 to max;
}
message ModuleDataHeader {
optional string id = 1;
optional string version = 2;
optional int64 size = 3;
optional string error = 15;
extensions 5000 to max;
}
message ModuleData {
optional bytes module = 1;
extensions 5000 to max;
}
message ModuleSendError {
optional string message = 1;
extensions 5000 to max;
}
message CreateEntityMessage {
optional PackedEntity entity = 1;
optional Vector3iData blockPos = 2;
extensions 5000 to max;
}
message UpdateEntityMessage {
optional PackedEntity entity = 1;
optional int32 netId = 2;
extensions 5000 to max;
}
message RemoveEntityMessage {
optional int32 netId = 1;
extensions 5000 to max;
}
message EventMessage {
optional int32 targetId = 1;
optional Event event = 2;
optional Vector3iData targetBlockPos = 3;
extensions 5000 to max;
}
from os import mkdir, write
import lz4.block
import struct
import os
import argparse
parser = argparse.ArgumentParser(description='Decode Terasology packet stream.')
parser.add_argument("-i", "--input", type=str, help='input packet')
parser.add_argument("-o", "--output", type=str, help='output folder' )
args = parser.parse_args()
if not os.path.exists(args.output):
mkdir(args.output)
def decode_unsigned_leb128(ff):
pair_count = 0
result = 0
while True:
single_byte = ff.read(1)[0]
# If first bit is 1
if single_byte & 0b10000000 == 0:
break
# Remove first bit
single_byte = single_byte & 0b01111111
# Push number of bits we already have calculated
single_byte = single_byte << (pair_count * 7)
# Merge byte with result
result = result | single_byte
pair_count = pair_count + 1
# Merge last byte with result
single_byte = single_byte << (pair_count * 7)
result = result | single_byte
return result
try:
with open(os.path.join(args.output,"stream.proto"),'wb') as protoStream:
with open(args.input, "rb") as file:
# ll = 0
while True:
# ll += 1
size = struct.unpack('!I', b'\x00' + file.read(3))[0]
if(size == 0):
continue
print("decoding packet -- " + str(size))
print(struct.unpack('!8c', file.read(8)))
token, compress, uncompress, cheksum = struct.unpack('<bIII', file.read(1 + 4 + 4 + 4))
payload = lz4.block.decompress(file.read(compress), uncompressed_size=uncompress)
protoStream.write(payload)
except Exception as inst:
print(inst)
with open(os.path.join(args.output, "stream.proto"), "rb") as file:
i = 0
while True:
length = decode_unsigned_leb128(file)
result = file.read(length)
protofile = os.path.join(args.output, "packet" + str(i) + ".proto")
with open(protofile, "wb") as pkt:
pkt.write(result)
print(length)
os.system("protoc --decode NetMessage NetMessage.proto < %s > %s" % (protofile, os.path.join(args.output, "packet_formatted" + str(i) + ".txt")))
i += 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment