-
Notifications
You must be signed in to change notification settings - Fork 15
/
ReplicationInstance.go
113 lines (98 loc) · 3.38 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
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) (*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
}
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) 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
}
return stream.WriteObject(instance.Parent, writer)
}