thats why magic values sux
[twcon.git] / datasrc / compile.py
blob088e500a89a766c5dd92fca55d1a230e585ddb2c
1 import os, imp, sys
2 from datatypes import *
3 import content
4 import network
6 def create_enum_table(names, num):
7 lines = []
8 lines += ["enum", "{"]
9 lines += ["\t%s=0,"%names[0]]
10 for name in names[1:]:
11 lines += ["\t%s,"%name]
12 lines += ["\t%s" % num, "};"]
13 return lines
15 def create_flags_table(names):
16 lines = []
17 lines += ["enum", "{"]
18 i = 0
19 for name in names:
20 lines += ["\t%s = 1<<%d," % (name,i)]
21 i += 1
22 lines += ["};"]
23 return lines
25 def EmitEnum(names, num):
26 print("enum")
27 print("{")
28 print("\t%s=0," % names[0])
29 for name in names[1:]:
30 print("\t%s," % name)
31 print("\t%s" % num)
32 print("};")
34 def EmitFlags(names, num):
35 print("enum")
36 print("{")
37 i = 0
38 for name in names:
39 print("\t%s = 1<<%d," % (name,i))
40 i += 1
41 print("};")
43 gen_network_header = False
44 gen_network_source = False
45 gen_client_content_header = False
46 gen_client_content_source = False
47 gen_server_content_header = False
48 gen_server_content_source = False
50 if "network_header" in sys.argv: gen_network_header = True
51 if "network_source" in sys.argv: gen_network_source = True
52 if "client_content_header" in sys.argv: gen_client_content_header = True
53 if "client_content_source" in sys.argv: gen_client_content_source = True
54 if "server_content_header" in sys.argv: gen_server_content_header = True
55 if "server_content_source" in sys.argv: gen_server_content_source = True
57 if gen_client_content_header:
58 print("#ifndef CLIENT_CONTENT_HEADER")
59 print("#define CLIENT_CONTENT_HEADER")
61 if gen_server_content_header:
62 print("#ifndef SERVER_CONTENT_HEADER")
63 print("#define SERVER_CONTENT_HEADER")
66 if gen_client_content_header or gen_server_content_header:
67 # emit the type declarations
68 contentlines = open("datasrc/content.py", "rb").readlines()
69 order = []
70 for line in contentlines:
71 line = line.strip()
72 if line[:6] == "class ".encode() and "(Struct)".encode() in line:
73 order += [line.split()[1].split("(".encode())[0].decode("ascii")]
74 for name in order:
75 EmitTypeDeclaration(content.__dict__[name])
77 # the container pointer
78 print('extern CDataContainer *g_pData;')
80 # enums
81 EmitEnum(["IMAGE_%s"%i.name.value.upper() for i in content.container.images.items], "NUM_IMAGES")
82 EmitEnum(["ANIM_%s"%i.name.value.upper() for i in content.container.animations.items], "NUM_ANIMS")
83 EmitEnum(["SPRITE_%s"%i.name.value.upper() for i in content.container.sprites.items], "NUM_SPRITES")
85 if gen_client_content_source or gen_server_content_source:
86 if gen_client_content_source:
87 print('#include "client_data.h"')
88 if gen_server_content_source:
89 print('#include "server_data.h"')
90 EmitDefinition(content.container, "datacontainer")
91 print('CDataContainer *g_pData = &datacontainer;')
93 # NETWORK
94 if gen_network_header:
96 print("#ifndef GAME_GENERATED_PROTOCOL_H")
97 print("#define GAME_GENERATED_PROTOCOL_H")
98 print(network.RawHeader)
100 for e in network.Enums:
101 for l in create_enum_table(["%s_%s"%(e.name, v) for v in e.values], 'NUM_%sS'%e.name): print(l)
102 print("")
104 for e in network.Flags:
105 for l in create_flags_table(["%s_%s" % (e.name, v) for v in e.values]): print(l)
106 print("")
108 for l in create_enum_table(["NETOBJ_INVALID"]+[o.enum_name for o in network.Objects], "NUM_NETOBJTYPES"): print(l)
109 print("")
110 for l in create_enum_table(["NETMSG_INVALID"]+[o.enum_name for o in network.Messages], "NUM_NETMSGTYPES"): print(l)
111 print("")
113 for item in network.Objects + network.Messages:
114 for line in item.emit_declaration():
115 print(line)
116 print("")
118 EmitEnum(["SOUND_%s"%i.name.value.upper() for i in content.container.sounds.items], "NUM_SOUNDS")
119 EmitEnum(["WEAPON_%s"%i.name.value.upper() for i in content.container.weapons.id.items], "NUM_WEAPONS")
121 print("""
123 class CNetObjHandler
125 const char *m_pMsgFailedOn;
126 const char *m_pObjCorrectedOn;
127 char m_aMsgData[1024];
128 int m_NumObjCorrections;
129 int ClampInt(const char *pErrorMsg, int Value, int Min, int Max);
131 static const char *ms_apObjNames[];
132 static int ms_aObjSizes[];
133 static const char *ms_apMsgNames[];
135 public:
136 CNetObjHandler();
138 int ValidateObj(int Type, void *pData, int Size);
139 const char *GetObjName(int Type);
140 int GetObjSize(int Type);
141 int NumObjCorrections();
142 const char *CorrectedObjOn();
144 const char *GetMsgName(int Type);
145 void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker);
146 const char *FailedMsgOn();
149 """)
151 print("#endif // GAME_GENERATED_PROTOCOL_H")
154 if gen_network_source:
155 # create names
156 lines = []
158 lines += ['#include <engine/shared/protocol.h>']
159 lines += ['#include <engine/message.h>']
160 lines += ['#include "protocol.h"']
162 lines += ['CNetObjHandler::CNetObjHandler()']
163 lines += ['{']
164 lines += ['\tm_pMsgFailedOn = "";']
165 lines += ['\tm_pObjCorrectedOn = "";']
166 lines += ['\tm_NumObjCorrections = 0;']
167 lines += ['}']
168 lines += ['']
169 lines += ['int CNetObjHandler::NumObjCorrections() { return m_NumObjCorrections; }']
170 lines += ['const char *CNetObjHandler::CorrectedObjOn() { return m_pObjCorrectedOn; }']
171 lines += ['const char *CNetObjHandler::FailedMsgOn() { return m_pMsgFailedOn; }']
172 lines += ['']
173 lines += ['']
174 lines += ['']
175 lines += ['']
176 lines += ['']
178 lines += ['static const int max_int = 0x7fffffff;']
180 lines += ['int CNetObjHandler::ClampInt(const char *pErrorMsg, int Value, int Min, int Max)']
181 lines += ['{']
182 lines += ['\tif(Value < Min) { m_pObjCorrectedOn = pErrorMsg; m_NumObjCorrections++; return Min; }']
183 lines += ['\tif(Value > Max) { m_pObjCorrectedOn = pErrorMsg; m_NumObjCorrections++; return Max; }']
184 lines += ['\treturn Value;']
185 lines += ['}']
187 lines += ["const char *CNetObjHandler::ms_apObjNames[] = {"]
188 lines += ['\t"invalid",']
189 lines += ['\t"%s",' % o.name for o in network.Objects]
190 lines += ['\t""', "};", ""]
192 lines += ["int CNetObjHandler::ms_aObjSizes[] = {"]
193 lines += ['\t0,']
194 lines += ['\tsizeof(%s),' % o.struct_name for o in network.Objects]
195 lines += ['\t0', "};", ""]
198 lines += ['const char *CNetObjHandler::ms_apMsgNames[] = {']
199 lines += ['\t"invalid",']
200 for msg in network.Messages:
201 lines += ['\t"%s",' % msg.name]
202 lines += ['\t""']
203 lines += ['};']
204 lines += ['']
206 lines += ['const char *CNetObjHandler::GetObjName(int Type)']
207 lines += ['{']
208 lines += ['\tif(Type < 0 || Type >= NUM_NETOBJTYPES) return "(out of range)";']
209 lines += ['\treturn ms_apObjNames[Type];']
210 lines += ['};']
211 lines += ['']
213 lines += ['int CNetObjHandler::GetObjSize(int Type)']
214 lines += ['{']
215 lines += ['\tif(Type < 0 || Type >= NUM_NETOBJTYPES) return 0;']
216 lines += ['\treturn ms_aObjSizes[Type];']
217 lines += ['};']
218 lines += ['']
221 lines += ['const char *CNetObjHandler::GetMsgName(int Type)']
222 lines += ['{']
223 lines += ['\tif(Type < 0 || Type >= NUM_NETMSGTYPES) return "(out of range)";']
224 lines += ['\treturn ms_apMsgNames[Type];']
225 lines += ['};']
226 lines += ['']
229 for l in lines:
230 print(l)
232 if 0:
233 for item in network.Objects:
234 for line in item.emit_validate():
235 print(line)
236 print("")
238 # create validate tables
239 lines = []
240 lines += ['static int validate_invalid(void *data, int size) { return -1; }']
241 lines += ["typedef int(*VALIDATEFUNC)(void *data, int size);"]
242 lines += ["static VALIDATEFUNC validate_funcs[] = {"]
243 lines += ['\tvalidate_invalid,']
244 lines += ['\tvalidate_%s,' % o.name for o in network.Objects]
245 lines += ["\t0x0", "};", ""]
247 lines += ["int netobj_validate(int type, void *data, int size)"]
248 lines += ["{"]
249 lines += ["\tif(type < 0 || type >= NUM_NETOBJTYPES) return -1;"]
250 lines += ["\treturn validate_funcs[type](data, size);"]
251 lines += ["};", ""]
253 lines = []
254 lines += ['int CNetObjHandler::ValidateObj(int Type, void *pData, int Size)']
255 lines += ['{']
256 lines += ['\tswitch(Type)']
257 lines += ['\t{']
259 for item in network.Objects:
260 for line in item.emit_validate():
261 lines += ["\t" + line]
262 lines += ['\t']
263 lines += ['\t}']
264 lines += ['\treturn -1;']
265 lines += ['};']
266 lines += ['']
268 #int Validate(int Type, void *pData, int Size);
270 if 0:
271 for item in network.Messages:
272 for line in item.emit_unpack():
273 print(line)
274 print("")
276 lines += ['static void *secure_unpack_invalid(CUnpacker *pUnpacker) { return 0; }']
277 lines += ['typedef void *(*SECUREUNPACKFUNC)(CUnpacker *pUnpacker);']
278 lines += ['static SECUREUNPACKFUNC secure_unpack_funcs[] = {']
279 lines += ['\tsecure_unpack_invalid,']
280 for msg in network.Messages:
281 lines += ['\tsecure_unpack_%s,' % msg.name]
282 lines += ['\t0x0']
283 lines += ['};']
286 lines += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)']
287 lines += ['{']
288 lines += ['\tm_pMsgFailedOn = 0;']
289 lines += ['\tswitch(Type)']
290 lines += ['\t{']
293 for item in network.Messages:
294 for line in item.emit_unpack():
295 lines += ["\t" + line]
296 lines += ['\t']
298 lines += ['\tdefault:']
299 lines += ['\t\tm_pMsgFailedOn = "(type out of range)";']
300 lines += ['\t\tbreak;']
301 lines += ['\t}']
302 lines += ['\t']
303 lines += ['\tif(pUnpacker->Error())']
304 lines += ['\t\tm_pMsgFailedOn = "(unpack error)";']
305 lines += ['\t']
306 lines += ['\tif(m_pMsgFailedOn)']
307 lines += ['\t\treturn 0;']
308 lines += ['\tm_pMsgFailedOn = "";']
309 lines += ['\treturn m_aMsgData;']
310 lines += ['};']
311 lines += ['']
314 for l in lines:
315 print(l)
317 if gen_client_content_header or gen_server_content_header:
318 print("#endif")