-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
Copy pathshared_resources.dm
269 lines (201 loc) · 8.15 KB
/
shared_resources.dm
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/datum/ai_shared_resources
///Where our RAM is coming from. Associative array where the network is the key
var/ram_sources = list()
///Where our CPU is coming from. Associative array where the network is the key
var/cpu_sources = list()
///Where our CPU is assigned to. Associative where either an AI or a network has values. Max total value = 1 (100%)
var/list/cpu_assigned = list()
///Where our CPU is assigned to. Associative where either an AI or a network has values
var/list/ram_assigned = list()
///List of all networks we are connected to
var/list/networks = list()
///How much RAM we had before updating resources
var/previous_ram = 0
///If resource allocation can only be changed physically at a console by a human
var/human_lock = FALSE
/datum/ai_shared_resources/New(network_assigned_cpu, network_assigned_ram, datum/ai_network/split_network, datum/ai_network/starting_network, _human_lock = FALSE)
if((network_assigned_ram || network_assigned_cpu) && split_network)
ram_assigned = network_assigned_ram
cpu_assigned = network_assigned_cpu
if(split_network)
split_network.resources = src
networks |= split_network
update_resources()
if(starting_network)
starting_network.resources = src
networks |= starting_network
for(var/datum/ai_network/AN in networks)
AN.rebuild_remote()
START_PROCESSING(SSobj, src)
human_lock = _human_lock
/datum/ai_shared_resources/Destroy(network_assigned_cpu, network_assigned_ram, datum/ai_network/split_network, datum/ai_network/starting_network)
STOP_PROCESSING(SSobj, src)
. = ..()
/datum/ai_shared_resources/process()
for(var/datum/ai_network/net in networks)
net.process()
//Networks automatically use their unspent CPU to research, this just catches cluster unassigned CPU. Local clusters can have their points boosted by local AIs
var/unused_cpu = 1 - total_cpu_assigned()
var/research_points = max(round(AI_RESEARCH_PER_CPU * (unused_cpu * total_cpu())), 0)
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_AI = research_points))
/datum/ai_shared_resources/proc/total_cpu_assigned()
var/total = 0
for(var/AI in cpu_assigned)
total += cpu_assigned[AI]
return total
/datum/ai_shared_resources/proc/total_ram_assigned()
var/total = 0
for(var/AI in ram_assigned)
total += (ram_assigned[AI])
return total
/datum/ai_shared_resources/proc/total_cpu()
var/total = 0
for(var/C in cpu_sources)
total += cpu_sources[C]
return total
/datum/ai_shared_resources/proc/total_ram()
var/total = 0
for(var/C in ram_sources)
total += ram_sources[C]
return total
/datum/ai_shared_resources/proc/update_resources()
previous_ram = total_ram()
ram_sources = list()
cpu_sources = list()
for(var/datum/ai_network/N in networks)
ram_sources[N] += N.total_ram()
cpu_sources[N] += N.total_cpu()
update_allocations()
/datum/ai_shared_resources/proc/add_resource(datum/ai_shared_resources/new_resources)
for(var/RU in new_resources.ram_assigned)
ram_assigned[RU] = new_resources.ram_assigned[RU]
for(var/CU in cpu_assigned) //We split the CPUs 50/50
cpu_assigned[CU] = round((cpu_assigned[CU] * 0.5) * 100) / 100
for(var/CU in new_resources.cpu_assigned)
cpu_assigned[CU] = round((new_resources.cpu_assigned[CU] * 0.5) * 100) / 100
for(var/datum/ai_network/N in new_resources.networks)
networks |= N
N.resources = src
update_resources()
update_allocations()
qdel(new_resources)
/datum/ai_shared_resources/proc/split_resources(datum/ai_network/split_network)
var/network_ram_assign = list()
var/network_cpu_assign = list()
var/split_network_cpu = 0
var/network_ais = split_network.ai_list
for(var/A in cpu_assigned)
if(A in network_ais || A == split_network)
network_cpu_assign[A] = cpu_assigned[A]
split_network_cpu += cpu_assigned[A]
cpu_assigned[A] = 0
//Normalize CPU so 100% is used in the new network if 100% was used in total before
var/total_usage = total_cpu_assigned() //We normalise around this value, so the split network CPU usage will (approximately) end up at this too
if(split_network_cpu)
for(var/A in network_cpu_assign)
var/split_usage = network_cpu_assign[A] / split_network_cpu
network_cpu_assign[A] = 1 * round(split_usage, 0.01)
//We do the same for the network we leave behid
if(total_usage)
for(var/A in cpu_assigned)
var/split_usage = cpu_assigned[A] / total_usage
cpu_assigned[A] = 1 * round(split_usage, 0.01)
//Not needed for RAM since it's not a percentage
for(var/A in ram_assigned)
if(A in network_ais || A == split_network)
network_ram_assign[A] = ram_assigned[A]
ram_assigned[A] = 0
networks -= split_network
update_resources()
new /datum/ai_shared_resources(network_cpu_assign, network_ram_assign, split_network, _human_lock = human_lock)
if(!length(networks))
qdel(src)
/datum/ai_shared_resources/proc/update_allocations()
//Do we have the same amount or more RAM than before? Do nothing
var/total_ram = total_ram()
if(total_ram >= previous_ram)
return
//Find out how much is actually assigned. We can have more total_cpu than the sum of cpu_assigned. Same with RAM
var/total_assigned_ram = total_ram_assigned()
//If we have less assigned ram than we have cpu and ram, just return, everything is fine.
if(total_assigned_ram < total_ram)
return
//Copy the lists of assigned resources so we don't manipulate the list prematurely.
var/list/ram_assigned_copy = ram_assigned.Copy()
//List of touched AIs so we can notify them at the end.
var/list/affected_AIs = list()
if(total_assigned_ram > total_ram)
var/needed_amount = total_assigned_ram - total_ram
for(var/A in ram_assigned_copy)
if(isAI(A))
var/mob/living/silicon/ai/AI = A
if((ram_assigned_copy[AI]) >= needed_amount)
ram_assigned_copy[AI] -= needed_amount
total_assigned_ram -= needed_amount
affected_AIs |= AI
break
else if(ram_assigned_copy[AI])
var/amount = ram_assigned_copy[AI]
ram_assigned_copy[AI] -= amount
affected_AIs |= AI
needed_amount -= amount
total_assigned_ram -= amount
if(total_ram >= total_assigned_ram)
break
else //If we're not an AI we are a network, networks have no programs to stop (for now)
if((ram_assigned_copy[A]) >= needed_amount)
ram_assigned_copy[A] -= needed_amount
total_assigned_ram -= needed_amount
break
else if(ram_assigned_copy[A])
var/amount = ram_assigned_copy[A]
ram_assigned_copy[A] -= amount
needed_amount -= amount
total_assigned_ram -= amount
if(total_ram >= total_assigned_ram)
break
//Set the actual values of the assigned to our manipulated copies. Bypass helper procs as we assume we're correct.
ram_assigned = ram_assigned_copy
to_chat(affected_AIs, span_warning("You have been deducted memory capacity. Please contact your network administrator if you believe this to be an error."))
/datum/ai_shared_resources/proc/set_cpu(target, amount)
if(!istype(target, /datum/ai_network) && !isAI(target))
stack_trace("Attempted to set_cpu with non-AI/network target! T: [target]")
return
if(!target)
return
if(amount > 1 || amount < 0)
return
cpu_assigned[target] = amount
update_allocations()
/datum/ai_shared_resources/proc/add_ram(target, amount)
if(!target || !amount)
return
if(!istype(target, /datum/ai_network) && !isAI(target))
stack_trace("Attempted to add_ram with non-AI/network target! T: [target]")
return
ram_assigned[target] += amount
update_allocations()
/datum/ai_shared_resources/proc/remove_ram(target, amount)
if(!target || !amount)
return
if(!istype(target, /datum/ai_network) && !isAI(target))
stack_trace("Attempted to remove_ram with non-AI/network target! T: [target]")
return
if(ram_assigned[target] - amount < 0)
ram_assigned[target] = 0
else
ram_assigned[target] -= amount
update_allocations()
/datum/ai_shared_resources/proc/clear_ai_resources(target)
if(!target)
return
if(!istype(target, /datum/ai_network) && !isAI(target))
stack_trace("Attempted to clear_ai_resources with non-AI/network target! T: [target]")
return
remove_ram(target, ram_assigned[target])
cpu_assigned[target] = 0
update_allocations()
/datum/ai_shared_resources/proc/get_all_ais()
. = list()
for(var/datum/ai_network/A in networks)
. |= A.ai_list