-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathArgumentUtils.cs
More file actions
157 lines (134 loc) · 6.29 KB
/
ArgumentUtils.cs
File metadata and controls
157 lines (134 loc) · 6.29 KB
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
154
155
156
157
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using MultiplayerMod.Multiplayer.Objects.Extensions;
using MultiplayerMod.Multiplayer.Objects.Reference;
using MultiplayerMod.Platform.Common.Network.Messaging.Surrogates;
using UnityEngine;
namespace MultiplayerMod.Multiplayer.Commands;
public static class ArgumentUtils {
public static object?[] WrapObjects(object?[] objects) {
return objects.Select(WrapObject).ToArray();
}
public static object?[] UnWrapObjects(object?[] objects) {
return objects.Select(UnWrapObject).ToArray();
}
public static object? WrapObject(object? obj) {
return obj switch {
null => null,
GameObject gameObject => gameObject.GetReference(),
KMonoBehaviour kMonoBehaviour => kMonoBehaviour.GetReference(),
Delegate action => new DelegateRef(action.GetType(), WrapObject(action.Target), action.Method),
FetchOrder2 order2 => new FetchOrder2Ref(order2),
_ => obj.GetType().IsSerializable || SerializationSurrogates.HasSurrogate(obj.GetType())
? obj
: throw new Exception($"Type {obj.GetType()} is not serializable")
};
}
public static object? UnWrapObject(object? obj) => obj is Reference reference ? reference.Resolve() : obj;
// TODO: Mitigate RCE
[Serializable]
public record DelegateRef(
Type DelegateType,
object? Target,
MethodInfo MethodInfo
) : Reference {
public object Resolve() {
return Delegate.CreateDelegate(
DelegateType,
UnWrapObject(Target),
MethodInfo
);
}
}
[Serializable]
public record FetchOrder2Ref(
HashSet<Tag> Tags,
FetchList2Ref? List2Ref,
ComponentReference<CreatureDeliveryPoint>? CreatureDeliveryPointReference
) : Reference {
public FetchOrder2Ref(FetchOrder2 fetchOrder2) : this(
fetchOrder2.Tags,
fetchOrder2.OnComplete.Target is FetchList2 fetchList2 ? new FetchList2Ref(fetchList2) : null,
fetchOrder2.OnComplete.Target is CreatureDeliveryPoint creatureDeliveryPoint
? creatureDeliveryPoint.GetReference()
: null
) { }
public object Resolve() {
var list = List2Ref?.GetFetchList2();
var creatureDeliveryPoint = CreatureDeliveryPointReference?.Resolve();
var fetchOrders = list?.FetchOrders ?? creatureDeliveryPoint?.fetches;
if (fetchOrders == null) {
return new FetchOrder2(null, Tags, FetchChore.MatchCriteria.MatchTags, null, null, null, 1);
}
return fetchOrders.Single(order => order.Tags.SequenceEqual(Tags));
}
public virtual bool Equals(FetchOrder2Ref? other) {
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Tags.SequenceEqual(other.Tags) && Equals(List2Ref, other.List2Ref) && Equals(
CreatureDeliveryPointReference,
other.CreatureDeliveryPointReference
);
}
public override int GetHashCode() {
var hashCode = Tags.GetHashCode();
hashCode = hashCode * 397 ^ (List2Ref != null ? List2Ref.GetHashCode() : 0);
hashCode = hashCode * 397 ^ (CreatureDeliveryPointReference != null
? CreatureDeliveryPointReference.GetHashCode()
: 0);
return hashCode;
}
}
[Serializable]
public record FetchList2Ref(
ComponentReference<Storage> StorageReference,
ChoreType ComplexFabricatorChoreType,
StateMachineReference? StateMachineReference,
ComponentReference<ComplexFabricator>? ComplexFabricatorReference,
ComponentReference<Constructable>? ConstructableReference,
FilteredStorageRef? FilteredStorageReference,
ComponentReference<ManualDeliveryKG>? ManualDeliveryKGReference
) {
public FetchList2Ref(FetchList2 fetchList2) : this(
fetchList2.Destination.GetReference(),
fetchList2.choreType,
fetchList2.OnComplete.Target is StateMachine.Instance smi ? smi.GetReference() : null,
fetchList2.OnComplete.Target is ComplexFabricator complexFabricator
? complexFabricator.GetReference()
: null,
fetchList2.OnComplete.Target is Constructable constructable ? constructable.GetReference() : null,
fetchList2.OnComplete.Target is FilteredStorage storage ? new FilteredStorageRef(storage) : null,
fetchList2.OnComplete.Target is ManualDeliveryKG manualDeliveryKg ? manualDeliveryKg.GetReference() : null
) { }
public FetchList2? GetFetchList2() {
var fetchListList = ComplexFabricatorReference?.Resolve().fetchListList ??
StateMachineReference?.Resolve()?.dataTable.OfType<FetchList2>().ToList();
return fetchListList?.Single(
fetchList => Equals(fetchList.Destination.GetReference(), StorageReference) &&
fetchList.choreType == ComplexFabricatorChoreType
) ??
ConstructableReference?.Resolve().fetchList ??
FilteredStorageReference?.GetFilteredStorage().fetchList ??
ManualDeliveryKGReference?.Resolve().fetchList;
}
}
[Serializable]
public record FilteredStorageRef(ComponentReference RootReference) {
private static BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
public FilteredStorageRef(FilteredStorage filteredStorage) : this(
filteredStorage.root.GetReference()
) { }
public FilteredStorage GetFilteredStorage() {
var root = RootReference.Resolve();
var type = root!.GetType();
var field = type.GetField("storageFilter", bindingFlags) ??
type.GetField("filteredStorage", bindingFlags) ??
type.GetField("foodStorageFilter", bindingFlags);
return (FilteredStorage) field!.GetValue(root);
}
}
[Serializable]
public record GameStateMachineFetchListRef;
}