1 module dengapi
is aliced
;
19 // ////////////////////////////////////////////////////////////////////////// //
20 private extern (C
) void _d_print_throwable (Throwable t
);
23 // ////////////////////////////////////////////////////////////////////////// //
28 // ////////////////////////////////////////////////////////////////////////// //
29 void updateActorClasses (int iteration
) {
30 foreach (string ctype
; dacsClassTypes(iteration
)) {
31 foreach (auto mod
; dacsClassModules(ctype
, iteration
)) {
32 auto adef
= registerActorDef(mod
.rmoduletype
.classtype
, mod
.rmoduletype
.classname
);
33 conwriteln("found info for actor '", adef
.fullname
, "'");
35 auto animInitFn
= FuncPool
.findByFQMG(mod
.name
~".initializeAnim", ":void");
36 if (animInitFn
!is null) {
37 if (animInitFn
.code
.length
== 0) throw new CompilerException("invalid 'initializeAnim' in module '"~mod
.name
~"' for '"~mod
.rmoduletype
.classtype
~":"~mod
.rmoduletype
.classname
~"'");
39 adef
.setAnimInitFunc(animInitFn
);
42 auto initFn
= FuncPool
.findByFQMG(mod
.name
~".initialize", ":void:Actor");
43 if (initFn
!is null) {
44 if (initFn
.code
.length
== 0) throw new CompilerException("invalid 'initialize' in module '"~mod
.name
~"' for '"~mod
.rmoduletype
.classtype
~":"~mod
.rmoduletype
.classname
~"'");
46 adef
.setInitFunc(initFn
);
49 auto thinkFn
= FuncPool
.findByFQMG(mod
.name
~".think", ":void:Actor");
50 if (thinkFn
!is null) {
51 if (thinkFn
.code
.length
== 0) throw new CompilerException("invalid 'think' in module '"~mod
.name
~"' for '"~mod
.rmoduletype
.classtype
~":"~mod
.rmoduletype
.classname
~"'");
53 adef
.setThinkFunc(thinkFn
);
60 // ////////////////////////////////////////////////////////////////////////// //
61 private string
modLoader (string modname
) {
62 static string
getTextFile (string fname
) {
64 auto res
= loadTextFile(fname
);
65 conwriteln("loading DACS module file '", fname
, "' (", res
.length
, " bytes)");
66 if (res
is null) res
= "";
68 } catch (Exception
) {}
74 //res = getTextFile(modname~".dacs");
75 //if (res !is null) return res;
77 res
= getTextFile("scripts/"~modname
~".dacs");
78 if (res
!is null) return res
;
81 string
[] parts
= ["scripts"];
83 while (mn
.length
> 0) {
85 if (mn
[0] >= 'A' && mn
[0] <= 'Z') ++pos
;
86 while (pos
< mn
.length
&& (mn
[pos
] < 'A' || mn
[pos
] > 'Z')) ++pos
;
87 if (mn
[0] >= 'A' && mn
[0] <= 'Z') {
88 parts
~= cast(char)(mn
[0]+32)~mn
[1..pos
];
95 import std
.array
: join
;
96 string path
= parts
.join("/")~".dacs";
97 res
= getTextFile(path
);
98 if (res
!is null) return res
;
102 throw new Exception("module '"~modname
~"' not found");
106 __gshared
int modIteration
= 0;
108 public void loadWadScripts () {
109 if (moduleLoader
is null) moduleLoader
= (string modname
) => modLoader(modname
);
112 import std
.array
: split
;
113 auto t
= loadTextFile("dacsmain.txt");
114 foreach (string line
; t
.split('\n')) {
115 while (line
.length
&& line
[0] <= ' ') line
= line
[1..$];
116 if (line
.length
== 0 || line
[0] == ';') continue;
117 while (line
.length
&& line
[$-1] <= ' ') line
= line
[0..$-1];
121 } catch (Exception e
) { return; }
123 //conwriteln("loading main DACS module '", mainmod, "'");
124 auto iter
= modIteration
++;
125 parseModule(mainmod
, iter
);
127 updateActorClasses(iter
);
128 } catch (CompilerException e
) {
129 _d_print_throwable(e
);
130 conwriteln("PARSE ERROR: ", e
.file
, " at ", e
.line
);
131 conwriteln(e
.toString
);
137 // ////////////////////////////////////////////////////////////////////////// //
138 public __gshared LevelMap map
;
139 public __gshared DACSVM dvm
;
140 public __gshared
uint prngSyncSeed
= 0x29a;
141 public __gshared
uint prngSeed
= 0x29a; // unsynced
144 // ////////////////////////////////////////////////////////////////////////// //
145 // Park-Miller-Carta Pseudo-Random Number Generator, based on David G. Carta paper
146 // 31 bit of randomness
147 // seed is previous result, as usual
148 public uint prngR31next (uint seed
) {
149 if (seed
== 0) seed
= 0x29a;
150 uint lo
= 16807*(seed
&0xffff);
151 uint hi
= 16807*(seed
>>16);
152 lo
+= (hi
&0x7fff)<<16;
154 //if (lo > 0x7fffffff) lo -= 0x7fffffff; // should be >=, actually
155 lo
= (lo
&0x7FFFFFFF)+(lo
>>31); // same as previous code, but branch-less
160 // "synced" random, using common seed for all players
161 public uint syncrandu31 () {
162 pragma(inline
, true);
163 return (prngSyncSeed
= prngR31next(prngSyncSeed
));
167 // ////////////////////////////////////////////////////////////////////////// //
168 // this is VAT function, argument order is reversed
169 void doWrite (DACSVM vm
, bool donl
) {
170 auto count
= vm
.popInt();
171 while (count
-- > 0) {
172 auto type
= vm
.popInt();
173 switch (cast(VATArgType
)type
) {
174 case VATArgType
.Int
: conwrite(vm
.popInt()); break;
175 case VATArgType
.Uint
: conwrite(vm
.popUint()); break;
176 case VATArgType
.Float
: conwrite(vm
.popFloat()); break;
177 case VATArgType
.StrId
: conwrite(StrId(vm
.popUint()).get
); break;
178 case VATArgType
.ActorId
: conwrite("<actor>"); vm
.popUint(); break; //TODO
179 default: conwrite("<invalid-type>"); vm
.popUint(); break; //TODO
182 if (donl
) conwriteln();
183 // push dummy return value
188 // ////////////////////////////////////////////////////////////////////////// //
189 void animClearFrames (StrId classtype
, StrId classname
, StrId state
) {
190 auto adef
= findActorDef(classtype
.get
, classname
.get
);
191 if (adef
is null) throw new Exception("animClearFrames: actor '"~classtype
.get
~":"~classname
.get
~"' not found!");
192 adef
.clearFrames(state
);
196 void animAddFrame (StrId classtype
, StrId classname
, StrId state
, uint dir
, StrId sprname
) {
197 auto adef
= findActorDef(classtype
.get
, classname
.get
);
198 if (adef
is null) throw new Exception("animAddFrame: actor '"~classtype
.get
~":"~classname
.get
~"' not found!");
199 if (dir
!= 0) dir
= 1; //TODO: process mirror flag here
200 adef
.addFrame(state
, dir
, sprname
);
204 // ////////////////////////////////////////////////////////////////////////// //
205 public void registerAPI () {
208 FuncPool
["write"] = delegate void (FuncPool
.FuncInfo fi
, DACSVM vm
) { doWrite(vm
, false); };
209 FuncPool
["writeln"] = delegate void (FuncPool
.FuncInfo fi
, DACSVM vm
) { doWrite(vm
, true); };
211 FuncPool
["syncrandu31"] = &syncrandu31
;
213 FuncPool
["animClearFrames"] = &animClearFrames
;
214 FuncPool
["animAddFrame"] = &animAddFrame
;
216 FuncPool
["actorSetAnimation"] = function void (ActorId me
, StrId state
) {
217 if (!me
.valid
) return;
218 if (auto adef
= findActorDef(me
.classtype
!string
, me
.classname
!string
)) {
219 me
.zAnimstate
= state
;
224 FuncPool
["getPlayer"] = function ActorId () { assert(0); };
226 // initialize actor animation
227 foreach (ActorDef adef
; actordefs
.byValue
) {
228 adef
.callAnimInit(dvm
);
233 // ////////////////////////////////////////////////////////////////////////// //
234 public void loadMapMonsters () {
235 assert(map
!is null);
236 foreach (ref thing
; map
.things
) {
237 if (thing
.dmonly
) continue;
238 if (auto did
= thing
.type
in d2dactordefsById
) {
239 if (did
.classtype
== "item") continue;
240 if (did
.classtype
== "playerstart") continue;
242 auto adef
= findD2DActorDef(thing
.type
);
244 if (auto did
= thing
.type
in d2dactordefsById
) {
245 conwriteln("ignoring D2D thing '", did
.fullname
, "'");
247 conwriteln("ignoring unknown D2D thing with mapid ", thing
.type
);
251 // load graphics (we'll load all graphics)
252 //adef.loadGraphics();
253 // create actor and initialize it
254 auto aid
= Actor
.alloc
;
255 aid
.classtype
= StrPool
.intern(adef
.classtype
);
256 aid
.classname
= StrPool
.intern(adef
.classname
);
257 if (auto did
= thing
.type
in d2dactordefsById
) {
258 assert(did
.classtype
== adef
.classtype
);
259 assert(did
.classname
== adef
.classname
);
260 conwriteln("mapid=", thing
.type
, "; ", adef
.classtype
, ":", adef
.classname
, "; id=", aid
.id
);
261 assert(aid
.classtype
!string
== adef
.classtype
);
262 assert(aid
.classname
!string
== adef
.classname
);
266 aid
.state
= StrPool
.MNST_SLEEP
;
267 aid
.x
= cast(int)thing
.x
;
268 aid
.y
= cast(int)thing
.y
;
269 aid
.dir
= cast(uint)(thing
.right ?
1 : 0);
270 adef
.callInit(dvm
, aid
);
273 foreach (ActorDef adef
; actordefs
.byValue
) adef
.loadGraphics();
274 //Actor.dumpActors();
278 // ////////////////////////////////////////////////////////////////////////// //
279 public void doActorsThink () {
280 Actor
.forEach((ActorId me
) {
281 // `act` is always valid here
282 if (auto adef
= findActorDef(me
.classtype
!string
, me
.classname
!string
)) {
283 adef
.callThink(dvm
, me
);
284 int aidx
= me
.zAnimidx
!int;
285 int nidx
= adef
.nextAnimIdx(me
.zAnimstate
!StrId
, me
.dir
!uint, aidx
);
286 //conwriteln("actor ", me.id, " (", me.classtype!string, me.classname!string, "): state=", me.zAnimstate!string, "; aidx=", aidx, "; nidx=", nidx);
288 assert(me
.zAnimidx
!int == nidx
);
291 //{ import std.stdio : stdout; stdout.writeln("========================================="); }
292 //Actor.dumpActors();