/
ReplicationInstance.go
127 lines (110 loc) · 3.63 KB
/
ReplicationInstance.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package peer
import (
"errors"
"fmt"
"github.com/Gskartwii/roblox-dissector/datamodel"
"github.com/robloxapi/rbxfile"
)
// ReplicationInstance describes a network instance creation packet
type ReplicationInstance struct {
Instance *datamodel.Instance
Properties map[string]rbxfile.Value
Parent *datamodel.Instance
Schema *NetworkInstanceSchema
DeleteOnDisconnect bool
}
func is2ndRoundType(typeID uint8) bool {
id := uint32(typeID)
return ((id-3) > 0x1F || ((1<<(id-3))&uint32(0xC200000F)) == 0) && (id != 1) // thank you ARM compiler for optimizing this <3
}
func decodeReplicationInstance(reader PacketReader, thisStream instanceReader, layers *PacketLayers, deferred deferredStrings, readDefers bool) (*ReplicationInstance, error) {
var err error
repInstance := &ReplicationInstance{
Properties: make(map[string]rbxfile.Value),
}
var reference datamodel.Reference
context := reader.Context()
reference, err = thisStream.ReadObject(reader)
if err != nil {
return nil, errors.New("while parsing self: " + err.Error())
}
if reference.IsNull {
return nil, errors.New("self is nil in decodeReplicationInstance")
}
thisInstance, err := context.InstancesByReference.CreateInstance(reference)
if err != nil {
return nil, err
}
repInstance.Instance = thisInstance
schemaIDx, err := thisStream.readUint16BE()
if int(schemaIDx) > len(context.NetworkSchema.Instances) {
return repInstance, fmt.Errorf("class idx %d is higher than %d", schemaIDx, len(context.NetworkSchema.Instances))
}
schema := context.NetworkSchema.Instances[schemaIDx]
repInstance.Schema = schema
thisInstance.ClassName = schema.Name
layers.Root.Logger.Println("will parse", reference.String(), schema.Name, len(schema.Properties))
repInstance.DeleteOnDisconnect, err = thisStream.readBoolByte()
if err != nil {
return repInstance, err
}
err = thisStream.ReadProperties(schema.Properties, repInstance.Properties, reader, deferred)
if err != nil {
return repInstance, err
}
if readDefers {
err = thisStream.resolveDeferredStrings(deferred)
if err != nil {
return repInstance, err
}
}
reference, err = thisStream.ReadObject(reader)
if err != nil {
return repInstance, errors.New("while parsing parent: " + err.Error())
}
if len(reference.String()) > 0x50 {
layers.Root.Logger.Println("Parent: (invalid), ", len(reference.String()))
} else {
layers.Root.Logger.Println("Parent: ", reference.String())
}
parent, err := context.InstancesByReference.TryGetInstance(reference)
if err != nil {
// service parents aren't excepted to exist
if err == datamodel.ErrInstanceDoesntExist && thisInstance.IsService {
return repInstance, nil
}
return repInstance, err
}
repInstance.Parent = parent
return repInstance, nil
}
// Serialize serializes an instance creation packet to its network format
func (instance *ReplicationInstance) Serialize(writer PacketWriter, stream instanceWriter, deferred writeDeferredStrings, writeDefers bool) error {
var err error
if instance == nil || instance.Instance == nil {
return errors.New("self is nil in serialize repl inst")
}
err = stream.WriteObject(instance.Instance, writer)
if err != nil {
return err
}
err = stream.writeUint16BE(instance.Schema.NetworkID)
if err != nil {
return err
}
err = stream.writeBoolByte(instance.DeleteOnDisconnect)
if err != nil {
return err
}
err = stream.WriteProperties(instance.Schema.Properties, instance.Properties, writer, deferred)
if err != nil {
return err
}
if writeDefers {
err = stream.resolveDeferredStrings(deferred)
if err != nil {
return err
}
}
return stream.WriteObject(instance.Parent, writer)
}