ddnet/datasrc/seven/compile.py

326 lines
9.1 KiB
Python
Raw Normal View History

2020-04-16 08:46:43 +00:00
import sys
2020-12-02 14:22:26 +00:00
from .datatypes import EmitDefinition, EmitTypeDeclaration
2020-04-18 12:27:41 +00:00
from . import content
from . import network
2020-04-16 08:46:43 +00:00
def create_enum_table(names, num):
lines = []
lines += ["enum", "{"]
lines += ["\t%s=0,"%names[0]]
for name in names[1:]:
lines += ["\t%s,"%name]
lines += ["\t%s" % num, "};"]
return lines
def create_flags_table(names):
lines = []
lines += ["enum", "{"]
i = 0
for name in names:
lines += ["\t%s = 1<<%d," % (name,i)]
i += 1
lines += ["};"]
return lines
def EmitEnum(names, num):
print("enum")
print("{")
print("\t%s=0," % names[0])
for name in names[1:]:
print("\t%s," % name)
print("\t%s" % num)
print("};")
2020-12-02 14:22:26 +00:00
def EmitFlags(names):
2020-04-16 08:46:43 +00:00
print("enum")
print("{")
i = 0
for name in names:
print("\t%s = 1<<%d," % (name,i))
i += 1
print("};")
2020-12-02 14:22:26 +00:00
def main():
gen_network_header = "network_header" in sys.argv
gen_network_source = "network_source" in sys.argv
gen_client_content_header = "client_content_header" in sys.argv
gen_client_content_source = "client_content_source" in sys.argv
gen_server_content_header = "server_content_header" in sys.argv
gen_server_content_source = "server_content_source" in sys.argv
if gen_client_content_header:
print("#ifndef CLIENT_CONTENT7_HEADER")
print("#define CLIENT_CONTENT7_HEADER")
if gen_server_content_header:
print("#ifndef SERVER_CONTENT7_HEADER")
print("#define SERVER_CONTENT7_HEADER")
if gen_client_content_header or gen_server_content_header:
# print some includes
print('#include <engine/graphics.h>')
print('#include <engine/sound.h>')
print("namespace client_data7 {")
# emit the type declarations
contentlines = open("datasrc/content.py", "rb").readlines()
order = []
for line in contentlines:
line = line.strip()
if line[:6] == "class ".encode() and "(Struct)".encode() in line:
order += [line.split()[1].split("(".encode())[0].decode("ascii")]
for name in order:
EmitTypeDeclaration(content.__dict__[name])
# the container pointer
print('extern CDataContainer *g_pData;')
# enums
EmitEnum(["IMAGE_%s"%i.name.value.upper() for i in content.container.images.items], "NUM_IMAGES")
EmitEnum(["ANIM_%s"%i.name.value.upper() for i in content.container.animations.items], "NUM_ANIMS")
EmitEnum(["SPRITE_%s"%i.name.value.upper() for i in content.container.sprites.items], "NUM_SPRITES")
if gen_client_content_source or gen_server_content_source:
if gen_client_content_source:
print('#include "client_data7.h"')
if gen_server_content_source:
print('#include "server_data.h"')
print("namespace client_data7 {")
EmitDefinition(content.container, "datacontainer")
print('CDataContainer *g_pData = &datacontainer;')
print("}")
2020-04-16 08:46:43 +00:00
# NETWORK
2020-12-02 14:22:26 +00:00
if gen_network_header:
print("#ifndef GAME_GENERATED_PROTOCOL7_H")
print("#define GAME_GENERATED_PROTOCOL7_H")
print("#include <engine/shared/protocol.h>")
print("#include <engine/message.h>")
print("namespace protocol7 {")
print(network.RawHeader)
for e in network.Enums:
for l in create_enum_table(["%s_%s"%(e.name, v) for v in e.values], 'NUM_%sS'%e.name):
print(l)
print("")
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
for e in network.Flags:
for l in create_flags_table(["%s_%s" % (e.name, v) for v in e.values]):
print(l)
print("")
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
for l in create_enum_table(["NETOBJ_INVALID"]+[o.enum_name for o in network.Objects], "NUM_NETOBJTYPES"):
print(l)
2020-04-16 08:46:43 +00:00
print("")
2020-12-02 14:22:26 +00:00
for l in create_enum_table(["NETMSG_INVALID"]+[o.enum_name for o in network.Messages], "NUM_NETMSGTYPES"):
print(l)
2020-04-16 08:46:43 +00:00
print("")
2020-12-02 14:22:26 +00:00
print("""
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
template<typename T, typename = void>
struct is_sixup {
constexpr static bool value = false;
};
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
template<typename T>
struct is_sixup<T, void_t<typename T::is_sixup>> {
constexpr static bool value = true;
};
""")
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
for item in network.Objects + network.Messages:
for line in item.emit_declaration():
print(line)
print("")
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
EmitEnum(["SOUND_%s"%i.name.value.upper() for i in content.container.sounds.items], "NUM_SOUNDS")
EmitEnum(["WEAPON_%s"%i.name.value.upper() for i in content.container.weapons.id.items], "NUM_WEAPONS")
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
print("""
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
class CNetObjHandler
{
const char *m_pMsgFailedOn;
char m_aMsgData[1024];
const char *m_pObjFailedOn;
int m_NumObjFailures;
bool CheckInt(const char *pErrorMsg, int Value, int Min, int Max);
bool CheckFlag(const char *pErrorMsg, int Value, int Mask);
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
static const char *ms_apObjNames[];
static int ms_aObjSizes[];
static const char *ms_apMsgNames[];
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
public:
CNetObjHandler();
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
int ValidateObj(int Type, const void *pData, int Size);
const char *GetObjName(int Type) const;
int GetObjSize(int Type) const;
const char *FailedObjOn() const;
int NumObjFailures() const;
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
const char *GetMsgName(int Type) const;
void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker);
const char *FailedMsgOn() const;
};
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
""")
print("}")
print("#endif // GAME_GENERATED_PROTOCOL7_H")
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
if gen_network_source:
# create names
2020-04-16 08:46:43 +00:00
lines = []
2020-12-02 14:22:26 +00:00
lines += ['#include "protocol7.h"']
lines += ['#include <engine/shared/protocol.h>']
lines += ['#include <engine/message.h>']
lines += ['namespace protocol7 {']
lines += ['CNetObjHandler::CNetObjHandler()']
lines += ['{']
lines += ['\tm_pMsgFailedOn = "";']
lines += ['\tm_pObjFailedOn = "";']
lines += ['\tm_NumObjFailures = 0;']
lines += ['}']
lines += ['']
lines += ['const char *CNetObjHandler::FailedObjOn() const { return m_pObjFailedOn; }']
lines += ['int CNetObjHandler::NumObjFailures() const { return m_NumObjFailures; }']
lines += ['const char *CNetObjHandler::FailedMsgOn() const { return m_pMsgFailedOn; }']
lines += ['']
lines += ['']
lines += ['']
lines += ['']
lines += ['static const int max_int = 0x7fffffff;']
lines += ['']
lines += ['bool CNetObjHandler::CheckInt(const char *pErrorMsg, int Value, int Min, int Max)']
lines += ['{']
lines += ['\tif(Value < Min || Value > Max) { m_pObjFailedOn = pErrorMsg; m_NumObjFailures++; return false; }']
lines += ['\treturn true;']
lines += ['}']
lines += ['']
lines += ['bool CNetObjHandler::CheckFlag(const char *pErrorMsg, int Value, int Mask)']
lines += ['{']
lines += ['\tif((Value&Mask) != Value) { m_pObjFailedOn = pErrorMsg; m_NumObjFailures++; return false; }']
lines += ['\treturn true;']
lines += ['}']
lines += ['']
lines += ["const char *CNetObjHandler::ms_apObjNames[] = {"]
lines += ['\t"invalid",']
lines += ['\t"%s",' % o.name for o in network.Objects]
lines += ['\t""', "};", ""]
lines += ["int CNetObjHandler::ms_aObjSizes[] = {"]
lines += ['\t0,']
lines += ['\tsizeof(%s),' % o.struct_name for o in network.Objects]
lines += ['\t0', "};", ""]
lines += ['const char *CNetObjHandler::ms_apMsgNames[] = {']
lines += ['\t"invalid",']
for msg in network.Messages:
lines += ['\t"%s",' % msg.name]
lines += ['\t""']
lines += ['};']
lines += ['']
lines += ['const char *CNetObjHandler::GetObjName(int Type) const']
lines += ['{']
lines += ['\tif(Type < 0 || Type >= NUM_NETOBJTYPES) return "(out of range)";']
lines += ['\treturn ms_apObjNames[Type];']
lines += ['};']
lines += ['']
lines += ['int CNetObjHandler::GetObjSize(int Type) const']
lines += ['{']
lines += ['\tif(Type < 0 || Type >= NUM_NETOBJTYPES) return 0;']
lines += ['\treturn ms_aObjSizes[Type];']
lines += ['};']
lines += ['']
lines += ['const char *CNetObjHandler::GetMsgName(int Type) const']
lines += ['{']
lines += ['\tif(Type < 0 || Type >= NUM_NETMSGTYPES) return "(out of range)";']
lines += ['\treturn ms_apMsgNames[Type];']
lines += ['};']
lines += ['']
for l in lines:
print(l)
lines = []
lines += ['int CNetObjHandler::ValidateObj(int Type, const void *pData, int Size)']
lines += ['{']
lines += ['\tswitch(Type)']
lines += ['\t{']
for item in network.Objects:
for line in item.emit_validate():
lines += ["\t" + line]
lines += ['\t']
lines += ['\t}']
lines += ['\treturn -1;']
lines += ['};']
lines += ['']
lines += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)']
lines += ['{']
lines += ['\tm_pMsgFailedOn = 0;']
lines += ['\tm_pObjFailedOn = 0;']
lines += ['\tswitch(Type)']
lines += ['\t{']
2020-04-16 08:46:43 +00:00
for item in network.Messages:
for line in item.emit_unpack():
2020-12-02 14:22:26 +00:00
lines += ["\t" + line]
lines += ['\t']
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
lines += ['\tdefault:']
lines += ['\t\tm_pMsgFailedOn = "(type out of range)";']
lines += ['\t\tbreak;']
lines += ['\t}']
lines += ['\t']
lines += ['\tif(pUnpacker->Error())']
lines += ['\t\tm_pMsgFailedOn = "(unpack error)";']
lines += ['\t']
lines += ['\tif(m_pMsgFailedOn || m_pObjFailedOn) {']
lines += ['\t\tif(!m_pMsgFailedOn)']
lines += ['\t\t\tm_pMsgFailedOn = "";']
lines += ['\t\tif(!m_pObjFailedOn)']
lines += ['\t\t\tm_pObjFailedOn = "";']
lines += ['\t\treturn 0;']
lines += ['\t}']
lines += ['\tm_pMsgFailedOn = "";']
lines += ['\tm_pObjFailedOn = "";']
lines += ['\treturn m_aMsgData;']
2020-04-16 08:46:43 +00:00
lines += ['};']
2020-12-02 14:22:26 +00:00
lines += ['}']
lines += ['']
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
for l in lines:
print(l)
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
if gen_client_content_header or gen_server_content_header:
print("}")
print("#endif")
2020-04-16 08:46:43 +00:00
2020-12-02 14:22:26 +00:00
if __name__ == '__main__':
main()