forked from Arisstath/roblox-dissector
/
ReplicationInstance.go
153 lines (136 loc) · 4.13 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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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 {
switch typeID {
case PropertyTypeString:
return false
case PropertyTypeProtectedString0:
return false
case PropertyTypeProtectedString3:
return false
case PropertyTypeInstance:
return false
case PropertyTypeContent:
return false
case PropertyTypeSystemAddress:
return false
case PropertyTypeLuauString:
return false
default:
return true
}
}
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.Context())
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 err != nil {
return nil, err
}
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.Context())
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 {
// create a dummy instance for DataModel
parent, err := context.InstancesByReference.CreateInstance(reference)
if err != nil {
return nil, err
}
parent.ClassName = "DataModel"
repInstance.Parent = parent
} else {
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.Context())
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.Context())
}