some constants
[dd2d.git] / d2dadefs.d
blobaf623c34c89211c060321a7c89b7beb3b137b599
1 /* DooM2D: Midnight on the Firing Line
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 module d2dadefs is aliced;
20 private:
21 import glutils;
22 import console;
23 import dacs;
24 import d2dgfx;
25 import tatlas;
27 //version = tatlas_dump;
30 // ////////////////////////////////////////////////////////////////////////// //
31 private enum BIT(ubyte n) = (1U<<n);
34 // ////////////////////////////////////////////////////////////////////////// //
35 // thing flags
36 public enum {
37 AF_NOCOLLISION = BIT!(0),
38 AF_NOGRAVITY = BIT!(1),
39 AF_NOTHINK = BIT!(2),
40 AF_NOONTOUCH = BIT!(3), // `onTouch` will never be called with `me` for this actor
41 AF_NODRAW = BIT!(4), // don't draw sprite
42 AF_NOLIGHT = BIT!(5), // no attached light
43 AF_NOANIMATE = BIT!(6), // don't do animation
47 // ////////////////////////////////////////////////////////////////////////// //
48 // known D2D actors (and pseudoactors)
49 struct ActorDefD2D {
50 StrId classtype;
51 StrId classname;
52 ushort mapid; // thing id in map
54 this (string ctype, string cname, ushort thid=0) {
55 classtype = StrPool.intern(ctype);
56 classname = StrPool.intern(cname);
57 mapid = thid;
60 string toString () const {
61 import std.string : format;
62 return "ActorDefD2D(%s, %s, %s)".format(classtype.get, classname.get, mapid);
66 immutable ActorDefD2D[] d2dactordefs;
67 public immutable ActorDefD2D[ushort] d2dactordefsById; // by mapid
69 shared static this () {
70 d2dactordefs = [
71 ActorDefD2D("playerstart", "Player1", 1),
72 ActorDefD2D("playerstart", "Player2", 2),
73 ActorDefD2D("playerstart", "DMStart", 3),
74 ActorDefD2D("item", "Clip", 100),
75 ActorDefD2D("item", "Shell", 101),
76 ActorDefD2D("item", "Rocket", 102),
77 ActorDefD2D("item", "Cell", 103),
78 ActorDefD2D("item", "Ammo", 104),
79 ActorDefD2D("item", "ShellBox", 105),
80 ActorDefD2D("item", "RocketBox", 106),
81 ActorDefD2D("item", "CellPack", 107),
82 ActorDefD2D("item", "StimPack", 108),
83 ActorDefD2D("item", "MediKit", 109),
84 ActorDefD2D("item", "BackPack", 110),
85 ActorDefD2D("item", "Chainsaw", 111),
86 ActorDefD2D("item", "Shotgun", 112),
87 ActorDefD2D("item", "SuperShotgun", 113),
88 ActorDefD2D("item", "MachineGun", 114),
89 ActorDefD2D("item", "RocketLauncher", 115),
90 ActorDefD2D("item", "Plasmagun", 116),
91 ActorDefD2D("item", "BFG9000", 117),
92 ActorDefD2D("item", "ArmorGreen", 118),
93 ActorDefD2D("item", "ArmorBlue", 119),
94 ActorDefD2D("item", "MegaSphere", 120),
95 ActorDefD2D("item", "Invulnerability", 121),
96 ActorDefD2D("item", "Aqualung", 122),
97 ActorDefD2D("item", "KeyRed", 123),
98 ActorDefD2D("item", "KeyGreen", 124),
99 ActorDefD2D("item", "KeyBlue", 125),
100 ActorDefD2D("item", "ProtectionSuit", 126),
101 ActorDefD2D("item", "Super", 127),
102 ActorDefD2D("item", "TorchRed", 128),
103 ActorDefD2D("item", "TorchGreen", 129),
104 ActorDefD2D("item", "TorchBlue", 130),
105 ActorDefD2D("item", "Gor1", 131),
106 ActorDefD2D("item", "FCan", 132),
107 ActorDefD2D("item", "Gun2", 133),
108 ActorDefD2D("monster", "Demon", 200),
109 ActorDefD2D("monster", "Imp", 201),
110 ActorDefD2D("monster", "Zombie", 202),
111 ActorDefD2D("monster", "Sergeant", 203),
112 ActorDefD2D("monster", "Cyberdemon", 204),
113 ActorDefD2D("monster", "Chaingunner", 205),
114 ActorDefD2D("monster", "BaronOfHell", 206),
115 ActorDefD2D("monster", "HellKnight", 207),
116 ActorDefD2D("monster", "Cacodemon", 208),
117 ActorDefD2D("monster", "LostSoul", 209),
118 ActorDefD2D("monster", "PainElemental", 210),
119 ActorDefD2D("monster", "SpiderMastermind", 211),
120 ActorDefD2D("monster", "Arachnotron", 212),
121 ActorDefD2D("monster", "Mancubus", 213),
122 ActorDefD2D("monster", "Revenant", 214),
123 ActorDefD2D("monster", "Archvile", 215),
124 ActorDefD2D("monster", "Fish", 216),
125 ActorDefD2D("monster", "Barrel", 217),
126 ActorDefD2D("monster", "Robot", 218),
127 ActorDefD2D("monster", "Man", 219),
129 foreach (const ref ActorDefD2D d2da; d2dactordefs) {
130 if (d2da.mapid) d2dactordefsById[d2da.mapid] = d2da;
135 // ////////////////////////////////////////////////////////////////////////// //
136 public string getD2DSwitchClassName (uint swtype) {
137 switch (swtype) {
138 case 1: return "Exit"; // SW_EXIT
139 case 2: return "ExitSecret"; // SW_EXITS
140 case 3: return "DoorOpen"; // SW_OPENDOOR
141 case 4: return "DoorClose"; // SW_SHUTDOOR
142 case 5: return "TrapClose"; // SW_SHUTTRAP
143 case 6: return "Door"; // SW_DOOR
144 case 7: return "Door5"; // SW_DOOR5
145 case 8: return "Press"; // SW_PRESS
146 case 9: return "Teleport"; // SW_TELE
147 case 10: return "Secret"; // SW_SECRET
148 case 11: return "LiftUp"; // SW_LIFTUP
149 case 12: return "LiftDown"; // SW_LIFTDOWN
150 case 13: return "Trap"; // SW_TRAP
151 case 14: return "Lift"; // SW_LIFT
152 case 64: return "WinGame"; // SW_WINGAME
153 default:
155 return null;
159 // ////////////////////////////////////////////////////////////////////////// //
160 public bool processCL (ref string[] args) {
161 static string h() (const(void)[] src) {
162 static immutable uint[5] g = [0x31c84b1, 0x95eed, 0x1c39, 0x55, 0x1];
163 uint a = 0; int c = 0; auto d = cast(const(ubyte)[])src; string e; ubyte f = 0x5a;
164 foreach (immutable b; d) { a += (b-0x21)*g[c++]; if (c == 5) { foreach (immutable _; 0..4) { e ~= ((a>>24)^(f^=0xff))&0xff; a <<= 8; } a = 0; c = 0; } }
165 if (c > 1) { a += g[--c]; foreach (immutable _; 0..c) { e ~= ((a>>24)^(f^=0xff))&0xff; a <<= 8; } }
166 return e;
169 for (usize idx = 1; idx < args.length; ++idx) {
170 string s = null;
171 if (args[idx] == h("Lj-`b^coRZ")) {
172 s = h("l86;\"KeCe2M0e21^coRZJglC6au@O$_Ks*Wf6Z40cqs6ff0@&oKfmL2f62ib^b4#!f6YOr`\\"~
173 "E/latM@m_)9@`Y8kb;^ikD\\bT_mi_C3>^KfauKf.Y-\"__^+jY6huq^bgmo^b`h_d<:3aau%:'K"~
174 "dkD2gj7<sKf6k%^iZaobV[+YKeC.tM0eJPdm)H1ei(<.eU#.s`&#SYMfc-");
175 } else if (args[idx] == h("Lj.0,a#Lj_dP]$!g]")) {
176 s = h("`=C<Xep>@bbVmR!_KLVpb<CV4bs-n2aYV=\"gj7@*dm)D[KmM]6_0WsCf0=sNb<CVCbW!R#^j="~
177 "3]KeCV7Ke:5&^gO>baYni3bW\")tKe:(g^j=B`^j=$Yf/:E&dm)E,YBkmAb<CV4bs-n@au@+^f/"~
178 "qA8ep>Ild66)Ca$5JYY>Buk^b*JQ^j=B`^j>H2a#Lj_dP]$!M0d5fKdk/$KM[AKnM7n+cTBQ(Ke"~
179 "CV3d<`hhd6EJ6d5&L``\\taeep>_!`%Ha(`%K%bKM^hrdQ?&FKeCV7Kb2TjcS*=ba\"u=2M0d)s_"~
180 "0XZfcnqqPKau?lKfms?a>:slep?L@b<E]iehk;t`\\N3lY>FUNKeCM*c?d_kep>e&f.+]sKdkG-f"~
181 "04mEbBhDpb<DOpKmMu@b<:P3bW!=`d5&L`a?.Qhau@+^__o5Ubs-n2atLUed<^UmY6i?tf0@h=^cmH"~
182 "-^j=$GKeCV7KauHgd4`Red3udpM,8nPj>=]!eh5*&_0X$ObqmI+Kepnud5&it_D9M\\Y>F::_01Mo"~
183 "ep>OsKeL>+bULe_d5&it_D9Mbbs-n2d5B'1M,8nPnM7n+mlSQL^aRVg`\\E<rdPK9+Kg4?Wep>J$Kf"~
184 "mI=a?PMXju^XKKe:P*_`Z$sb<:P3bp^^f_D6ftbs-n7co/a*gj7C+b!(YYKmMf:_0X-Tf/Ul:_0X$KK"~
185 "eq,&`]M7+KM\\ieb<Li0d4NLfKb_cqM0dQ$b'Sg]b<CV4bp^^f_D6g,b<CV4bp^^f_D8<@Kau?lKe1@"~
186 "peN:m!a#:k\"^j=Enb:\\Jtb;7-m^aP!fb<*]uKM_&#Kf6_/d<a\"hKg*:6_01Mob<CV3bV%.dbV%Im"~
187 "bs0-1YBkm8^j=Enb:\\K3`&>t$eM>?*_Ks6a`\\EBJYB]+b_01Mf`$pBmbr*joei(H&bBhPk^j>H2a"~
188 "#Lj_dP]$!RS\\]aju(4EKeCMoa<QC#f/M9(Kf@e5a$7L$bULe_a#2Y!Y8)aRf/q#,atM=l_)pG!Kc."~
189 "feaYh3rKR2cBaYq'^KRL%MKbD1I`\\P[bd5Jd(KepnubqmpscSaL\"Y>DD`nL_[.KfI[?aYq@+M0d)s_"~
190 "0XKa^j=QibV%-bKeCM!^aZI5Kc\\H%Kg\"3>^j<pU_0WsSa>h:+Kepnud5&L`dQ>K6Sl\"K+aa2#aa=5n"~
191 "jdQc>JKeCV7KfI4'b!!lu^aY+:KmMf:_0XKa^j='Za?PA,`%K:`Kf.40_C3>^^iZa");
192 } else if (args[idx] == h("Lj.<*f.+]s") || args[idx] == h("Lj.<*f.+]seh,#m_#") || args[idx] == h("Lj.<*f.+]sa#:k\"^]")) {
193 s = h("r&)iI_)9Dad<a&!dm&Nrbs-mjasbe%aa3,.`'1tYY5");
194 } else if (args[idx] == h("Lj.E7dm)\"")) {
195 s = h("p-7\"jbBh)T^j=B`^a\"\\^ej%VJbBh)T^j=B`^a\"M/lnjDKbs-nBbra**^c$m(_g9]c^j<g]^"
196 "ab$e^b!8XKfdmNKeCV7gj?4<bBhPk^j=To_)'\"d`]o/7_g9Ql`%8\\\\Kdjeg^bga,f0=sAbs1!1Y7o**d5&"~
197 "L``\\PIhb<O*paukA1bs-nG^d$@qbVY#8Kdt#!`&YVZ_C32OKeCV7gj7<sMbrV!aZkJ3bs1!0`$iEIb;I[jKfm"~
198 ".0`&>DWd5&K^KfdmNKf$q)MbrasKeCV7Kf@4>eh2Y6_g9]c^j<g]^ab%\"f0=sAbs0E#Kdt\"nbpeQInh\\0JK"~
199 "eCV7gj74,dm&OCatANsehtWsd5&K^KegRt^j=0]d<)Q,f06tuKfdIAKe^e._)/qVep>Uuat8<\"bs1!0b;I[hY"~
200 "6rlCgcsD:`&,;Veh>Q'aYUpud5/p%KegG*f6Yh\"^a\"OiatATKnM7n+`]MX6f//1;bBhPk^j='Zcns-3bVY#+"~
201 "bs1!0^bjG'f6\"2,b:^q`m6AO8`$iEId5&K^Kege\"d5/m/Mbrq!^j=B`f/:`9LcE13f0@k9Kf-bod5&L`_DT."~
202 "YKfdmNKeCV7giT_@bULpmf/Uu2_KsTb^j=*YaWlKqbBhPk^j=Bcf-nEkd4'c2f0=sAbs1!0ej%Q(Y8G29^c]t%"~
203 "KfdmNKeCV7gieB2`&>Cnco-S>f0=sAbs1!*Y6huq^bga,f0=sAbs1!,Kdjeg^bga,f0=sAbs1!,Kdjeg^bg`td"~
204 "PJm-Kfd.5bVY#8f0=sAbs1!*Y8>,%KeCV7KdkP.f/(f'Kf-bobs0,t^bg`n^c0%fa$81!Kf?ppKeCV7KdkP.f/"~
205 "(f'Kf-bo^cU.#c$Iu+a?Ra*^aP+;");
206 } else if (args[idx] == h("Lj-lsf0'")) {
207 s = h("niqgif0=sAbs-n!asb,KKbhf_^aOm]atM@mehYH6aZe:%`&,;Veh>W'^biklf6Z40cmXSsbqmm!Mbrt/"~
208 "Ke:M,aa1lh_0XlocmXT-bVdL\"_DB1naa1l^_0XKn`\\P^paYgpk`]M@i_)'XpbV[<lbUgOd^a[i\\d5?V8cmXT*"~
209 "dPQkYr&)hLKfRL<d4a*9Ke:M,aa1lh`%'/\\d5?V,^aRYf`]o/1eo\\)$^a[JVd6#N3^j=3RKfm^7bVm7YY5");
210 } else if (args[idx] == h("Lj-]nauI0bec") || args[idx] == h("Lcrm<a$80)")) {
212 if (s.length) {
213 import core.stdc.stdio : printf;
214 printf("%.*s", cast(uint)s.length, s.ptr);
215 foreach (immutable c; idx+1..args.length) args[c-1] = args[c];
216 args.length = args.length-1;
217 --idx;
218 return true;
221 return false;
225 // ////////////////////////////////////////////////////////////////////////// //
226 // sprite atlases
227 __gshared TexAtlas[] atlases;
228 __gshared ImgSprite[string] sprImages;
231 public void realiseSpriteAtlases () {
232 foreach (immutable idx, TexAtlas a; atlases) {
233 import arsd.png;
234 import std.string : format;
235 a.updateTexture();
236 version(tatlas_dump) writePng("_za%02s.png".format(idx), a.img);
241 public struct ImgSprite {
242 D2DImage vga;
243 //Texture tex;
244 bool mirrored;
245 float tx0, tx1, ty0, ty1;
246 TexAtlas atlas;
247 TexAtlas.Rect arect;
249 //@disable this (this);
251 void putToAtlas () {
252 if (atlas !is null) return;
253 TexAtlas.Rect arc;
254 TexAtlas aa;
255 foreach (TexAtlas a; atlases) {
256 auto rc = a.insert(vga);
257 if (rc.valid) { arc = rc; aa = a; break; }
259 if (!arc.valid) {
260 int w = (vga.width < 1024 ? 1024 : vga.width);
261 int h = (vga.height < 1024 ? 1024 : vga.height);
262 aa = new TexAtlas(w, h);
263 arc = aa.insert(vga);
264 assert(arc.valid);
265 atlases ~= aa;
267 atlas = aa;
268 arect = arc;
269 tx0 = cast(float)arc.x/cast(float)(aa.width);
270 ty0 = cast(float)arc.y/cast(float)(aa.height);
271 tx1 = cast(float)(arc.x+arc.w)/cast(float)(aa.width);
272 ty1 = cast(float)(arc.y+arc.h)/cast(float)(aa.height);
275 void drawAtXY (int x, int y, bool mirrorX=false, bool mirrorY=false) {
276 import iv.glbinds;
277 if (atlas is null || !atlas.hasTexture) return;
278 x -= (mirrored ? vga.width-1-vga.sx : vga.sx);
279 y -= vga.sy;
280 int w = x+vga.width;
281 int h = y+vga.height;
282 if (mirrored) mirrorX = !mirrorX;
283 if (mirrorX) { int tmp = x; x = w; w = tmp; }
284 if (mirrorY) { int tmp = y; y = h; h = tmp; }
285 glBindTexture(GL_TEXTURE_2D, atlas.tex.tid);
286 glBegin(GL_QUADS);
287 glTexCoord2f(tx0, ty0); glVertex2i(x, y); // top-left
288 glTexCoord2f(tx1, ty0); glVertex2i(w, y); // top-right
289 glTexCoord2f(tx1, ty1); glVertex2i(w, h); // bottom-right
290 glTexCoord2f(tx0, ty1); glVertex2i(x, h); // bottom-left
291 glEnd();
296 // ////////////////////////////////////////////////////////////////////////// //
297 ImgSprite* loadSprite (string spnamef, bool checkMirror=true) {
298 if (spnamef.length == 0) return null;
299 import std.algorithm : endsWith;
300 if (auto im = spnamef in sprImages) {
301 //conwriteln("cached sprite '", spnamef, "'");
302 return im;
304 string spname = spnamef;
305 bool mirrored = false;
306 if (checkMirror && spname.endsWith("_mirrored.vga")) {
307 mirrored = true;
308 spname = spname[0..$-13]~".vga";
310 // for mirrored, load normal sprite and create mirrored one
311 if (mirrored) {
312 auto im = spname in sprImages;
313 if (im is null) im = loadSprite(spname, false);
314 if (im is null) return null;
315 auto imm = new ImgSprite();
316 *imm = *im;
317 imm.mirrored = true;
318 sprImages[spnamef] = *imm;
319 } else {
320 // new sprite
321 assert(!mirrored);
322 auto im = new ImgSprite();
323 im.vga = new D2DImage(spname);
324 im.putToAtlas();
325 sprImages[spnamef] = *im;
327 return spnamef in sprImages;
331 // ////////////////////////////////////////////////////////////////////////// //
332 public final class ActorDef {
333 StrId classtype;
334 StrId classname;
336 // animation sequences for stated; keyed by state strid
337 StrId[][][uint] anims; // [statestrid][dir][pos]
339 FuncPool.FuncInfo[] fiAnimInit;
340 FuncPool.FuncInfo fiInit;
341 FuncPool.FuncInfo fiThink;
343 ImgSprite*[][][uint] animSprites;
344 //__gshared ImgSprite*[][] animCur;
346 // load actor graphics
347 void loadGraphics () {
348 //conwriteln("loading graphics for '", fullname, "'; anims.length=", anims.length");
349 if (anims.length == 0) return; // no graphics here
350 // load sprites
351 foreach (auto anma2; anims.byValue) {
352 foreach (auto anma; anma2) {
353 foreach (StrId ssid; anma) {
354 //conwriteln(fullname, ": ssid=", ssid.id, "; is ", ssid.get);
355 if (ssid.id != 0) loadSprite(ssid.get);
359 // now fill animSprites
360 foreach (auto anma2; anims.byKeyValue) {
361 if (anma2.key !in animSprites) animSprites[anma2.key] = new ImgSprite*[][](2); // 2 dirs
362 auto aspx = animSprites[anma2.key];
363 foreach (immutable dir, auto anma; anma2.value) {
364 foreach (StrId ssid; anma) {
365 ImgSprite* spi = ssid.get in sprImages;
366 aspx[dir] ~= spi;
372 // unload actor graphics
373 void releaseGraphics () {
374 animSprites = null;
377 int nextAnimIdx (StrId state, uint dir, int curidx) {
378 if (dir != 0) dir = 1;
379 if (++curidx <= 0) return 0;
380 if (auto spra = state.id in animSprites) {
381 if (curidx < (*spra).ptr[dir].length) return curidx;
382 return 0;
384 return 0;
387 ImgSprite* animSpr (StrId state, uint dir, int curidx) {
388 if (dir != 0) dir = 1;
389 if (curidx < 0) return null;
390 if (auto spra = state.id in animSprites) {
391 if (curidx >= (*spra).ptr[dir].length) return null;
392 return (*spra).ptr[dir].ptr[curidx];
394 return null;
397 this (string ctype, string cname) {
398 classtype = StrPool.intern(ctype);
399 classname = StrPool.intern(cname);
402 void clearAllFrames (StrId state) {
403 anims.clear();
406 void clearFrames (StrId state) {
407 anims.remove(state.id);
410 void addFrame (StrId state, uint dir, StrId sprname) {
411 //conwriteln("new frame for '", fullname, "'; state=", state.get, "; sprname=", sprname.get, "; dir=", dir);
412 if (dir > 1) throw new Exception("addFrame: invalid dir");
413 if (state.id !in anims) anims[state.id] = new StrId[][](2);
414 auto aa = anims[state.id];
415 aa[dir] ~= sprname;
418 void setAnimInitFunc (FuncPool.FuncInfo fi) {
419 if (fi is null) return;
420 if (fi.mgtype != ":void") throw new Exception("invalid actor animation init function");
421 fiAnimInit ~= fi;
424 void setInitFunc (FuncPool.FuncInfo fi) {
425 if (fi is null) return;
426 if (fi.mgtype != ":void:Actor") throw new Exception("invalid actor init function");
427 fiInit = fi;
430 void setThinkFunc (FuncPool.FuncInfo fi) {
431 if (fi is null) return;
432 if (fi.mgtype != ":void:Actor") throw new Exception("invalid actor think function");
433 fiThink = fi;
436 void callAnimInit () {
437 foreach (auto fi; fiAnimInit) if (fi !is null) fi();
440 void callInit (ActorId aid) {
441 if (fiInit is null || !aid.valid) return;
442 fiInit(aid);
445 void callThink (ActorId aid) {
446 if (fiThink is null || !aid.valid) return;
447 fiThink(aid);
450 static:
451 // return `true` to stop
452 bool forEach (bool delegate (ActorDef d) dg) {
453 foreach (ActorDef adef; actordefs.byValue) if (dg(adef)) return true;
454 return false;
457 void forEach (void delegate (ActorDef d) dg) {
458 foreach (ActorDef adef; actordefs.byValue) dg(adef);
463 // ////////////////////////////////////////////////////////////////////////// //
464 public ActorDef findD2DActorDef (ushort mapid) {
465 if (mapid == 0) assert(0);
466 if (mapid == 1 || mapid == 2) return findActorDef("monster", "Player");
467 if (auto dad = mapid in d2dactordefsById) {
468 auto adef = findActorDef(dad.classtype, dad.classname);
469 if (adef is null) throw new Exception("can't find DACS actor definition for D2D actor '"~dad.classtype.get~":"~dad.classname.get~"'");
470 return adef;
472 import std.conv : to;
473 throw new Exception("can't find D2D ActorDef for mapid "~to!string(mapid));
477 // ////////////////////////////////////////////////////////////////////////// //
478 import dacs.actor;
480 __gshared ActorDef[ulong] actordefs; // by (name<<32)|type
482 mixin(Actor.FieldGetMixin!("classtype", StrId)); // fget_classtype
483 mixin(Actor.FieldGetMixin!("classname", StrId)); // fget_classname
486 ulong ctn2idx (uint ctid, uint cnid) { pragma(inline, true); return ((cast(ulong)cnid)<<32)|ctid; }
487 ulong ctn2idx (StrId ct, StrId cn) { pragma(inline, true); return ctn2idx(ct.id, cn.id); }
490 public ActorDef findActorDef (ActorId aid) {
491 pragma(inline, true);
492 if (!aid.valid) return null;
493 return findActorDef(aid.fget_classtype, aid.fget_classname);
497 public ActorDef findActorDef (StrId ctype, StrId cname) { /*pragma(inline, true);*/ return actordefs.get(ctn2idx(ctype.id, cname.id), null); }
500 public ActorDef findActorDef (const(char)[] ctype, const(char)[] cname) {
501 auto ctid = ctype in StrPool;
502 auto cnid = cname in StrPool;
503 if (!ctid || !cnid) return null;
504 return actordefs.get(ctn2idx(ctid, cnid), null);
508 public ActorDef registerActorDef (string classtype, string classname) {
509 auto ct = StrPool.intern(classtype);
510 auto cn = StrPool.intern(classname);
511 if (findActorDef(ct, cn) is null) actordefs[ctn2idx(ct, cn)] = new ActorDef(classtype, classname);
512 return actordefs[ctn2idx(ct, cn)];