blob: a734c2579cf8984f0709fabbc21b08df0ed2950c [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// * living_name-Behandlung
2
Zesstracd25d262020-01-21 19:36:39 +01003#include "/sys/userinfo.h"
4
MG Mud User88f12472016-06-24 23:31:02 +02005#define clean_log(s)
6//#define clean_log(s) log_file("CLEAN_SIM",ctime(time())[4..18]+": "+(s));
7
8private nosave mapping living_name_m, name_living_m, netdead;
9
10private void InitLivingData(mixed wizinfo) {
11 // living_name ist ein Pointer der auch in der extra_wizinfo gehalten
12 // wird, so kann die simul_efun neu geladen werden, ohne dass dieses
13 // Mapping verloren geht
14 if (!mappingp(living_name_m = wizinfo[LIVING_NAME]))
15 living_name_m = wizinfo[LIVING_NAME] = m_allocate(0, 1);
16
17 // Gleiches gilt fuer das Mapping Name-Living
18 if (!mappingp(name_living_m = wizinfo[NAME_LIVING]))
19 name_living_m = wizinfo[NAME_LIVING] = m_allocate(0, 1);
20
21 // Netztote sind ebenfalls in der extra_wizinfo
22 if (!mappingp(netdead = wizinfo[NETDEAD_MAP]))
23 netdead = wizinfo[NETDEAD_MAP] = ([]);
24}
25
Zesstrafddc2a42020-01-21 22:06:47 +010026public varargs string getuuid( object|string ob )
MG Mud User88f12472016-06-24 23:31:02 +020027{
Zesstrafddc2a42020-01-21 22:06:47 +010028 string uid;
29 if (stringp(ob))
30 uid = ob;
31 else
32 {
33 if ( !objectp(ob) )
34 ob = previous_object();
35 uid = getuid(ob);
36 }
MG Mud User88f12472016-06-24 23:31:02 +020037
Zesstrafddc2a42020-01-21 22:06:47 +010038 // sollte <uid> kein Spieler-UID sein (keine Spieler-UID uebergeben oder
39 // !query_once_interactive(ob)), ist creation 0 und es wird die <uid>
40 // unveraendert zurueckgeben.
41 int creation = master()->query_userlist(uid, USER_CREATION_DATE);
MG Mud User88f12472016-06-24 23:31:02 +020042
Zesstra311f9702020-01-21 22:08:56 +010043 if (!creation)
Zesstrafddc2a42020-01-21 22:06:47 +010044 return uid;
MG Mud User88f12472016-06-24 23:31:02 +020045
Zesstracd25d262020-01-21 19:36:39 +010046 // Username + "_" + CreationDate
Zesstrafddc2a42020-01-21 22:06:47 +010047 return uid + "_" + creation;
MG Mud User88f12472016-06-24 23:31:02 +020048}
49
50void set_object_living_name(string livname, object obj)
51{
52 string old;
53 mixed a;
54 int i;
55
56 if (previous_object()==obj || previous_object()==this_object() ||
57 previous_object()==master())
58 {
59 if(!livname || !stringp(livname)) {
60 set_this_object(previous_object());
61 raise_error(sprintf("%O: illegal living name: %O\n", obj, livname));
62 }
63 if (old = living_name_m[obj]) {
64 if (pointerp(a = name_living_m[old])) {
65 a[member(a, obj)] = 0;
66 } else {
67 m_delete(name_living_m, old);
68 }
69 }
70 living_name_m[obj] = livname;
71 if (a = name_living_m[livname]) {
72 if (!pointerp(a)) {
73 name_living_m[livname] = ({a, obj});
74 return;
75 }
76 /* Try to reallocate entry from destructed object */
77 if ((i = member(a, 0)) >= 0) {
78 a[i] = obj;
79 return;
80 }
81 name_living_m[livname] = a + ({obj});
82 return;
83 }
84 name_living_m[livname] = obj;
85 }
86}
87
88void set_living_name(string livname)
89{
90 set_object_living_name(livname,previous_object());
91}
92
93void remove_living_name()
94{
95 string livname;
96
97 if (!previous_object())
98 return;
99 if (livname=living_name_m[previous_object()])
100 {
101 m_delete(living_name_m,previous_object());
102 if (objectp(name_living_m[livname]))
103 {
104 if (name_living_m[livname]==previous_object())
105 m_delete(name_living_m,livname);
106 return;
107 }
108 if (pointerp(name_living_m[livname]))
109 {
110 name_living_m[livname]-=({previous_object()});
111 if (!sizeof(name_living_m[livname]))
112 m_delete(name_living_m,livname);
113 }
114 }
115}
116
117void _set_netdead()
118{
119 if (query_once_interactive(previous_object()))
120 netdead[getuid(previous_object())]=previous_object();
121}
122
123void _remove_netdead()
124{
125 m_delete(netdead,getuid(previous_object()));
126}
127
128object find_netdead(string uuid)
129{
130 int i;
131 string uid;
132 // Wenn sscanf() 2 liefert, ist uuid auch ne uuid.
133 int is_uuid = sscanf(uuid, "%s_%d", uid, i) == 2;
134 if (!is_uuid)
135 uid = uuid;
136
137 if (is_uuid && getuuid(netdead[uid]) != uuid)
138 return 0;
139
140 return netdead[uid];
141}
142
143string *dump_netdead()
144{
145 return m_indices(netdead);
146}
147
148object find_living(string livname) {
149 mixed *a, r;
150 int i;
151
152 if (pointerp(r = name_living_m[livname])) {
153 if (member(r,0)>=0)
154 r-=({0});
155 if (!sizeof(r)){
156 m_delete(name_living_m,livname);
157 clean_log(sprintf("find_living loescht %s\n",livname));
158 return 0;
159 }
160 if ( !living(r = (a = r)[0])) {
161 for (i = sizeof(a); --i;) {
162 if (living(a[<i])) {
163 r = a[<i];
164 a[<i] = a[0];
165 return a[0] = r;
166 }
167 }
168 }
169 return r;
170 }
171 return living(r) && r;
172}
173
174object *find_livings(string livname)
175{
176 mixed r;
177
178 if (pointerp(r=name_living_m[livname]))
179 r-=({0});
180 else
181 if (objectp(r))
182 r=({r});
183 if (!pointerp(r)||!sizeof(r))
184 return 0;
185 return r;
186}
187
188object find_player(string uuid) {
189 object *objs;
190 mixed res;
191 int i;
192 string uid;
193
194 if (!stringp(uuid))
195 return 0;
196 // Wenn sscanf() 2 liefert, ist uuid auch ne uuid.
197 int is_uuid = sscanf(uuid, "%s_%d", uid, i) == 2;
198 if (!is_uuid)
199 uid = uuid;
200
201 if (pointerp(res = name_living_m[uid])) {
202 // zerstoerte Objekte ggf. entfernen
203 if (member(res,0)>=0) {
204 res-=({0});
205 name_living_m[uid] = res;
206 }
207 // ggf. Namen ohne Objekte entfernen.
208 if (!sizeof(res)){
209 m_delete(name_living_m,uid);
210 clean_log(sprintf("find_player loescht %s\n",uid));
211 return 0;
212 }
213 objs = res;
214 res = objs[0];
215 // Wenn das 0. Element der Spieler ist, sind wir fertig. Ansonsten suchen
216 // wir den Spieler und schieben ihn an die 0. Stelle im Array.
217 if ( !query_once_interactive(res)) {
218 for (i = sizeof(objs); --i;) {
219 if (objs[<i] && query_once_interactive(objs[<i])) {
220 res = objs[<i];
221 objs[<i] = objs[0];
222 objs[0] = res;
223 break;
224 }
225 }
226 res = (objectp(res) && query_once_interactive(res)) ? res : 0;
227 }
228 // else: in res steht der Spieler schon.
229 }
230 else if (objectp(res)) // r ist nen Einzelobjekt
231 res = query_once_interactive(res) ? res : 0;
232
233 // res ist jetzt ggf. der Spieler. Aber wenn der ne andere als die gesuchte
234 // UUID hat, ist das Ergebnis trotzdem 0.
235 if (is_uuid && getuuid(res)!=uuid)
236 return 0;
237
238 // endlich gefunden
239 return res;
240}
241
242private int check_match( string str, int players_only )
243{
244 mixed match;
245
246 if ( !(match = name_living_m[str]) )
247 return 0;
248
249 if ( !pointerp(match) )
250 match = ({ match });
251
252 match -= ({0});
253
254 if ( sizeof(match) ){
255 if ( players_only )
256 return sizeof(filter( match, #'query_once_interactive/*'*/ ))
257 > 0;
258 else
259 return 1;
260 }
261
262 m_delete( name_living_m, str );
263 clean_log( sprintf("check_match loescht %s\n", str) );
264 return 0;
265}
266
267//TODO:: string|string* exclude
268varargs mixed match_living( string str, int players_only, mixed exclude )
269{
270 int i, s;
271 mixed match, *user;
272
273 if ( !str || str == "" )
274 return 0;
275
276 if ( !pointerp(exclude) )
277 exclude = ({ exclude });
278
279 if ( member(exclude, str) < 0 && check_match(str, players_only) )
280 return str;
281
282 user = m_indices(name_living_m);
283 s = sizeof(str);
284 match = 0;
285
286 for ( i = sizeof(user); i--; )
287 if ( str == user[i][0..s-1] && member( exclude, user[i] ) < 0 )
288 if ( match )
289 return -1;
290 else
291 if ( check_match(user[i], players_only) )
292 match = user[i];
293
294 if ( !match )
295 return -2;
296
297 return match;
298}
299
300mixed *dump_livings()
301{
302 return sort_array(m_indices(name_living_m),#'>);
303}
304
305// * regelmaessig Listen von Ballast befreien
306private void clean_name_living_m(string *keys, int left, int num)
307{
308 int i, j;
309 mixed a;
310
311 while (left && num--)
312 {
313 if (pointerp(a = name_living_m[keys[--left]]) && member(a, 0)>=0)
314 {
315 a-=({0});
316 name_living_m[keys[left]] = a;
317 }
318 if (!a || (pointerp(a) && !sizeof(a)))
319 {
320 clean_log("Toasting "+keys[left]+"\n");
321 m_delete(name_living_m, keys[left]);
322 } else clean_log(sprintf("KEEPING %s (%O)\n",keys[left],pointerp(a)?sizeof(a):a));
323 }
324 if (left)
325 efun::call_out(#'clean_name_living_m, 1, keys, left, 80);
326 else
327 clean_log("Clean process finished\n");
328}
329
330private void clean_netdead() {
331 int i;
332 string *s;
333 object ob;
334
335 s=m_indices(netdead);
336 for (i=sizeof(s)-1;i>=0;i--)
337 if (!objectp(ob=netdead[s[i]]) || interactive(ob))
338 m_delete(netdead,s[i]);
339}
340
341private void CleanLivingData() {
342 if (find_call_out(#'clean_name_living_m) < 0) {
343 clean_log("Starting clean process\n");
344 efun::call_out(#'clean_name_living_m,
345 1,
346 m_indices(name_living_m),
347 sizeof(name_living_m),
348 80
349 );
350 }
351 efun::call_out(#'clean_netdead,2);
352}
353
354#undef clean_log
355