blob: e7464ec2eadfb631792fdb008da95558cdc1a3c7 [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
73// Key: string Schiff.
74// Value0: string* Haefen, die von <Schiff> angefahren werden.
75mapping transporters = ([]);
76// Key: string Hafen
77// Value0: string* Schiffe, die <Hafen> anfahren.
78mapping stops = ([]);
79
80protected void create()
81{
82 // Vom MEMORY die Daten abholen.
83 // Wenn keine da, war vermutlich Reboot, dann muessen wir warten, bis die
84 // Transporter sich wieder melden. Aber die Mappings muessen ins Memory
85 // geschrieben werden.
86 mapping tmp = MEMORY->Load("stops");
87 if (mappingp(tmp))
88 {
89 stops = tmp;
90 }
91 else
92 {
93 if (MEMORY->Save("stops",stops) != 1)
94 raise_error("Could not save memory to /secure/memory.");
95 }
96 tmp = MEMORY->Load("transporters");
97 if (mappingp(tmp))
98 {
99 transporters = tmp;
100 }
101 else
102 {
103 if (MEMORY->Save("transporters",transporters) != 1)
104 raise_error("Could not save memory to /secure/memory.");
105 }
Zesstrac1f496a2017-09-21 22:56:52 +0200106 set_next_reset(10800);
107}
108
109public void reset()
110{
111 set_next_reset(10800);
112 // Als Wuergaround fuer das Problem, dass selten genutzte Transporter in
113 // spielerunzugaenglichen Raeumen stehen bleiben und der spielerzugaengliche Raum
114 // mangels Benutzung ausgeswappt wird, lassen wir hier alle paar Stunden mal
115 // alle bekannten Transporter loslaufen. Ohne Spielerkontakt bleiben sie
116 // nach einem Routenumlauf wieder stehen.
117 // TODO: Problem "richtig" loesen.
118 foreach(string ship: transporters)
119 {
120 // ja, geht nur fuer Blueprints. BTW: hart zerstoerte Transporter, die
121 // sich nicht abgemeldet haben, werden jetzt neugeladen. Das muss nicht
122 // immer gut sein, ist momentan aber sogar willkommen.
123 ship->Continue();
124 }
MG Mud User88f12472016-06-24 23:31:02 +0200125}
126
127varargs int remove(int s)
128{
129 destruct(this_object());
130 return 1;
131}
132
133// Loeschfunktion
134private int _remove_data(string|object key, int what)
135{
136 mapping first,second;
137 // Erstmal die Arbeitsmappings befuellen.
138 if(what==TRANSPORTER)
139 {
140 first=transporters;
141 second=stops;
142 }
143 else
144 {
145 first=stops;
146 second=transporters;
147 }
148
149 // Key auf einen String normalisieren.
150 if(objectp(key))
151 {
152 key=object_name(key);
153 }
154
155 if(!member(first,key))
156 {
157 return 0;
158 }
159
160 // Erstmal aus dem jeweils anderen Mapping austragen.
161 foreach(string s : first[key])
162 {
163 // Nicht existent oder nicht zugeordnet -> weiter.
164 if(!member(second,s) || member(second[s],key)==-1)
165 {
166 continue;
167 }
168 second[s]-=({key});
169 if (!sizeof(second[s]))
170 m_delete(second,s);
171 }
172 // Jetzt noch aus dem eigenen Mapping austragen.
173 m_delete(first,key);
174 return 1;
175}
176
177// Ein komplettes Schiff entfernen.
178public int RemoveTransporter(object|string transporter)
179{
Zesstra@Morgengrauenf8f1b752016-11-01 13:33:38 +0100180 if (extern_call()
181 && previous_object() != transporter
182 && !IS_ELDER(getuid(previous_object())))
183 return -1;
MG Mud User88f12472016-06-24 23:31:02 +0200184 return _remove_data(transporter,TRANSPORTER);
185}
186
187// Entfernt einen kompletten Hafen aus dem Daemon
188public int RemoveStop(object|string stop)
189{
Zesstra@Morgengrauenf8f1b752016-11-01 13:33:38 +0100190 if (extern_call()
191 && previous_object() != stop
192 && !IS_ELDER(getuid(previous_object())))
193 return -1;
MG Mud User88f12472016-06-24 23:31:02 +0200194 return _remove_data(stop,STOP);
195}
196
197// Setzt die aktuelle Route eines Transporters.
198// Die Route hier ist allerdings nur die Liste von Haltepunkten - nicht der
199// Rest, der in den Routen in den Transporter abgelegt ist.
200// Wird von /std/transport gerufen, wenn P_NO_TRAVELING nicht gesetzt ist.
201public int AddRoute(string transporter, string* l_stops)
202{
203 if (!stringp(transporter) || !pointerp(l_stops) || !sizeof(l_stops))
204 return 0;
205
206 if ((transporter[0..2] == "/p/" || transporter[0..8] == "/players/")
207 && !IS_ARCH(getuid(previous_object())))
208 {
209 return -1;
210 }
211
212 // Damit sind alle Abfragen auf find_object(transporter|stop) ueberfluessig,
213 // im Zweifelsfall knallt es naemlich hier. ;-)
214 transporter = object_name(load_object(transporter));
215
216 // Wenn die route bereits existiert, austragen. Dies ist noetig, weil die
217 // Haltepunkte ja auch bereinigt werden muessen.
218 if (member(transporters, transporter))
219 RemoveTransporter(transporter);
220
221 // Transporter eintragen, die Route wird dabei immer ueberschrieben, wenn
222 // der Transporter schon bekannt ist. Ziel: hier ist immer die aktuell
223 // konfigurierte Route drin.
224 m_add(transporters, transporter, l_stops);
225
226 // Nach obigen Schema, nur diesmal Haltepunkte und zugehoerige Schiffe
227 // eintragen.
228 foreach(string stop : l_stops)
229 {
230 if (!member(stops,stop))
231 {
232 m_add(stops, stop, ({transporter}));
233 }
234 else if (member(stops[stop],transporter) == -1)
235 {
236 stops[stop] += ({ transporter });
237 }
238 }
239 return 1;
240
241}
242
243// Abfrage ob ein Schiff einen Hafen anfaehrt.
244public varargs int|object* HasTransporter(object stop,
245 string transporter_id)
246{
247 if (!objectp(stop)) return 0;
248
249 <string|object>* trans=stops[object_name(stop)];
250 if (!pointerp(trans)) return 0;
251
252 // Eigentlich sollten sich Transporter ordentlich abmelden... Aber zur
253 // Sicherheit die nicht gefundenen Objekte ausfiltern.
254 trans = map(trans, #'find_object) - ({0});
255
256 // Wenn ne bestimmte ID gesucht wird, nur diese Transporter liefern.
257 if (stringp(transporter_id))
258 trans = filter_objects(trans, "id", transporter_id);
259
260 return sizeof(trans) ? trans : 0;
261}
262
263public mixed RouteExists(object transporter, string dest)
264{
265 if (!objectp(transporter) || !stringp(dest))
266 {
267 return 0;
268 }
269 return transporter->HasRoute(dest);
270}
271
272public mapping QueryTransporters()
273{
274 return deep_copy(transporters);
275}
276
277public mapping QueryAllStops()
278{
279 return deep_copy(stops);
280}
281
282// Liefert alle Transporter mit ihren Haltepunkten zurueck, die diesen Halt ansteuern.
283public mapping QueryTransportByStop(string stop)
284{
285 mapping res=m_allocate(4);
286 foreach(string s, string* arr : transporters)
287 {
288 if(member(arr,stop)!=-1)
289 {
290 m_add(res,s,arr);
291 }
292 }
293 return res;
294}
295
296// Liefert alle Haltepunkte mit ihren Transportern zurueck, die dieser
297// transporter ansteuert.
298public mapping QueryStopsByTransporter(string transporter)
299{
300 mapping res=m_allocate(4);
301 foreach(string s, string* arr : stops)
302 {
303 if(member(arr,transporter)!=-1)
304 {
305 m_add(res,s,arr);
306 }
307 }
308 return res;
309}
310