blob: bcce57ea4da1ae1a80ffe09718c403c480a27afd [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001/** Doku:
2public int AddRoute(string transporter, string* l_stops)
3 Beschreibung:
4 Setzt die aktuelle Route eines Transporters.
5 Die Route hier ist allerdings nur die Liste von Haltepunkten - nicht der
6 Rest, der in den Routen in den Transporter abgelegt ist.
7 Eine neue Route ersetzt immer die bisherige Route
8 Wird von /std/transport gerufen, wenn P_NO_TRAVELING nicht gesetzt ist.
9 Rueckgabewerte:
10 - 1: Transporter und Haltepunkt Eingetragen.
11 - 0: Transporter oder Haltepunkt kein string|string*.
12 - -1: Es wurde versucht einen Transporter in /p/ oder /players/
13 einzutragen
14 und der Eintragende ist kein EM.
15
16public int RemoveTransporter(string|object transporter)
17public int RemoveStop(string|object stop)
18 Beschreibung:
19 Entfernt einen kompletten Transporter oder einen Haltepunkt aus dem
20 Daemon.
21 Rueckgabewerte:
22 - 1: Erfolg.
23 - 0: Transporter|Haltepunkt existiert nicht.
24 - -1: Keine Berechtigung.
25
26public varargs int|object* HasTransporter(object stop, string transporter_id)
27 Beschreibung:
28 Gibt eine Liste der Transporter aus, den den Haltepunkt anlaufen, oder
29 prueft auf einen bestimmten Transporter.
30 Rueckgabewerte:
31 - 0: Haltepunkt ist kein Objekt, dem Haltepunkt sind keine Transporter
32 zugeordnet,
33 die Transporter sind nicht geladen
34 oder, bei angabe von <transporter>: <transporter> faehrt den Hafen
35 nicht an.
36 - object*: Liste mit einem oder mehreren Transportern.
37 Bemerkung:
38 Auch bei der Angabe von <transporter_id> koennen mehrere Objekte
39 zurueckgegeben werden, es wird mittels id() gefiltert.
40
41public mixed RouteExists(object transporter, string dest)
42 Beschreibung:
43 Prueft auf korrekte Parameter und leitet die Anfrage an
44 /std/transport weiter.
45 Rueckgabewerte:
46 - 0: <transporter> ist kein Objekt oder <dest> ist kein String.
47 - Das Ergebnis von transporter->HasRoute(dest);
48
49public mapping QueryTransporters()
50public mapping QueryAllStops()
51public mapping QueryTransporterByStop(string stop)
52public mapping QueryStopsByTransporter(string transporter)
53 Beschreibung:
54 Gibt das jewilige gefilterte oder ungefilterte Mapping aus.
55 Rueckgabewerte:
56 Mapping mit dem Ergebnis.
57*/
58
59#pragma strong_types,save_types,rtt_checks
60#pragma pedantic,range_check,warn_deprecated
61#pragma warn_empty_casts,warn_missing_return,warn_function_inconsistent
62#pragma no_clone,no_shadow
63
64#include <transport.h>
65#include <wizlevels.h>
66#include <daemon.h>
67
68#define TRANSPORTER 0
69#define STOP 1
70
71#define MEMORY "/secure/memory"
72
Zesstra4e7b3322019-07-19 17:23:39 +020073// Propertyname zum Speichern der Reloadversuchszaehler
74#define RELOAD_TRIES "p_lib_reload_try_counter"
75
MG Mud User88f12472016-06-24 23:31:02 +020076// Key: string Schiff.
77// Value0: string* Haefen, die von <Schiff> angefahren werden.
78mapping transporters = ([]);
79// Key: string Hafen
80// Value0: string* Schiffe, die <Hafen> anfahren.
81mapping stops = ([]);
82
83protected void create()
84{
85 // Vom MEMORY die Daten abholen.
86 // Wenn keine da, war vermutlich Reboot, dann muessen wir warten, bis die
87 // Transporter sich wieder melden. Aber die Mappings muessen ins Memory
88 // geschrieben werden.
89 mapping tmp = MEMORY->Load("stops");
90 if (mappingp(tmp))
91 {
92 stops = tmp;
93 }
94 else
95 {
96 if (MEMORY->Save("stops",stops) != 1)
97 raise_error("Could not save memory to /secure/memory.");
98 }
99 tmp = MEMORY->Load("transporters");
100 if (mappingp(tmp))
101 {
102 transporters = tmp;
103 }
104 else
105 {
106 if (MEMORY->Save("transporters",transporters) != 1)
107 raise_error("Could not save memory to /secure/memory.");
108 }
Zesstra4e7b3322019-07-19 17:23:39 +0200109 set_next_reset(86400);
110}
111
112protected void reload_transporters(object *ships)
113{
114 if (!sizeof(ships))
115 return;
116 else if (sizeof(ships) > 1)
117 call_out(#'reload_transporters, 45, ships[1..]);
118
119 object s = ships[0];
120 if (s)
121 {
122 object *inv = all_inventory(s);
123 if (sizeof(inv))
124 {
125 // Wenn Spieler drin sind, muss auf jeden Fall gewartet werden.
126 // Bei sonstigem Krempel nur dann, wenn wir das noch nicht oft genug
127 // erfolglos versucht haben.
128 // Bemerkung: eigentlich muesste man hier pruefen, was davon per
129 // AddItem() erzeugt wurde. Das ist mir gerade aber zu aufwendig.
130 if (sizeof(filter(inv, #'query_once_interactive))
131 || s->QueryProp(RELOAD_TRIES) < 3)
132 {
133 s->SetProp(RELOAD_TRIES, s->QueryProp(RELOAD_TRIES) + 1);
134 // naechsten reset vorziehen
135 set_next_reset(10800);
136 return;
137 }
138 // ansonsten ist uns das Inventar jetzt egal und bald Schrott...
139 }
140 string sname = object_name(s);
141 s->remove(1);
142 load_object(sname);
143 // Und hoffentlich starten Transporter selber. Wenn nicht, muss hier evtl.
144 // noch nen Continue hin.
145 }
Zesstrac1f496a2017-09-21 22:56:52 +0200146}
147
148public void reset()
149{
Zesstra4e7b3322019-07-19 17:23:39 +0200150 set_next_reset(86400);
151 // Zeit des Programms vom Standardtransporter herausfinden. Wenn der nicht
152 // geladen ist, muss nix gemacht werden.
153 object std_transport = find_object("/std/transport");
154 if (!std_transport)
155 return;
156 int std_time = program_time(std_transport);
Zesstraf15383d2019-07-19 16:35:06 +0200157
Zesstra4e7b3322019-07-19 17:23:39 +0200158 // ueber alle Transporter laufen. Wenn der Transport aelter ist als
159 // /std/transport, wird er neu gelauden.
160 // Das kann Nebenwirkungen haben. Aber in diesem Fall sollte man besser
161 // den Transporter so bauen, dass es OK ist.
162 // Aber speziell bei VC-Transportern ist fraglich, wie gut das
163 // funktioniert...
164 // Und es funktioniert nur fuer Blueprints.
Zesstra21b21072019-08-31 21:13:37 +0200165 object *old_ships = map(m_indices(transporters),
166 function object (string sname)
Zesstra4e7b3322019-07-19 17:23:39 +0200167 {
168 object ship = find_object(sname);
169 if (ship && !clonep(ship) && program_time(ship) < std_time)
170 return ship;
171 return 0;
172 } );
173 old_ships -= ({0});
174 if (sizeof(old_ships))
175 reload_transporters(old_ships);
MG Mud User88f12472016-06-24 23:31:02 +0200176}
177
178varargs int remove(int s)
179{
180 destruct(this_object());
181 return 1;
182}
183
184// Loeschfunktion
185private int _remove_data(string|object key, int what)
186{
187 mapping first,second;
188 // Erstmal die Arbeitsmappings befuellen.
189 if(what==TRANSPORTER)
190 {
191 first=transporters;
192 second=stops;
193 }
194 else
195 {
196 first=stops;
197 second=transporters;
198 }
199
200 // Key auf einen String normalisieren.
201 if(objectp(key))
202 {
203 key=object_name(key);
204 }
205
206 if(!member(first,key))
207 {
208 return 0;
209 }
210
211 // Erstmal aus dem jeweils anderen Mapping austragen.
212 foreach(string s : first[key])
213 {
214 // Nicht existent oder nicht zugeordnet -> weiter.
215 if(!member(second,s) || member(second[s],key)==-1)
216 {
217 continue;
218 }
219 second[s]-=({key});
220 if (!sizeof(second[s]))
221 m_delete(second,s);
222 }
223 // Jetzt noch aus dem eigenen Mapping austragen.
224 m_delete(first,key);
225 return 1;
226}
227
228// Ein komplettes Schiff entfernen.
229public int RemoveTransporter(object|string transporter)
230{
Zesstra@Morgengrauenf8f1b752016-11-01 13:33:38 +0100231 if (extern_call()
232 && previous_object() != transporter
233 && !IS_ELDER(getuid(previous_object())))
234 return -1;
MG Mud User88f12472016-06-24 23:31:02 +0200235 return _remove_data(transporter,TRANSPORTER);
236}
237
238// Entfernt einen kompletten Hafen aus dem Daemon
239public int RemoveStop(object|string stop)
240{
Zesstra@Morgengrauenf8f1b752016-11-01 13:33:38 +0100241 if (extern_call()
242 && previous_object() != stop
243 && !IS_ELDER(getuid(previous_object())))
244 return -1;
MG Mud User88f12472016-06-24 23:31:02 +0200245 return _remove_data(stop,STOP);
246}
247
248// Setzt die aktuelle Route eines Transporters.
249// Die Route hier ist allerdings nur die Liste von Haltepunkten - nicht der
250// Rest, der in den Routen in den Transporter abgelegt ist.
251// Wird von /std/transport gerufen, wenn P_NO_TRAVELING nicht gesetzt ist.
252public int AddRoute(string transporter, string* l_stops)
253{
254 if (!stringp(transporter) || !pointerp(l_stops) || !sizeof(l_stops))
255 return 0;
256
257 if ((transporter[0..2] == "/p/" || transporter[0..8] == "/players/")
258 && !IS_ARCH(getuid(previous_object())))
259 {
260 return -1;
261 }
262
263 // Damit sind alle Abfragen auf find_object(transporter|stop) ueberfluessig,
264 // im Zweifelsfall knallt es naemlich hier. ;-)
265 transporter = object_name(load_object(transporter));
266
267 // Wenn die route bereits existiert, austragen. Dies ist noetig, weil die
268 // Haltepunkte ja auch bereinigt werden muessen.
269 if (member(transporters, transporter))
270 RemoveTransporter(transporter);
271
272 // Transporter eintragen, die Route wird dabei immer ueberschrieben, wenn
273 // der Transporter schon bekannt ist. Ziel: hier ist immer die aktuell
274 // konfigurierte Route drin.
275 m_add(transporters, transporter, l_stops);
276
277 // Nach obigen Schema, nur diesmal Haltepunkte und zugehoerige Schiffe
278 // eintragen.
279 foreach(string stop : l_stops)
280 {
281 if (!member(stops,stop))
282 {
283 m_add(stops, stop, ({transporter}));
284 }
285 else if (member(stops[stop],transporter) == -1)
286 {
287 stops[stop] += ({ transporter });
288 }
289 }
290 return 1;
291
292}
293
294// Abfrage ob ein Schiff einen Hafen anfaehrt.
295public varargs int|object* HasTransporter(object stop,
296 string transporter_id)
297{
298 if (!objectp(stop)) return 0;
299
300 <string|object>* trans=stops[object_name(stop)];
301 if (!pointerp(trans)) return 0;
302
303 // Eigentlich sollten sich Transporter ordentlich abmelden... Aber zur
304 // Sicherheit die nicht gefundenen Objekte ausfiltern.
305 trans = map(trans, #'find_object) - ({0});
306
307 // Wenn ne bestimmte ID gesucht wird, nur diese Transporter liefern.
308 if (stringp(transporter_id))
309 trans = filter_objects(trans, "id", transporter_id);
310
311 return sizeof(trans) ? trans : 0;
312}
313
314public mixed RouteExists(object transporter, string dest)
315{
316 if (!objectp(transporter) || !stringp(dest))
317 {
318 return 0;
319 }
320 return transporter->HasRoute(dest);
321}
322
323public mapping QueryTransporters()
324{
325 return deep_copy(transporters);
326}
327
328public mapping QueryAllStops()
329{
330 return deep_copy(stops);
331}
332
333// Liefert alle Transporter mit ihren Haltepunkten zurueck, die diesen Halt ansteuern.
334public mapping QueryTransportByStop(string stop)
335{
336 mapping res=m_allocate(4);
337 foreach(string s, string* arr : transporters)
338 {
339 if(member(arr,stop)!=-1)
340 {
341 m_add(res,s,arr);
342 }
343 }
344 return res;
345}
346
347// Liefert alle Haltepunkte mit ihren Transportern zurueck, die dieser
348// transporter ansteuert.
349public mapping QueryStopsByTransporter(string transporter)
350{
351 mapping res=m_allocate(4);
352 foreach(string s, string* arr : stops)
353 {
354 if(member(arr,transporter)!=-1)
355 {
356 m_add(res,s,arr);
357 }
358 }
359 return res;
360}
361