3371: Add shellcheck & pylint r=heinrich5991 a=def-

<!-- What is the motivation for the changes of this pull request -->

## Checklist

- [ ] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: def <dennis@felsin9.de>
Co-authored-by: ChillerDragon <chillerdragon@gmail.com>
This commit is contained in:
bors[bot] 2020-12-09 09:55:26 +00:00 committed by GitHub
commit d9bda64fdf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 1225 additions and 1629 deletions

View file

@ -19,23 +19,24 @@ jobs:
- name: Prepare - name: Prepare
run: | run: |
sudo apt-get update -y sudo apt-get update -y
sudo apt-get install clang-format imagemagick ddnet-tools -y sudo apt-get install clang-format imagemagick ddnet-tools shellcheck pkg-config cmake libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev pylint3 python3-clang -y
- name: Check style
run: |
clang-format -version
scripts/fix_style.py --dry-run
scripts/check_header_guards.py
scripts/languages/update_all.py
- name: Prepare build dilate
run: |
sudo apt-get update -y
sudo apt-get install pkg-config cmake libfreetype6-dev libnotify-dev libsdl2-dev libsqlite3-dev -y
- name: Build dilate
run: |
mkdir release mkdir release
cd release cd release
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DDOWNLOAD_GTEST=OFF -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=. .. cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DDOWNLOAD_GTEST=OFF -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=. ..
cmake --build . --config Release --target dilate --parallel cmake --build . --config Release --target dilate --parallel
- name: Check if images are dilated - name: Check clang-format
run: clang-format -version
- name: Check fix_style
run: scripts/fix_style.py --dry-run
- name: Check header guards
run: scripts/check_header_guards.py
- name: Check languages
run: scripts/languages/update_all.py
- name: Check dilated images
run: scripts/check_dilate.sh release data
- name: Shellcheck
run: find . -type f -name '*.sh' -print0 | xargs -0 shellcheck
- name: Pylint
run: | run: |
scripts/check_dilate.sh release data pylint --version
find . -type f -name "*.py" -print0 | xargs -0 pylint

24
.pylintrc Normal file
View file

@ -0,0 +1,24 @@
[MESSAGES CONTROL]
indent-string=' '
disable=
C0103, # invalid-name
C0114, # missing-module-docstring
C0115, # missing-class-docstring
C0116, # missing-function-docstring
C0301, # line-too-long
C0326, # bad-whitespace
C0330, # bad-continuation
E0402, # relative-beyond-top-level
R0201, # no-self-use
R0801, # duplicate-code
R0902, # too-many-instance-attributes
R0903, # too-few-public-methods
R0911, # too-many-return-statements
R0912, # too-many-branches
R0913, # too-many-arguments
R0914, # too-many-locals
R0915, # too-many-statements
W0511, # fixme
W0603, # global-statement

View file

@ -1,6 +1,5 @@
import os
import sys import sys
from datatypes import * from datatypes import EmitDefinition, EmitTypeDeclaration
import content import content
import network import network
@ -31,7 +30,7 @@ def EmitEnum(names, num):
print("\t%s" % num) print("\t%s" % num)
print("};") print("};")
def EmitFlags(names, num): def EmitFlags(names):
print("enum") print("enum")
print("{") print("{")
i = 0 i = 0
@ -40,30 +39,24 @@ def EmitFlags(names, num):
i += 1 i += 1
print("};") print("};")
gen_network_header = False def main():
gen_network_source = False gen_network_header = "network_header" in sys.argv
gen_client_content_header = False gen_network_source = "network_source" in sys.argv
gen_client_content_source = False gen_client_content_header = "client_content_header" in sys.argv
gen_server_content_header = False gen_client_content_source = "client_content_source" in sys.argv
gen_server_content_source = False gen_server_content_header = "server_content_header" in sys.argv
gen_server_content_source = "server_content_source" in sys.argv
if "network_header" in sys.argv: gen_network_header = True if gen_client_content_header:
if "network_source" in sys.argv: gen_network_source = True
if "client_content_header" in sys.argv: gen_client_content_header = True
if "client_content_source" in sys.argv: gen_client_content_source = True
if "server_content_header" in sys.argv: gen_server_content_header = True
if "server_content_source" in sys.argv: gen_server_content_source = True
if gen_client_content_header:
print("#ifndef CLIENT_CONTENT_HEADER") print("#ifndef CLIENT_CONTENT_HEADER")
print("#define CLIENT_CONTENT_HEADER") print("#define CLIENT_CONTENT_HEADER")
if gen_server_content_header: if gen_server_content_header:
print("#ifndef SERVER_CONTENT_HEADER") print("#ifndef SERVER_CONTENT_HEADER")
print("#define SERVER_CONTENT_HEADER") print("#define SERVER_CONTENT_HEADER")
if gen_client_content_header or gen_server_content_header: if gen_client_content_header or gen_server_content_header:
# print some includes # print some includes
print('#include <engine/graphics.h>') print('#include <engine/graphics.h>')
@ -85,7 +78,7 @@ if gen_client_content_header or gen_server_content_header:
EmitEnum(["ANIM_%s"%i.name.value.upper() for i in content.container.animations.items], "NUM_ANIMS") 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") 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 or gen_server_content_source:
if gen_client_content_source: if gen_client_content_source:
print('#include "client_data.h"') print('#include "client_data.h"')
if gen_server_content_source: if gen_server_content_source:
@ -94,7 +87,7 @@ if gen_client_content_source or gen_server_content_source:
print('CDataContainer *g_pData = &datacontainer;') print('CDataContainer *g_pData = &datacontainer;')
# NETWORK # NETWORK
if gen_network_header: if gen_network_header:
print("#ifndef GAME_GENERATED_PROTOCOL_H") print("#ifndef GAME_GENERATED_PROTOCOL_H")
print("#define GAME_GENERATED_PROTOCOL_H") print("#define GAME_GENERATED_PROTOCOL_H")
@ -103,24 +96,30 @@ if gen_network_header:
print(network.RawHeader) print(network.RawHeader)
for e in network.Enums: 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) for l in create_enum_table(["%s_%s"%(e.name, v) for v in e.values], 'NUM_%sS'%e.name): # pylint: disable=E1101
print(l)
print("") print("")
for e in network.Flags: for e in network.Flags:
for l in create_flags_table(["%s_%s" % (e.name, v) for v in e.values]): print(l) for l in create_flags_table(["%s_%s" % (e.name, v) for v in e.values]):
print(l)
print("") print("")
non_extended = [o for o in network.Objects if o.ex is None] non_extended = [o for o in network.Objects if o.ex is None]
extended = [o for o in network.Objects if o.ex is not None] extended = [o for o in network.Objects if o.ex is not None]
for l in create_enum_table(["NETOBJTYPE_EX"]+[o.enum_name for o in non_extended], "NUM_NETOBJTYPES"): print(l) for l in create_enum_table(["NETOBJTYPE_EX"]+[o.enum_name for o in non_extended], "NUM_NETOBJTYPES"):
for l in create_enum_table(["__NETOBJTYPE_UUID_HELPER=OFFSET_GAME_UUID-1"]+[o.enum_name for o in extended], "OFFSET_NETMSGTYPE_UUID"): print(l) print(l)
for l in create_enum_table(["__NETOBJTYPE_UUID_HELPER=OFFSET_GAME_UUID-1"]+[o.enum_name for o in extended], "OFFSET_NETMSGTYPE_UUID"):
print(l)
print("") print("")
non_extended = [o for o in network.Messages if o.ex is None] non_extended = [o for o in network.Messages if o.ex is None]
extended = [o for o in network.Messages if o.ex is not None] extended = [o for o in network.Messages if o.ex is not None]
for l in create_enum_table(["NETMSGTYPE_EX"]+[o.enum_name for o in non_extended], "NUM_NETMSGTYPES"): print(l) for l in create_enum_table(["NETMSGTYPE_EX"]+[o.enum_name for o in non_extended], "NUM_NETMSGTYPES"):
print(l)
print("") print("")
for l in create_enum_table(["__NETMSGTYPE_UUID_HELPER=OFFSET_NETMSGTYPE_UUID-1"]+[o.enum_name for o in extended], "OFFSET_MAPITEMTYPE_UUID"): print(l) for l in create_enum_table(["__NETMSGTYPE_UUID_HELPER=OFFSET_NETMSGTYPE_UUID-1"]+[o.enum_name for o in extended], "OFFSET_MAPITEMTYPE_UUID"):
print(l)
print("") print("")
for item in network.Objects + network.Messages: for item in network.Objects + network.Messages:
@ -133,8 +132,8 @@ if gen_network_header:
print(""" print("""
class CNetObjHandler class CNetObjHandler
{ {
const char *m_pMsgFailedOn; const char *m_pMsgFailedOn;
const char *m_pObjCorrectedOn; const char *m_pObjCorrectedOn;
char m_aMsgData[1024]; char m_aMsgData[1024];
@ -145,7 +144,7 @@ class CNetObjHandler
static int ms_aObjSizes[]; static int ms_aObjSizes[];
static const char *ms_apMsgNames[]; static const char *ms_apMsgNames[];
public: public:
CNetObjHandler(); CNetObjHandler();
int ValidateObj(int Type, void *pData, int Size); int ValidateObj(int Type, void *pData, int Size);
@ -158,14 +157,14 @@ public:
void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker); void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker);
bool TeeHistorianRecordMsg(int Type); bool TeeHistorianRecordMsg(int Type);
const char *FailedMsgOn(); const char *FailedMsgOn();
}; };
""") """)
print("#endif // GAME_GENERATED_PROTOCOL_H") print("#endif // GAME_GENERATED_PROTOCOL_H")
if gen_network_source: if gen_network_source:
# create names # create names
lines = [] lines = []
@ -246,12 +245,6 @@ if gen_network_source:
for l in lines: for l in lines:
print(l) print(l)
if 0:
for item in network.Objects:
for line in item.emit_validate():
print(line)
print("")
# create validate tables # create validate tables
lines = [] lines = []
lines += ['static int validate_invalid(void *data, int size) { return -1; }'] lines += ['static int validate_invalid(void *data, int size) { return -1; }']
@ -286,24 +279,6 @@ if gen_network_source:
lines += ['}'] lines += ['}']
lines += [''] lines += ['']
#int Validate(int Type, void *pData, int Size);
if 0:
for item in network.Messages:
for line in item.emit_unpack():
print(line)
print("")
lines += ['static void *secure_unpack_invalid(CUnpacker *pUnpacker) { return 0; }']
lines += ['typedef void *(*SECUREUNPACKFUNC)(CUnpacker *pUnpacker);']
lines += ['static SECUREUNPACKFUNC secure_unpack_funcs[] = {']
lines += ['\tsecure_unpack_invalid,']
for msg in network.Messages:
lines += ['\tsecure_unpack_%s,' % msg.name]
lines += ['\t0x0']
lines += ['};']
#
lines += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)'] lines += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)']
lines += ['{'] lines += ['{']
lines += ['\tm_pMsgFailedOn = 0;'] lines += ['\tm_pMsgFailedOn = 0;']
@ -360,5 +335,8 @@ if gen_network_source:
for l in lines: for l in lines:
print(l) print(l)
if gen_client_content_header or gen_server_content_header: if gen_client_content_header or gen_server_content_header:
print("#endif") print("#endif")
if __name__ == '__main__':
main()

View file

@ -1,5 +1,4 @@
import copy from datatypes import Array, Float, Int, Pointer, String, Struct, TextureHandle
from datatypes import *
class Sound(Struct): class Sound(Struct):
def __init__(self, filename=""): def __init__(self, filename=""):
@ -8,13 +7,13 @@ class Sound(Struct):
self.filename = String(filename) self.filename = String(filename)
class SoundSet(Struct): class SoundSet(Struct):
def __init__(self, name="", files=[]): def __init__(self, name="", files=()):
Struct.__init__(self, "CDataSoundset") Struct.__init__(self, "CDataSoundset")
self.name = String(name) self.name = String(name)
self.sounds = Array(Sound()) self.sounds = Array(Sound())
self.last = Int(-1) self.last = Int(-1)
for name in files: for filename in files:
self.sounds.Add(Sound(name)) self.sounds.Add(Sound(filename))
class Image(Struct): class Image(Struct):
def __init__(self, name="", filename=""): def __init__(self, name="", filename=""):
@ -24,7 +23,7 @@ class Image(Struct):
self.id = TextureHandle() self.id = TextureHandle()
class SpriteSet(Struct): class SpriteSet(Struct):
def __init__(self, name="", image=None, gridx=0, gridy=0): def __init__(self, _name="", image=None, gridx=0, gridy=0):
Struct.__init__(self, "CDataSpriteset") Struct.__init__(self, "CDataSpriteset")
self.image = Pointer(Image, image) # TODO self.image = Pointer(Image, image) # TODO
self.gridx = Int(gridx) self.gridx = Int(gridx)
@ -70,7 +69,7 @@ class Animation(Struct):
self.attach = AnimSequence() self.attach = AnimSequence()
class WeaponSpec(Struct): class WeaponSpec(Struct):
def __init__(self, container=None, name=""): def __init__(self, cont=None, name=""):
Struct.__init__(self, "CDataWeaponspec") Struct.__init__(self, "CDataWeaponspec")
self.name = String(name) self.name = String(name)
self.sprite_body = Pointer(Sprite, Sprite()) self.sprite_body = Pointer(Sprite, Sprite())
@ -91,11 +90,14 @@ class WeaponSpec(Struct):
self.muzzleduration = Float(5) self.muzzleduration = Float(5)
# dig out sprites if we have a container # dig out sprites if we have a container
if container: if cont:
for sprite in container.sprites.items: for sprite in cont.sprites.items:
if sprite.name.value == "weapon_"+name+"_body": self.sprite_body.Set(sprite) if sprite.name.value == "weapon_"+name+"_body":
elif sprite.name.value == "weapon_"+name+"_cursor": self.sprite_cursor.Set(sprite) self.sprite_body.Set(sprite)
elif sprite.name.value == "weapon_"+name+"_proj": self.sprite_proj.Set(sprite) elif sprite.name.value == "weapon_"+name+"_cursor":
self.sprite_cursor.Set(sprite)
elif sprite.name.value == "weapon_"+name+"_proj":
self.sprite_proj.Set(sprite)
elif "weapon_"+name+"_muzzle" in sprite.name.value: elif "weapon_"+name+"_muzzle" in sprite.name.value:
self.sprite_muzzles.Add(Pointer(Sprite, sprite)) self.sprite_muzzles.Add(Pointer(Sprite, sprite))
@ -168,8 +170,8 @@ class DataContainer(Struct):
self.animations = Array(Animation()) self.animations = Array(Animation())
self.weapons = Weapons() self.weapons = Weapons()
def FileList(format, num): def FileList(fmt, num):
return [format%(x+1) for x in range(0,num)] return [fmt%(x+1) for x in range(0,num)]
container = DataContainer() container = DataContainer()
container.sounds.Add(SoundSet("gun_fire", FileList("audio/wp_gun_fire-%02d.wv", 3))) container.sounds.Add(SoundSet("gun_fire", FileList("audio/wp_gun_fire-%02d.wv", 3)))

View file

@ -1,43 +1,34 @@
def get_msgs(): import network
from datatypes import NetMessage import seven.network
import network
def get_msgs():
return ["NETMSG_INVALID"] + [m.enum_name for m in network.Messages] return ["NETMSG_INVALID"] + [m.enum_name for m in network.Messages]
def get_msgs_7(): def get_msgs_7():
from seven.datatypes import NetMessage return ["NETMSG_INVALID"] + [m.enum_name for m in seven.network.Messages]
import seven.network as network
return ["NETMSG_INVALID"] + [m.enum_name for m in network.Messages]
def get_objs(): def get_objs():
from datatypes import NetObject
import network
return ["NETOBJ_INVALID"] + [m.enum_name for m in network.Objects if m.ex is None] return ["NETOBJ_INVALID"] + [m.enum_name for m in network.Objects if m.ex is None]
def get_objs_7(): def get_objs_7():
from seven.datatypes import NetObject return ["NETOBJ_INVALID"] + [m.enum_name for m in seven.network.Objects]
import seven.network as network
return ["NETOBJ_INVALID"] + [m.enum_name for m in network.Objects]
def generate_map(a, b): def generate_map(a, b):
map = [] result = []
for i, m in enumerate(a): for m in a:
try: try:
map += [b.index(m)] result += [b.index(m)]
except ValueError: except ValueError:
map += [-1] result += [-1]
return map return result
def output_map(name, map): def output_map(name, m):
print("static const int gs_{}[{}] = {{".format(name, len(map))) print("static const int gs_{}[{}] = {{".format(name, len(m)))
print(*map, sep=',') print(*m, sep=',')
print("};") print("};")
print("inline int {0}(int a) {{ if(a < 0 || a >= {1}) return -1; return gs_{0}[a]; }}".format(name, len(map))) print("inline int {0}(int a) {{ if(a < 0 || a >= {1}) return -1; return gs_{0}[a]; }}".format(name, len(m)))
def main(): def main():
guard = "GAME_GENERATED_PROTOCOLGLUE" guard = "GAME_GENERATED_PROTOCOLGLUE"

View file

@ -1,5 +1,3 @@
import sys
GlobalIdCounter = 0 GlobalIdCounter = 0
def GetID(): def GetID():
global GlobalIdCounter global GlobalIdCounter
@ -22,10 +20,10 @@ def FixCasing(Str):
NewStr += c.lower() NewStr += c.lower()
return NewStr return NewStr
def FormatName(type, name): def FormatName(typ, name):
if "*" in type: if "*" in typ:
return "m_p" + FixCasing(name) return "m_p" + FixCasing(name)
if "[]" in type: if "[]" in typ:
return "m_a" + FixCasing(name) return "m_a" + FixCasing(name)
return "m_" + FixCasing(name) return "m_" + FixCasing(name)
@ -35,17 +33,21 @@ class BaseType:
self._target_name = "INVALID" self._target_name = "INVALID"
self._id = GetID() # this is used to remember what order the members have in structures etc self._id = GetID() # this is used to remember what order the members have in structures etc
def Identifyer(self): return "x"+str(self._id) def Identifyer(self):
def TargetName(self): return self._target_name return "x"+str(self._id)
def TypeName(self): return self._type_name def TargetName(self):
def ID(self): return self._id; return self._target_name
def TypeName(self):
return self._type_name
def ID(self):
return self._id
def EmitDeclaration(self, name): def EmitDeclaration(self, name):
return ["%s %s;"%(self.TypeName(), FormatName(self.TypeName(), name))] return ["%s %s;"%(self.TypeName(), FormatName(self.TypeName(), name))]
def EmitPreDefinition(self, target_name): def EmitPreDefinition(self, target_name):
self._target_name = target_name self._target_name = target_name
return [] return []
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return [] return []
class MemberType: class MemberType:
@ -64,15 +66,10 @@ class Struct(BaseType):
if name[0] == "_": if name[0] == "_":
continue continue
m += [MemberType(name, self.__dict__[name])] m += [MemberType(name, self.__dict__[name])]
try:
m.sort(key = sorter) m.sort(key = sorter)
except:
for v in m:
print(v.name, v.var)
sys.exit(-1)
return m return m
def EmitTypeDeclaration(self, name): def EmitTypeDeclaration(self, _name):
lines = [] lines = []
lines += ["struct " + self.TypeName()] lines += ["struct " + self.TypeName()]
lines += ["{"] lines += ["{"]
@ -87,7 +84,7 @@ class Struct(BaseType):
for member in self.Members(): for member in self.Members():
lines += member.var.EmitPreDefinition(target_name+"."+member.name) lines += member.var.EmitPreDefinition(target_name+"."+member.name)
return lines return lines
def EmitDefinition(self, name): def EmitDefinition(self, _name):
lines = ["/* %s */ {" % self.TargetName()] lines = ["/* %s */ {" % self.TargetName()]
for member in self.Members(): for member in self.Members():
lines += ["\t" + " ".join(member.var.EmitDefinition("")) + ","] lines += ["\t" + " ".join(member.var.EmitDefinition("")) + ","]
@ -95,13 +92,13 @@ class Struct(BaseType):
return lines return lines
class Array(BaseType): class Array(BaseType):
def __init__(self, type): def __init__(self, typ):
BaseType.__init__(self, type.TypeName()) BaseType.__init__(self, typ.TypeName())
self.type = type self.type = typ
self.items = [] self.items = []
def Add(self, instance): def Add(self, instance):
if instance.TypeName() != self.type.TypeName(): if instance.TypeName() != self.type.TypeName():
error("bah") raise "bah"
self.items += [instance] self.items += [instance]
def EmitDeclaration(self, name): def EmitDeclaration(self, name):
return ["int m_Num%s;"%(FixCasing(name)), return ["int m_Num%s;"%(FixCasing(name)),
@ -115,7 +112,7 @@ class Array(BaseType):
lines += item.EmitPreDefinition("%s[%d]"%(self.Identifyer(), i)) lines += item.EmitPreDefinition("%s[%d]"%(self.Identifyer(), i))
i += 1 i += 1
if len(self.items): if self.items:
lines += ["static %s %s[] = {"%(self.TypeName(), self.Identifyer())] lines += ["static %s %s[] = {"%(self.TypeName(), self.Identifyer())]
for item in self.items: for item in self.items:
itemlines = item.EmitDefinition("") itemlines = item.EmitDefinition("")
@ -125,7 +122,7 @@ class Array(BaseType):
lines += ["static %s *%s = 0;"%(self.TypeName(), self.Identifyer())] lines += ["static %s *%s = 0;"%(self.TypeName(), self.Identifyer())]
return lines return lines
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return [str(len(self.items))+","+self.Identifyer()] return [str(len(self.items))+","+self.Identifyer()]
# Basic Types # Basic Types
@ -136,7 +133,7 @@ class Int(BaseType):
self.value = value self.value = value
def Set(self, value): def Set(self, value):
self.value = value self.value = value
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ["%d"%self.value] return ["%d"%self.value]
#return ["%d /* %s */"%(self.value, self._target_name)] #return ["%d /* %s */"%(self.value, self._target_name)]
@ -146,7 +143,7 @@ class Float(BaseType):
self.value = value self.value = value
def Set(self, value): def Set(self, value):
self.value = value self.value = value
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ["%ff"%self.value] return ["%ff"%self.value]
#return ["%d /* %s */"%(self.value, self._target_name)] #return ["%d /* %s */"%(self.value, self._target_name)]
@ -156,22 +153,22 @@ class String(BaseType):
self.value = value self.value = value
def Set(self, value): def Set(self, value):
self.value = value self.value = value
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ['"'+self.value+'"'] return ['"'+self.value+'"']
class Pointer(BaseType): class Pointer(BaseType):
def __init__(self, type, target): def __init__(self, typ, target):
BaseType.__init__(self, "%s*"%type().TypeName()) BaseType.__init__(self, "%s*"%typ().TypeName())
self.target = target self.target = target
def Set(self, target): def Set(self, target):
self.target = target self.target = target
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ["&"+self.target.TargetName()] return ["&"+self.target.TargetName()]
class TextureHandle(BaseType): class TextureHandle(BaseType):
def __init__(self): def __init__(self):
BaseType.__init__(self, "IGraphics::CTextureHandle") BaseType.__init__(self, "IGraphics::CTextureHandle")
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ["IGraphics::CTextureHandle()"] return ["IGraphics::CTextureHandle()"]
# helper functions # helper functions
@ -343,10 +340,10 @@ class NetIntAny(NetVariable):
return ["pPacker->AddInt(%s);" % self.name] return ["pPacker->AddInt(%s);" % self.name]
class NetIntRange(NetIntAny): class NetIntRange(NetIntAny):
def __init__(self, name, min, max): def __init__(self, name, min_val, max_val):
NetIntAny.__init__(self,name) NetIntAny.__init__(self,name)
self.min = str(min) self.min = str(min_val)
self.max = str(max) self.max = str(max_val)
def emit_validate(self): def emit_validate(self):
return ["pObj->%s = ClampInt(\"%s\", pObj->%s, %s, %s);"%(self.name, self.name, self.name, self.min, self.max)] return ["pObj->%s = ClampInt(\"%s\", pObj->%s, %s, %s);"%(self.name, self.name, self.name, self.min, self.max)]
def emit_unpack_check(self): def emit_unpack_check(self):

View file

@ -1,4 +1,4 @@
from datatypes import * from datatypes import Enum, Flags, NetBool, NetEvent, NetIntAny, NetIntRange, NetMessage, NetMessageEx, NetObject, NetObjectEx, NetString, NetStringHalfStrict, NetStringStrict, NetTick
Emotes = ["NORMAL", "PAIN", "HAPPY", "SURPRISE", "ANGRY", "BLINK"] Emotes = ["NORMAL", "PAIN", "HAPPY", "SURPRISE", "ANGRY", "BLINK"]
PlayerFlags = ["PLAYING", "IN_MENU", "CHATTING", "SCOREBOARD", "AIM"] PlayerFlags = ["PLAYING", "IN_MENU", "CHATTING", "SCOREBOARD", "AIM"]

View file

@ -1,5 +1,5 @@
import sys import sys
from .datatypes import * from .datatypes import EmitDefinition, EmitTypeDeclaration
from . import content from . import content
from . import network from . import network
@ -31,7 +31,7 @@ def EmitEnum(names, num):
print("\t%s" % num) print("\t%s" % num)
print("};") print("};")
def EmitFlags(names, num): def EmitFlags(names):
print("enum") print("enum")
print("{") print("{")
i = 0 i = 0
@ -40,30 +40,24 @@ def EmitFlags(names, num):
i += 1 i += 1
print("};") print("};")
gen_network_header = False def main():
gen_network_source = False gen_network_header = "network_header" in sys.argv
gen_client_content_header = False gen_network_source = "network_source" in sys.argv
gen_client_content_source = False gen_client_content_header = "client_content_header" in sys.argv
gen_server_content_header = False gen_client_content_source = "client_content_source" in sys.argv
gen_server_content_source = False gen_server_content_header = "server_content_header" in sys.argv
gen_server_content_source = "server_content_source" in sys.argv
if "network_header" in sys.argv: gen_network_header = True if gen_client_content_header:
if "network_source" in sys.argv: gen_network_source = True
if "client_content_header" in sys.argv: gen_client_content_header = True
if "client_content_source" in sys.argv: gen_client_content_source = True
if "server_content_header" in sys.argv: gen_server_content_header = True
if "server_content_source" in sys.argv: gen_server_content_source = True
if gen_client_content_header:
print("#ifndef CLIENT_CONTENT7_HEADER") print("#ifndef CLIENT_CONTENT7_HEADER")
print("#define CLIENT_CONTENT7_HEADER") print("#define CLIENT_CONTENT7_HEADER")
if gen_server_content_header: if gen_server_content_header:
print("#ifndef SERVER_CONTENT7_HEADER") print("#ifndef SERVER_CONTENT7_HEADER")
print("#define SERVER_CONTENT7_HEADER") print("#define SERVER_CONTENT7_HEADER")
if gen_client_content_header or gen_server_content_header: if gen_client_content_header or gen_server_content_header:
# print some includes # print some includes
print('#include <engine/graphics.h>') print('#include <engine/graphics.h>')
print('#include <engine/sound.h>') print('#include <engine/sound.h>')
@ -87,7 +81,7 @@ if gen_client_content_header or gen_server_content_header:
EmitEnum(["ANIM_%s"%i.name.value.upper() for i in content.container.animations.items], "NUM_ANIMS") 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") 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 or gen_server_content_source:
if gen_client_content_source: if gen_client_content_source:
print('#include "client_data7.h"') print('#include "client_data7.h"')
if gen_server_content_source: if gen_server_content_source:
@ -98,7 +92,7 @@ if gen_client_content_source or gen_server_content_source:
print("}") print("}")
# NETWORK # NETWORK
if gen_network_header: if gen_network_header:
print("#ifndef GAME_GENERATED_PROTOCOL7_H") print("#ifndef GAME_GENERATED_PROTOCOL7_H")
print("#define GAME_GENERATED_PROTOCOL7_H") print("#define GAME_GENERATED_PROTOCOL7_H")
@ -108,32 +102,36 @@ if gen_network_header:
print(network.RawHeader) print(network.RawHeader)
for e in network.Enums: 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) for l in create_enum_table(["%s_%s"%(e.name, v) for v in e.values], 'NUM_%sS'%e.name):
print(l)
print("") print("")
for e in network.Flags: for e in network.Flags:
for l in create_flags_table(["%s_%s" % (e.name, v) for v in e.values]): print(l) for l in create_flags_table(["%s_%s" % (e.name, v) for v in e.values]):
print(l)
print("") print("")
for l in create_enum_table(["NETOBJ_INVALID"]+[o.enum_name for o in network.Objects], "NUM_NETOBJTYPES"): print(l) for l in create_enum_table(["NETOBJ_INVALID"]+[o.enum_name for o in network.Objects], "NUM_NETOBJTYPES"):
print(l)
print("") print("")
for l in create_enum_table(["NETMSG_INVALID"]+[o.enum_name for o in network.Messages], "NUM_NETMSGTYPES"): print(l) for l in create_enum_table(["NETMSG_INVALID"]+[o.enum_name for o in network.Messages], "NUM_NETMSGTYPES"):
print(l)
print("") print("")
print(""" print("""
template<typename... Ts> struct make_void { typedef void type;}; template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type; template<typename... Ts> using void_t = typename make_void<Ts...>::type;
template<typename T, typename = void> template<typename T, typename = void>
struct is_sixup { struct is_sixup {
constexpr static bool value = false; constexpr static bool value = false;
}; };
template<typename T> template<typename T>
struct is_sixup<T, void_t<typename T::is_sixup>> { struct is_sixup<T, void_t<typename T::is_sixup>> {
constexpr static bool value = true; constexpr static bool value = true;
}; };
""") """)
for item in network.Objects + network.Messages: for item in network.Objects + network.Messages:
for line in item.emit_declaration(): for line in item.emit_declaration():
@ -145,8 +143,8 @@ struct is_sixup<T, void_t<typename T::is_sixup>> {
print(""" print("""
class CNetObjHandler class CNetObjHandler
{ {
const char *m_pMsgFailedOn; const char *m_pMsgFailedOn;
char m_aMsgData[1024]; char m_aMsgData[1024];
const char *m_pObjFailedOn; const char *m_pObjFailedOn;
@ -158,7 +156,7 @@ class CNetObjHandler
static int ms_aObjSizes[]; static int ms_aObjSizes[];
static const char *ms_apMsgNames[]; static const char *ms_apMsgNames[];
public: public:
CNetObjHandler(); CNetObjHandler();
int ValidateObj(int Type, const void *pData, int Size); int ValidateObj(int Type, const void *pData, int Size);
@ -170,15 +168,15 @@ public:
const char *GetMsgName(int Type) const; const char *GetMsgName(int Type) const;
void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker); void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker);
const char *FailedMsgOn() const; const char *FailedMsgOn() const;
}; };
""") """)
print("}") print("}")
print("#endif // GAME_GENERATED_PROTOCOL7_H") print("#endif // GAME_GENERATED_PROTOCOL7_H")
if gen_network_source: if gen_network_source:
# create names # create names
lines = [] lines = []
@ -265,27 +263,6 @@ if gen_network_source:
for l in lines: for l in lines:
print(l) print(l)
if 0:
for item in network.Objects:
for line in item.emit_validate():
print(line)
print("")
# create validate tables
lines = []
lines += ['static int validate_invalid(void *data, int size) { return -1; }']
lines += ["typedef int(*VALIDATEFUNC)(void *data, int size);"]
lines += ["static VALIDATEFUNC validate_funcs[] = {"]
lines += ['\tvalidate_invalid,']
lines += ['\tvalidate_%s,' % o.name for o in network.Objects]
lines += ["\t0x0", "};", ""]
lines += ["int netobj_validate(int type, void *data, int size)"]
lines += ["{"]
lines += ["\tif(type < 0 || type >= NUM_NETOBJTYPES) return -1;"]
lines += ["\treturn validate_funcs[type](data, size);"]
lines += ["};", ""]
lines = [] lines = []
lines += ['int CNetObjHandler::ValidateObj(int Type, const void *pData, int Size)'] lines += ['int CNetObjHandler::ValidateObj(int Type, const void *pData, int Size)']
lines += ['{'] lines += ['{']
@ -301,24 +278,6 @@ if gen_network_source:
lines += ['};'] lines += ['};']
lines += [''] lines += ['']
#int Validate(int Type, void *pData, int Size);
if 0:
for item in network.Messages:
for line in item.emit_unpack():
print(line)
print("")
lines += ['static void *secure_unpack_invalid(CUnpacker *pUnpacker) { return 0; }']
lines += ['typedef void *(*SECUREUNPACKFUNC)(CUnpacker *pUnpacker);']
lines += ['static SECUREUNPACKFUNC secure_unpack_funcs[] = {']
lines += ['\tsecure_unpack_invalid,']
for msg in network.Messages:
lines += ['\tsecure_unpack_%s,' % msg.name]
lines += ['\t0x0']
lines += ['};']
#
lines += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)'] lines += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)']
lines += ['{'] lines += ['{']
lines += ['\tm_pMsgFailedOn = 0;'] lines += ['\tm_pMsgFailedOn = 0;']
@ -358,6 +317,9 @@ if gen_network_source:
for l in lines: for l in lines:
print(l) print(l)
if gen_client_content_header or gen_server_content_header: if gen_client_content_header or gen_server_content_header:
print("}") print("}")
print("#endif") print("#endif")
if __name__ == '__main__':
main()

View file

@ -1,4 +1,4 @@
from .datatypes import * from .datatypes import Array, Float, Int, Pointer, SampleHandle, String, Struct, TextureHandle
class Sound(Struct): class Sound(Struct):
def __init__(self, filename=""): def __init__(self, filename=""):
@ -7,13 +7,13 @@ class Sound(Struct):
self.filename = String(filename) self.filename = String(filename)
class SoundSet(Struct): class SoundSet(Struct):
def __init__(self, name="", files=[]): def __init__(self, name="", files=()):
Struct.__init__(self, "CDataSoundset") Struct.__init__(self, "CDataSoundset")
self.name = String(name) self.name = String(name)
self.sounds = Array(Sound()) self.sounds = Array(Sound())
self.last = Int(-1) self.last = Int(-1)
for name in files: for filename in files:
self.sounds.Add(Sound(name)) self.sounds.Add(Sound(filename))
class Image(Struct): class Image(Struct):
def __init__(self, name="", filename="", linear_mapping=0): def __init__(self, name="", filename="", linear_mapping=0):
@ -24,7 +24,7 @@ class Image(Struct):
self.id = TextureHandle() self.id = TextureHandle()
class SpriteSet(Struct): class SpriteSet(Struct):
def __init__(self, name="", image=None, gridx=0, gridy=0): def __init__(self, _name="", image=None, gridx=0, gridy=0):
Struct.__init__(self, "CDataSpriteset") Struct.__init__(self, "CDataSpriteset")
self.image = Pointer(Image, image) # TODO self.image = Pointer(Image, image) # TODO
self.gridx = Int(gridx) self.gridx = Int(gridx)
@ -70,7 +70,7 @@ class Animation(Struct):
self.attach = AnimSequence() self.attach = AnimSequence()
class WeaponSpec(Struct): class WeaponSpec(Struct):
def __init__(self, container=None, name=""): def __init__(self, cont=None, name=""):
Struct.__init__(self, "CDataWeaponspec") Struct.__init__(self, "CDataWeaponspec")
self.name = String(name) self.name = String(name)
self.sprite_body = Pointer(Sprite, Sprite()) self.sprite_body = Pointer(Sprite, Sprite())
@ -91,11 +91,14 @@ class WeaponSpec(Struct):
self.muzzleduration = Float(5) self.muzzleduration = Float(5)
# dig out sprites if we have a container # dig out sprites if we have a container
if container: if cont:
for sprite in container.sprites.items: for sprite in cont.sprites.items:
if sprite.name.value == "weapon_"+name+"_body": self.sprite_body.Set(sprite) if sprite.name.value == "weapon_"+name+"_body":
elif sprite.name.value == "weapon_"+name+"_cursor": self.sprite_cursor.Set(sprite) self.sprite_body.Set(sprite)
elif sprite.name.value == "weapon_"+name+"_proj": self.sprite_proj.Set(sprite) elif sprite.name.value == "weapon_"+name+"_cursor":
self.sprite_cursor.Set(sprite)
elif sprite.name.value == "weapon_"+name+"_proj":
self.sprite_proj.Set(sprite)
elif "weapon_"+name+"_muzzle" in sprite.name.value: elif "weapon_"+name+"_muzzle" in sprite.name.value:
self.sprite_muzzles.Add(Pointer(Sprite, sprite)) self.sprite_muzzles.Add(Pointer(Sprite, sprite))
@ -175,8 +178,8 @@ class DataContainer(Struct):
self.weapons = Weapons() self.weapons = Weapons()
#self.explosion = Explosion() #self.explosion = Explosion()
def FileList(format, num): def FileList(fmt, num):
return [format%(x+1) for x in range(0,num)] return [fmt%(x+1) for x in range(0,num)]
container = DataContainer() container = DataContainer()
container.sounds.Add(SoundSet("gun_fire", FileList("audio/wp_gun_fire-%02d.wv", 3))) container.sounds.Add(SoundSet("gun_fire", FileList("audio/wp_gun_fire-%02d.wv", 3)))

View file

@ -1,5 +1,3 @@
import sys
GlobalIdCounter = 0 GlobalIdCounter = 0
def GetID(): def GetID():
global GlobalIdCounter global GlobalIdCounter
@ -22,10 +20,10 @@ def FixCasing(Str):
NewStr += c.lower() NewStr += c.lower()
return NewStr return NewStr
def FormatName(type, name): def FormatName(typ, name):
if "*" in type: if "*" in typ:
return "m_p" + FixCasing(name) return "m_p" + FixCasing(name)
if "[]" in type: if "[]" in typ:
return "m_a" + FixCasing(name) return "m_a" + FixCasing(name)
return "m_" + FixCasing(name) return "m_" + FixCasing(name)
@ -35,17 +33,21 @@ class BaseType:
self._target_name = "INVALID" self._target_name = "INVALID"
self._id = GetID() # this is used to remember what order the members have in structures etc self._id = GetID() # this is used to remember what order the members have in structures etc
def Identifyer(self): return "x"+str(self._id) def Identifyer(self):
def TargetName(self): return self._target_name return "x"+str(self._id)
def TypeName(self): return self._type_name def TargetName(self):
def ID(self): return self._id; return self._target_name
def TypeName(self):
return self._type_name
def ID(self):
return self._id
def EmitDeclaration(self, name): def EmitDeclaration(self, name):
return ["%s %s;"%(self.TypeName(), FormatName(self.TypeName(), name))] return ["%s %s;"%(self.TypeName(), FormatName(self.TypeName(), name))]
def EmitPreDefinition(self, target_name): def EmitPreDefinition(self, target_name):
self._target_name = target_name self._target_name = target_name
return [] return []
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return [] return []
class MemberType: class MemberType:
@ -64,15 +66,10 @@ class Struct(BaseType):
if name[0] == "_": if name[0] == "_":
continue continue
m += [MemberType(name, self.__dict__[name])] m += [MemberType(name, self.__dict__[name])]
try:
m.sort(key = sorter) m.sort(key = sorter)
except:
for v in m:
print(v.name, v.var)
sys.exit(-1)
return m return m
def EmitTypeDeclaration(self, name): def EmitTypeDeclaration(self, _name):
lines = [] lines = []
lines += ["struct " + self.TypeName()] lines += ["struct " + self.TypeName()]
lines += ["{"] lines += ["{"]
@ -87,7 +84,7 @@ class Struct(BaseType):
for member in self.Members(): for member in self.Members():
lines += member.var.EmitPreDefinition(target_name+"."+member.name) lines += member.var.EmitPreDefinition(target_name+"."+member.name)
return lines return lines
def EmitDefinition(self, name): def EmitDefinition(self, _name):
lines = ["/* %s */ {" % self.TargetName()] lines = ["/* %s */ {" % self.TargetName()]
for member in self.Members(): for member in self.Members():
lines += ["\t" + " ".join(member.var.EmitDefinition("")) + ","] lines += ["\t" + " ".join(member.var.EmitDefinition("")) + ","]
@ -95,13 +92,13 @@ class Struct(BaseType):
return lines return lines
class Array(BaseType): class Array(BaseType):
def __init__(self, type): def __init__(self, typ):
BaseType.__init__(self, type.TypeName()) BaseType.__init__(self, typ.TypeName())
self.type = type self.type = typ
self.items = [] self.items = []
def Add(self, instance): def Add(self, instance):
if instance.TypeName() != self.type.TypeName(): if instance.TypeName() != self.type.TypeName():
error("bah") raise "bah"
self.items += [instance] self.items += [instance]
def EmitDeclaration(self, name): def EmitDeclaration(self, name):
return ["int m_Num%s;"%(FixCasing(name)), return ["int m_Num%s;"%(FixCasing(name)),
@ -115,7 +112,7 @@ class Array(BaseType):
lines += item.EmitPreDefinition("%s[%d]"%(self.Identifyer(), i)) lines += item.EmitPreDefinition("%s[%d]"%(self.Identifyer(), i))
i += 1 i += 1
if len(self.items): if self.items:
lines += ["static %s %s[] = {"%(self.TypeName(), self.Identifyer())] lines += ["static %s %s[] = {"%(self.TypeName(), self.Identifyer())]
for item in self.items: for item in self.items:
itemlines = item.EmitDefinition("") itemlines = item.EmitDefinition("")
@ -125,7 +122,7 @@ class Array(BaseType):
lines += ["static %s *%s = 0;"%(self.TypeName(), self.Identifyer())] lines += ["static %s *%s = 0;"%(self.TypeName(), self.Identifyer())]
return lines return lines
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return [str(len(self.items))+","+self.Identifyer()] return [str(len(self.items))+","+self.Identifyer()]
# Basic Types # Basic Types
@ -136,7 +133,7 @@ class Int(BaseType):
self.value = value self.value = value
def Set(self, value): def Set(self, value):
self.value = value self.value = value
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ["%d"%self.value] return ["%d"%self.value]
#return ["%d /* %s */"%(self.value, self._target_name)] #return ["%d /* %s */"%(self.value, self._target_name)]
@ -146,7 +143,7 @@ class Float(BaseType):
self.value = value self.value = value
def Set(self, value): def Set(self, value):
self.value = value self.value = value
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ["%ff"%self.value] return ["%ff"%self.value]
#return ["%d /* %s */"%(self.value, self._target_name)] #return ["%d /* %s */"%(self.value, self._target_name)]
@ -156,28 +153,28 @@ class String(BaseType):
self.value = value self.value = value
def Set(self, value): def Set(self, value):
self.value = value self.value = value
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ['"'+self.value+'"'] return ['"'+self.value+'"']
class Pointer(BaseType): class Pointer(BaseType):
def __init__(self, type, target): def __init__(self, typ, target):
BaseType.__init__(self, "%s*"%type().TypeName()) BaseType.__init__(self, "%s*"%typ().TypeName())
self.target = target self.target = target
def Set(self, target): def Set(self, target):
self.target = target self.target = target
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ["&"+self.target.TargetName()] return ["&"+self.target.TargetName()]
class TextureHandle(BaseType): class TextureHandle(BaseType):
def __init__(self): def __init__(self):
BaseType.__init__(self, "IGraphics::CTextureHandle") BaseType.__init__(self, "IGraphics::CTextureHandle")
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ["IGraphics::CTextureHandle()"] return ["IGraphics::CTextureHandle()"]
class SampleHandle(BaseType): class SampleHandle(BaseType):
def __init__(self): def __init__(self):
BaseType.__init__(self, "ISound::CSampleHandle") BaseType.__init__(self, "ISound::CSampleHandle")
def EmitDefinition(self, name): def EmitDefinition(self, _name):
return ["ISound::CSampleHandle()"] return ["ISound::CSampleHandle()"]
# helper functions # helper functions
@ -322,16 +319,15 @@ class NetIntAny(NetVariable):
def emit_unpack(self): def emit_unpack(self):
if self.default is None: if self.default is None:
return ["pMsg->%s = pUnpacker->GetInt();" % self.name] return ["pMsg->%s = pUnpacker->GetInt();" % self.name]
else:
return ["pMsg->%s = pUnpacker->GetIntOrDefault(%s);" % (self.name, self.default)] return ["pMsg->%s = pUnpacker->GetIntOrDefault(%s);" % (self.name, self.default)]
def emit_pack(self): def emit_pack(self):
return ["pPacker->AddInt(%s);" % self.name] return ["pPacker->AddInt(%s);" % self.name]
class NetIntRange(NetIntAny): class NetIntRange(NetIntAny):
def __init__(self, name, min, max, default=None): def __init__(self, name, min_val, max_val, default=None):
NetIntAny.__init__(self,name,default=default) NetIntAny.__init__(self,name,default=default)
self.min = str(min) self.min = str(min_val)
self.max = str(max) self.max = str(max_val)
def emit_validate(self): def emit_validate(self):
return ["if(!CheckInt(\"%s\", pObj->%s, %s, %s)) return -1;"%(self.name, self.name, self.min, self.max)] return ["if(!CheckInt(\"%s\", pObj->%s, %s, %s)) return -1;"%(self.name, self.name, self.min, self.max)]
def emit_unpack_check(self): def emit_unpack_check(self):
@ -366,6 +362,7 @@ class NetTick(NetIntRange):
class NetArray(NetVariable): class NetArray(NetVariable):
def __init__(self, var, size): def __init__(self, var, size):
NetVariable.__init__(self,var.name)
self.base_name = var.name self.base_name = var.name
self.var = var self.var = var
self.size = size self.size = size

View file

@ -1,4 +1,4 @@
from .datatypes import * from .datatypes import Enum, Flags, NetArray, NetBool, NetEnum, NetEvent, NetFlag, NetIntAny, NetIntRange, NetMessage, NetObject, NetString, NetStringStrict, NetTick
Pickups = Enum("PICKUP", ["HEALTH", "ARMOR", "GRENADE", "SHOTGUN", "LASER", "NINJA", "GUN", "HAMMER"]) Pickups = Enum("PICKUP", ["HEALTH", "ARMOR", "GRENADE", "SHOTGUN", "LASER", "NINJA", "GUN", "HAMMER"])
Emotes = Enum("EMOTE", ["NORMAL", "PAIN", "HAPPY", "SURPRISE", "ANGRY", "BLINK"]) Emotes = Enum("EMOTE", ["NORMAL", "PAIN", "HAPPY", "SURPRISE", "ANGRY", "BLINK"])

View file

@ -4,24 +4,24 @@ result=
dil_path=$1 dil_path=$1
result=$(find $2 -iname '*.png' -print0 | while IFS= read -r -d $'\0' file; do result=$(find "$2" -iname '*.png' -print0 | while IFS= read -r -d $'\0' file; do
new_file=$(mktemp --tmpdir "$(basename "$file" .png).XXX.png") new_file=$(mktemp --tmpdir "$(basename "$file" .png).XXX.png")
cp "$file" "$new_file" cp "$file" "$new_file"
convert "$new_file" "${new_file}_old.bmp" >> /dev/null convert "$new_file" "${new_file}_old.bmp" > /dev/null
${dil_path}/dilate "$new_file" >> /dev/null "${dil_path}"/dilate "$new_file" > /dev/null
convert "$new_file" "${new_file}_new.bmp" >> /dev/null convert "$new_file" "${new_file}_new.bmp" > /dev/null
orig_hash=$(identify -quiet -format "%#" "${new_file}_old.bmp") orig_hash=$(identify -quiet -format "%#" "${new_file}_old.bmp")
new_hash=$(identify -quiet -format "%#" "${new_file}_new.bmp") new_hash=$(identify -quiet -format "%#" "${new_file}_new.bmp")
rm "$new_file" rm "$new_file"
rm "${new_file}_old.bmp" rm "${new_file}_old.bmp"
rm "${new_file}_new.bmp" rm "${new_file}_new.bmp"
if [ "$orig_hash" != "$new_hash" ]; then if [ "$orig_hash" != "$new_hash" ]; then
printf "$file is not dilated\n" echo "$file is not dilated"
fi fi
done) done)
if [[ "$result" != "" ]]; then if [[ "$result" != "" ]]; then
printf "$result" echo -n "$result"
exit 1 exit 1
fi fi

View file

@ -22,8 +22,8 @@ def check_file(filename):
if line[0] == "/" or line[0] == "*" or line[0] == "\r" or line[0] == "\n" or line[0] == "\t": if line[0] == "/" or line[0] == "*" or line[0] == "\r" or line[0] == "\n" or line[0] == "\t":
continue continue
if line.startswith("#ifndef"): if line.startswith("#ifndef"):
hg = "#ifndef " + ("_".join(filename.split(PATH)[1].split("/"))[:-2]).upper() + "_H" header_guard = "#ifndef " + ("_".join(filename.split(PATH)[1].split("/"))[:-2]).upper() + "_H"
if line[:-1] != hg: if line[:-1] != header_guard:
error = True error = True
print("Wrong header guard in {}".format(filename)) print("Wrong header guard in {}".format(filename))
else: else:
@ -32,13 +32,13 @@ def check_file(filename):
break break
return error return error
def check_dir(dir): def check_dir(directory):
errors = 0 errors = 0
list = os.listdir(dir) file_list = os.listdir(directory)
for file in list: for file in file_list:
path = dir + file path = directory + file
if os.path.isdir(path): if os.path.isdir(path):
if file != "external" and file != "generated": if file not in ("external", "generated"):
errors += check_dir(path + "/") errors += check_dir(path + "/")
elif file.endswith(".h") and file != "keynames.h": elif file.endswith(".h") and file != "keynames.h":
errors += check_file(path) errors += check_file(path)

View file

@ -1,18 +1,18 @@
import argparse
import csv import csv
import sys import sys
import re
def check_name(kind, qualifiers, type, name): def check_name(kind, qualifiers, typ, name):
if kind == "variable": if kind == "variable":
return check_variable_name(qualifiers, type, name) return check_variable_name(qualifiers, typ, name)
elif kind in "class struct".split(): if kind in "class struct".split():
if name[0] not in "CI": if name[0] not in "CI":
return "should start with 'C' (or 'I' for interfaces)" return "should start with 'C' (or 'I' for interfaces)"
if len(name) < 2: if len(name) < 2:
return "must be at least two characters long" return "must be at least two characters long"
if not name[1].isupper(): if not name[1].isupper():
return "must start with an uppercase letter" return "must start with an uppercase letter"
elif kind == "enum_constant": if kind == "enum_constant":
if not name.isupper(): if not name.isupper():
return "must only contain uppercase letters, digits and underscores" return "must only contain uppercase letters, digits and underscores"
return None return None
@ -28,10 +28,11 @@ ALLOW = set("""
x0 x1 x0 x1
y0 y1 y0 y1
""".split()) """.split())
def check_variable_name(qualifiers, type, name):
if qualifiers == "" and type == "" and name == "argc": def check_variable_name(qualifiers, typ, name):
if qualifiers == "" and typ == "" and name == "argc":
return None return None
if qualifiers == "" and type == "pp" and name == "argv": if qualifiers == "" and typ == "pp" and name == "argv":
return None return None
if qualifiers == "cs": if qualifiers == "cs":
# Allow all uppercase names for constant statics. # Allow all uppercase names for constant statics.
@ -41,7 +42,7 @@ def check_variable_name(qualifiers, type, name):
# Allow single lowercase letters as member and variable names. # Allow single lowercase letters as member and variable names.
if qualifiers in ["m", ""] and len(name) == 1 and name.islower(): if qualifiers in ["m", ""] and len(name) == 1 and name.islower():
return None return None
prefix = "".join([qualifiers, "_" if qualifiers else "", type]) prefix = "".join([qualifiers, "_" if qualifiers else "", typ])
if not name.startswith(prefix): if not name.startswith(prefix):
return "should start with {!r}".format(prefix) return "should start with {!r}".format(prefix)
if name in ALLOW: if name in ALLOW:
@ -50,14 +51,12 @@ def check_variable_name(qualifiers, type, name):
if not name[0].isupper(): if not name[0].isupper():
if prefix: if prefix:
return "should start with an uppercase letter after the prefix {!r}".format(prefix) return "should start with an uppercase letter after the prefix {!r}".format(prefix)
else:
return "should start with an uppercase letter" return "should start with an uppercase letter"
return None return None
def main(): def main():
import argparse
p = argparse.ArgumentParser(description="Check identifiers (input via stdin in CSV format from extract_identifiers.py) for naming style in DDNet code") p = argparse.ArgumentParser(description="Check identifiers (input via stdin in CSV format from extract_identifiers.py) for naming style in DDNet code")
args = p.parse_args() p.parse_args()
identifiers = list(csv.DictReader(sys.stdin)) identifiers = list(csv.DictReader(sys.stdin))

View file

@ -1,3 +1,4 @@
import argparse
import subprocess import subprocess
import re import re
@ -16,7 +17,6 @@ def split_cmds(lines):
return cmds[1:] return cmds[1:]
def main(): def main():
import argparse
p = argparse.ArgumentParser(description="Strip LC_RPATH commands from executable") p = argparse.ArgumentParser(description="Strip LC_RPATH commands from executable")
p.add_argument('otool', help="Path to otool") p.add_argument('otool', help="Path to otool")
@ -31,7 +31,7 @@ def main():
cmds = split_cmds(subprocess.check_output([otool, "-l", executable]).decode().splitlines()) cmds = split_cmds(subprocess.check_output([otool, "-l", executable]).decode().splitlines())
lc_rpath_cmds = [cmd for cmd in cmds if cmd[0] == "cmd LC_RPATH"] lc_rpath_cmds = [cmd for cmd in cmds if cmd[0] == "cmd LC_RPATH"]
path_regex = re.compile("^path (.*) \(offset \d+\)$") path_regex = re.compile(r"^path (.*) \(offset \d+\)$")
rpaths = [k[0] for k in [[path_regex.match(part).group(1) for part in cmd if path_regex.match(part)] for cmd in lc_rpath_cmds]] rpaths = [k[0] for k in [[path_regex.match(part).group(1) for part in cmd if path_regex.match(part)] for cmd in lc_rpath_cmds]]
print("Found paths:") print("Found paths:")

View file

@ -1,4 +1,5 @@
from collections import namedtuple from collections import namedtuple
import argparse
import os import os
import shlex import shlex
import subprocess import subprocess
@ -74,7 +75,6 @@ class Hdiutil(Dmg):
self._hdiutil('create', '-volname', volume_name, '-srcdir', directory, dmg) self._hdiutil('create', '-volname', volume_name, '-srcdir', directory, dmg)
def main(): def main():
import argparse
p = argparse.ArgumentParser(description="Manipulate dmg archives") p = argparse.ArgumentParser(description="Manipulate dmg archives")
subcommands = p.add_subparsers(help="Subcommand", dest='command', metavar="COMMAND") subcommands = p.add_subparsers(help="Subcommand", dest='command', metavar="COMMAND")

View file

@ -1,16 +1,16 @@
import clang.cindex import argparse
import csv import csv
import enum
import os import os
import sys import sys
import clang.cindex
from clang.cindex import CursorKind, LinkageKind, StorageClass, TypeKind from clang.cindex import CursorKind, LinkageKind, StorageClass, TypeKind
from collections import Counter
try: try:
from tqdm import tqdm from tqdm import tqdm
except ImportError: except ImportError:
def tqdm(it, *args, **kwargs): def tqdm(it, *_args, **_kwargs):
return it return it
def traverse_namespaced(root, filter_files=None, skip_namespaces=1, namespace=()): def traverse_namespaced(root, filter_files=None, skip_namespaces=1, namespace=()):
@ -38,31 +38,31 @@ INTERESTING_NODE_KINDS = {
CursorKind.FUNCTION_DECL: "function", CursorKind.FUNCTION_DECL: "function",
} }
def is_array_type(type): def is_array_type(typ):
return type.kind in (TypeKind.CONSTANTARRAY, TypeKind.DEPENDENTSIZEDARRAY, TypeKind.INCOMPLETEARRAY) return typ.kind in (TypeKind.CONSTANTARRAY, TypeKind.DEPENDENTSIZEDARRAY, TypeKind.INCOMPLETEARRAY)
def get_complex_type(type): def get_complex_type(typ):
if type.spelling in ("IOHANDLE", "LOCK"): if typ.spelling in ("IOHANDLE", "LOCK"):
return "" return ""
if type.kind == TypeKind.AUTO: if typ.kind == TypeKind.AUTO:
return get_complex_type(type.get_canonical()) return get_complex_type(typ.get_canonical())
if type.kind == TypeKind.LVALUEREFERENCE: if typ.kind == TypeKind.LVALUEREFERENCE:
return get_complex_type(type.get_pointee()) return get_complex_type(typ.get_pointee())
if type.kind == TypeKind.POINTER: if typ.kind == TypeKind.POINTER:
return "p" + get_complex_type(type.get_pointee()) return "p" + get_complex_type(typ.get_pointee())
if is_array_type(type): if is_array_type(type):
return "a" + get_complex_type(type.element_type) return "a" + get_complex_type(typ.element_type)
if type.kind == TypeKind.FUNCTIONPROTO: if typ.kind == TypeKind.FUNCTIONPROTO:
return "fn" return "fn"
if type.kind == TypeKind.TYPEDEF: if typ.kind == TypeKind.TYPEDEF:
return get_complex_type(type.get_declaration().underlying_typedef_type) return get_complex_type(typ.get_declaration().underlying_typedef_type)
if type.kind == TypeKind.ELABORATED: if typ.kind == TypeKind.ELABORATED:
return get_complex_type(type.get_named_type()) return get_complex_type(typ.get_named_type())
if type.kind in (TypeKind.UNEXPOSED, TypeKind.RECORD): if typ.kind in (TypeKind.UNEXPOSED, TypeKind.RECORD):
if type.get_declaration().spelling in "shared_ptr unique_ptr".split(): if typ.get_declaration().spelling in "shared_ptr unique_ptr".split():
return "p" + get_complex_type(type.get_template_argument_type(0)) return "p" + get_complex_type(typ.get_template_argument_type(0))
if type.get_declaration().spelling in "array sorted_array".split(): if typ.get_declaration().spelling in "array sorted_array".split():
return "a" + get_complex_type(type.get_template_argument_type(0)) return "a" + get_complex_type(typ.get_template_argument_type(0))
return "" return ""
def is_static_member_definition_hack(node): def is_static_member_definition_hack(node):
@ -79,11 +79,11 @@ def is_static_member_definition_hack(node):
return False return False
return False return False
def is_const(type): def is_const(typ):
if type.is_const_qualified(): if typ.is_const_qualified():
return True return True
if is_array_type(type): if is_array_type(type):
return is_const(type.element_type) return is_const(typ.element_type)
return False return False
class ParseError(RuntimeError): class ParseError(RuntimeError):
@ -113,10 +113,10 @@ def process_source_file(out, file, extra_args, break_on):
cur_file = None cur_file = None
if node.location.file is not None: if node.location.file is not None:
cur_file = node.location.file.name cur_file = node.location.file.name
if cur_file is None or (cur_file != file and cur_file != header): if cur_file is None or cur_file not in (file, header):
continue continue
if node.kind in INTERESTING_NODE_KINDS and node.spelling: if node.kind in INTERESTING_NODE_KINDS and node.spelling:
type = get_complex_type(node.type) typ = get_complex_type(node.type)
qualifiers = "" qualifiers = ""
if INTERESTING_NODE_KINDS[node.kind] in {"variable", "function"}: if INTERESTING_NODE_KINDS[node.kind] in {"variable", "function"}:
is_member = node.semantic_parent.kind in {CursorKind.CLASS_DECL, CursorKind.CLASS_TEMPLATE, CursorKind.STRUCT_DECL, CursorKind.UNION_DECL} is_member = node.semantic_parent.kind in {CursorKind.CLASS_DECL, CursorKind.CLASS_TEMPLATE, CursorKind.STRUCT_DECL, CursorKind.UNION_DECL}
@ -136,14 +136,13 @@ def process_source_file(out, file, extra_args, break_on):
"kind": INTERESTING_NODE_KINDS[node.kind], "kind": INTERESTING_NODE_KINDS[node.kind],
"path": "::".join(namespace), "path": "::".join(namespace),
"qualifiers": qualifiers, "qualifiers": qualifiers,
"type": type, "type": typ,
"name": node.spelling, "name": node.spelling,
}) })
if node.spelling == break_on: if node.spelling == break_on:
breakpoint() breakpoint()
def main(): def main():
import argparse
p = argparse.ArgumentParser(description="Extracts identifier data from a Teeworlds source file and its header, outputting the data as CSV to stdout") p = argparse.ArgumentParser(description="Extracts identifier data from a Teeworlds source file and its header, outputting the data as CSV to stdout")
p.add_argument("file", metavar="FILE", nargs="+", help="Source file to analyze") p.add_argument("file", metavar="FILE", nargs="+", help="Source file to analyze")
p.add_argument("--break-on", help="Break on a specific variable name, useful to debug issues with the script") p.add_argument("--break-on", help="Break on a specific variable name, useful to debug issues with the script")

View file

@ -1,16 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from collections import defaultdict
import os import os
import re
import subprocess import subprocess
import sys import sys
import argparse
os.chdir(os.path.dirname(__file__) + "/..") os.chdir(os.path.dirname(__file__) + "/..")
def recursive_file_list(path): def recursive_file_list(path):
result = [] result = []
for dirpath, dirnames, filenames in os.walk(path): for dirpath, _, filenames in os.walk(path):
result += [os.path.join(dirpath, filename) for filename in filenames] result += [os.path.join(dirpath, filename) for filename in filenames]
return result return result
@ -34,7 +33,6 @@ def warn(filenames):
return subprocess.call(["clang-format", "-Werror", "--dry-run"] + filenames) return subprocess.call(["clang-format", "-Werror", "--dry-run"] + filenames)
def main(): def main():
import argparse
p = argparse.ArgumentParser(description="Check and fix style of changed files") p = argparse.ArgumentParser(description="Check and fix style of changed files")
p.add_argument("-n", "--dry-run", action="store_true", help="Don't fix, only warn") p.add_argument("-n", "--dry-run", action="store_true", help="Don't fix, only warn")
args = p.parse_args() args = p.parse_args()

View file

@ -1,5 +1,4 @@
import sys, os # pylint: skip-file
# generate keys.h file # generate keys.h file
f = file("src/engine/keys.h", "w") f = file("src/engine/keys.h", "w")
@ -74,4 +73,3 @@ print >>f, "};"
print >>f, "" print >>f, ""
f.close() f.close()

View file

@ -13,12 +13,12 @@ CURL_RE=re.compile(r"\bcurl_\w*")
def get_curl_calls(path): def get_curl_calls(path):
names = set() names = set()
for dir, _, files in os.walk(path): for directory, _, files in os.walk(path):
for filename in files: for filename in files:
if (filename.endswith(".cpp") or if (filename.endswith(".cpp") or
filename.endswith(".c") or filename.endswith(".c") or
filename.endswith(".h")): filename.endswith(".h")):
with open(os.path.join(dir, filename)) as f: with open(os.path.join(directory, filename)) as f:
contents = f.read() contents = f.read()
names = names.union(CURL_RE.findall(contents)) names = names.union(CURL_RE.findall(contents))
return names return names

View file

@ -5,10 +5,6 @@ try:
except ImportError: except ImportError:
import os import os
DEVNULL = open(os.devnull, 'wb') DEVNULL = open(os.devnull, 'wb')
try:
FileNotFoundError
except NameError:
FileNotFoundError = OSError
try: try:
git_hash = subprocess.check_output(["git", "rev-parse", "--short=16", "HEAD"], stderr=DEVNULL).decode().strip() git_hash = subprocess.check_output(["git", "rev-parse", "--short=16", "HEAD"], stderr=DEVNULL).decode().strip()
definition = '"{}"'.format(git_hash) definition = '"{}"'.format(git_hash)
@ -17,5 +13,5 @@ except FileNotFoundError as e:
raise raise
definition = "0" definition = "0"
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
definition = "0"; definition = "0"
print("const char *GIT_SHORTREV_HASH = {};".format(definition)) print("const char *GIT_SHORTREV_HASH = {};".format(definition))

View file

@ -1,3 +1,5 @@
import argparse
import tempfile
import binascii import binascii
import hashlib import hashlib
import os import os
@ -38,16 +40,13 @@ def parse_line(line):
if AUTH_ADD_PRESENT_REGEX.search(line): if AUTH_ADD_PRESENT_REGEX.search(line):
print("Warning: Funny-looking line with 'auth_add', not touching it:") print("Warning: Funny-looking line with 'auth_add', not touching it:")
print(line, end="") print(line, end="")
return return None
password = m.group('password') password = m.group('password')
if password.startswith('"'): if password.startswith('"'):
password = password[1:-1] # Strip quotes. password = password[1:-1] # Strip quotes.
return m.group('username'), m.group('level'), password return m.group('username'), m.group('level'), password
def main(): def main():
import argparse
import tempfile
p = argparse.ArgumentParser(description="Hash passwords in a way suitable for DDNet configs.") p = argparse.ArgumentParser(description="Hash passwords in a way suitable for DDNet configs.")
p.add_argument('--new', '-n', nargs=3, metavar=("USERNAME", "LEVEL", "PASSWORD"), action='append', default=[], help="username, level and password of the new user") p.add_argument('--new', '-n', nargs=3, metavar=("USERNAME", "LEVEL", "PASSWORD"), action='append', default=[], help="username, level and password of the new user")
p.add_argument('config', nargs='?', metavar="CONFIG", help="config file to update.") p.add_argument('config', nargs='?', metavar="CONFIG", help="config file to update.")

View file

@ -2,6 +2,7 @@
from collections import namedtuple from collections import namedtuple
from decimal import Decimal from decimal import Decimal
import argparse
import os.path import os.path
import re import re
import sqlite3 import sqlite3
@ -34,7 +35,6 @@ def read_records(file):
MAP_RE=re.compile(r"^(?P<map>.*)_record\.dtb$") MAP_RE=re.compile(r"^(?P<map>.*)_record\.dtb$")
def main(): def main():
import argparse
p = argparse.ArgumentParser(description="Merge multiple DDNet race database files", formatter_class=argparse.ArgumentDefaultsHelpFormatter) p = argparse.ArgumentParser(description="Merge multiple DDNet race database files", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
p.add_argument("--out", default="ddnet-server.sqlite", help="Output SQLite database") p.add_argument("--out", default="ddnet-server.sqlite", help="Output SQLite database")
p.add_argument("in_", metavar="IN", nargs='+', help="Text score databases to import; must have the format MAPNAME_record.dtb") p.add_argument("in_", metavar="IN", nargs='+', help="Text score databases to import; must have the format MAPNAME_record.dtb")
@ -44,14 +44,14 @@ def main():
records = {} records = {}
for in_ in args.in_: for in_ in args.in_:
m = MAP_RE.match(os.path.basename(in_)) match = MAP_RE.match(os.path.basename(in_))
if not m: if not match:
raise ValueError("Invalid text score database name, does not end in '_record.dtb': {}".format(in_)) raise ValueError("Invalid text score database name, does not end in '_record.dtb': {}".format(in_))
map = m.group("map") m = match.group("map")
if map in records: if m in records:
raise ValueError("Two text score databases refer to the same map: {}".format(in_)) raise ValueError("Two text score databases refer to the same map: {}".format(in_))
with open(in_) as f: with open(in_) as f:
records[map] = read_records(f) records[m] = read_records(f)
if not args.dry_run: if not args.dry_run:
conn = sqlite3.connect(args.out) conn = sqlite3.connect(args.out)
@ -65,7 +65,7 @@ def main():
"".join("cp{} FLOAT DEFAULT 0, ".format(i + 1) for i in range(25)) + "".join("cp{} FLOAT DEFAULT 0, ".format(i + 1) for i in range(25)) +
"GameID VARCHAR(64), " "GameID VARCHAR(64), "
"DDNet7 BOOL DEFAULT FALSE" "DDNet7 BOOL DEFAULT FALSE"
");"); ");")
c.executemany( c.executemany(
"INSERT INTO record_race (Map, Name, Time, Server, " + "INSERT INTO record_race (Map, Name, Time, Server, " +
"".join("cp{}, ".format(i + 1) for i in range(25)) + "".join("cp{}, ".format(i + 1) for i in range(25)) +

View file

@ -1,8 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import twlang
import os import os
import sys import sys
import twlang
def copy_fix(infile, delete_unused, append_missing, delete_empty): def copy_fix(infile, delete_unused, append_missing, delete_empty):
content = open(infile).readlines() content = open(infile).readlines()
trans = twlang.translations(infile) trans = twlang.translations(infile)
@ -20,28 +21,28 @@ def copy_fix(infile, delete_unused, append_missing, delete_empty):
content[start:end] = [None]*(end-start) content[start:end] = [None]*(end-start)
if delete_empty and not expr: if delete_empty and not expr:
content[start:end] = [None]*(end-start) content[start:end] = [None]*(end-start)
content = [line for line in content if line != None] content = [line for line in content if line is not None]
if append_missing: if append_missing:
missing = [index for index in range(len(local)) if index not in supported] missing = [index for index in range(len(local)) if index not in supported]
if missing: if missing:
if content[-1] != "\n": if content[-1] != "\n":
content.append("\n") content.append("\n")
for i, miss in enumerate(missing): for miss in missing:
if local[miss][1] != "": if local[miss][1] != "":
content.append("["+local[miss][1]+"]\n") content.append("["+local[miss][1]+"]\n")
content.append(local[miss][0]+"\n== \n\n") content.append(local[miss][0]+"\n== \n\n")
content[-1] = content[-1][:-1] content[-1] = content[-1][:-1]
return "".join(content) return "".join(content)
if __name__ == '__main__': def main(argv):
os.chdir(os.path.dirname(__file__) + "/../..") os.chdir(os.path.dirname(__file__) + "/../..")
if len(sys.argv) < 3: if len(argv) < 3:
print("usage: python copy_fix.py <infile> <outfile> [--delete-unused] [--append-missing] [--delete-empty]") print("usage: python copy_fix.py <infile> <outfile> [--delete-unused] [--append-missing] [--delete-empty]")
sys.exit() sys.exit()
infile = sys.argv[1] infile = argv[1]
outfile = sys.argv[2] outfile = argv[2]
args = sys.argv[3:] args = argv[3:]
delete_unused = False delete_unused = False
append_missing = False append_missing = False
delete_empty = False delete_empty = False
@ -60,3 +61,6 @@ if __name__ == '__main__':
open(outfile, "w").write("".join(content)) open(outfile, "w").write("".join(content))
print("Successfully created '" + outfile + "'.") print("Successfully created '" + outfile + "'.")
if __name__ == '__main__':
main(sys.argv)

View file

@ -5,11 +5,11 @@ from collections import OrderedDict
class LanguageDecodeError(Exception): class LanguageDecodeError(Exception):
def __init__(self, message, filename, line): def __init__(self, message, filename, line):
error = "File \"{1}\", line {2}: {0}".format(message, filename, line+1) error = "File \"{1}\", line {2}: {0}".format(message, filename, line+1)
super(LanguageDecodeError, self).__init__(error) super().__init__(error)
# Taken from https://stackoverflow.com/questions/30011379/how-can-i-parse-a-c-format-string-in-python # Taken from https://stackoverflow.com/questions/30011379/how-can-i-parse-a-c-format-string-in-python
cfmt = '''\ cfmt = r'''\
( # start of capture group 1 ( # start of capture group 1
% # literal "%" % # literal "%"
(?: # first option (?: # first option
@ -27,10 +27,10 @@ def decode(fileobj, elements_per_key):
data = {} data = {}
current_context = "" current_context = ""
current_key = None current_key = None
index = -1
for index, line in enumerate(fileobj): for index, line in enumerate(fileobj):
line = line.encode("utf-8").decode("utf-8-sig") line = line.encode("utf-8").decode("utf-8-sig")
line = line[:-1] line = line[:-1]
context = ""
if line and line[-1] == "\r": if line and line[-1] == "\r":
line = line[:-1] line = line[:-1]
if not line or line[:1] == "#": if not line or line[:1] == "#":
@ -45,7 +45,7 @@ def decode(fileobj, elements_per_key):
if len(data[current_key]) >= 1+elements_per_key: if len(data[current_key]) >= 1+elements_per_key:
raise LanguageDecodeError("Wrong number of elements per key", fileobj.name, index) raise LanguageDecodeError("Wrong number of elements per key", fileobj.name, index)
if current_key: if current_key:
original = current_key[0] original = current_key[0] # pylint: disable=E1136
translation = line[3:] translation = line[3:]
if translation and [m.group(1) for m in re.finditer(cfmt, original, flags=re.X)] != [m.group(1) for m in re.finditer(cfmt, translation, flags=re.X)]: if translation and [m.group(1) for m in re.finditer(cfmt, original, flags=re.X)] != [m.group(1) for m in re.finditer(cfmt, translation, flags=re.X)]:
raise LanguageDecodeError("Non-matching formatting string", fileobj.name, index) raise LanguageDecodeError("Non-matching formatting string", fileobj.name, index)
@ -69,18 +69,18 @@ def decode(fileobj, elements_per_key):
def check_file(path): def check_file(path):
with open(path) as fileobj: with open(path) as fileobj:
matches = re.findall("Localize\s*\(\s*\"([^\"]+)\"(?:\s*,\s*\"([^\"]+)\")?\s*\)", fileobj.read()) matches = re.findall(r"Localize\s*\(\s*\"([^\"]+)\"(?:\s*,\s*\"([^\"]+)\")?\s*\)", fileobj.read())
return matches return matches
def check_folder(path): def check_folder(path):
englishlist = OrderedDict() englishlist = OrderedDict()
for path, dirs, files in os.walk(path): for path2, dirs, files in os.walk(path):
dirs.sort() dirs.sort()
for f in sorted(files): for f in sorted(files):
if not any(f.endswith(x) for x in ".cpp .c .h".split()): if not any(f.endswith(x) for x in ".cpp .c .h".split()):
continue continue
for sentence in check_file(os.path.join(path, f)): for sentence in check_file(os.path.join(path2, f)):
englishlist[sentence] = None englishlist[sentence] = None
return englishlist return englishlist
@ -92,8 +92,7 @@ def languages():
def translations(filename): def translations(filename):
translations = decode(open(filename), 1) return decode(open(filename), 1)
return translations
def localizes(): def localizes():

View file

@ -1,351 +0,0 @@
import os, re, sys
alphanum = "0123456789abcdefghijklmnopqrstuvwzyxABCDEFGHIJKLMNOPQRSTUVWXYZ_"
cpp_keywords = ["auto", "const", "double", "float", "int", "short", "struct", "unsigned", # C
"break", "continue", "else", "for", "long", "signed", "switch", "void",
"case", "default", "enum", "goto", "register", "sizeof", "typedef", "volatile",
"char", "do", "extern", "if", "return", "static", "union", "while",
"asm", "dynamic_cast", "namespace", "reinterpret_cast", "try", # C++
"bool", "explicit", "new", "static_cast", "typeid",
"catch", "false", "operator", "template", "typename",
"class", "friend", "private", "this", "using",
"const_cast", "inline", "public", "throw", "virtual",
"delete", "mutable", "protected", "true", "wchar_t"]
allowed_words = []
#allowed_words += ["bitmap_left", "advance", "glyph"] # ft2
allowed_words += ["qsort"] # stdio / stdlib
allowed_words += ["size_t", "cosf", "sinf", "asinf", "acosf", "atanf", "powf", "fabs", "rand", "powf", "fmod", "sqrtf"] # math.h
allowed_words += ["time_t", "time", "strftime", "localtime"] # time.h
allowed_words += [ # system.h
"int64",
"dbg_assert", "dbg_msg", "dbg_break", "dbg_logger_stdout", "dbg_logger_debugger", "dbg_logger_file",
"mem_alloc", "mem_zero", "mem_free", "mem_copy", "mem_move", "mem_comp", "mem_stats", "total_allocations", "allocated",
"thread_create", "thread_sleep", "lock_wait", "lock_create", "lock_release", "lock_destroy", "swap_endian",
"io_open", "io_read", "io_read", "io_write", "io_flush", "io_close", "io_seek", "io_skip", "io_tell", "io_length",
"str_comp", "str_length", "str_quickhash", "str_format", "str_copy", "str_comp_nocase", "str_sanitize", "str_append",
"str_comp_num", "str_find_nocase", "str_sanitize_strong", "str_uppercase", "str_toint", "str_tofloat",
"str_utf8_encode", "str_utf8_rewind", "str_utf8_forward", "str_utf8_decode", "str_sanitize_cc", "str_skip_whitespaces",
"fs_makedir", "fs_listdir", "fs_storage_path", "fs_is_dir",
"net_init", "net_addr_comp", "net_host_lookup", "net_addr_str", "type", "port", "net_addr_from_str",
"net_udp_create", "net_udp_send", "net_udp_recv", "net_udp_close", "net_socket_read_wait",
"net_stats", "sent_bytes", "recv_bytes", "recv_packets", "sent_packets",
"time_get", "time_freq", "time_timestamp"]
allowed_words += ["vec2", "vec3", "vec4", "round", "clamp", "length", "dot", "normalize", "frandom", "mix", "distance", "min",
"closest_point_on_line", "max", "absolute"] # math.hpp
allowed_words += [ # tl
"array", "sorted_array", "string",
"all", "sort", "add", "remove_index", "remove", "delete_all", "set_size",
"base_ptr", "size", "swap", "empty", "front", "pop_front", "find_binary", "find_linear", "clear", "range", "end", "cstr",
"partition_linear", "partition_binary"]
allowed_words += ["fx2f", "f2fx"] # fixed point math
def CheckIdentifier(ident):
return False
class Checker:
def CheckStart(self, checker, filename):
pass
def CheckLine(self, checker, line):
pass
def CheckEnd(self, checker):
pass
class FilenameExtentionChecker(Checker):
def __init__(self):
self.allowed = [".cpp", ".h"]
def CheckStart(self, checker, filename):
ext = os.path.splitext(filename)[1]
if not ext in self.allowed:
checker.Error("file extension '%s' is not allowed" % ext)
class IncludeChecker(Checker):
def __init__(self):
self.disallowed_headers = ["stdio.h", "stdlib.h", "string.h", "memory.h"]
def CheckLine(self, checker, line):
if "#include" in line:
include_file = ""
if '<' in line:
include_file = line.split('<')[1].split(">")[0]
#if not "/" in include_file:
# checker.Error("%s is not allowed" % include_file)
elif '"' in line:
include_file = line.split('"')[1]
#print include_file
if include_file in self.disallowed_headers:
checker.Error("%s is not allowed" % include_file)
class HeaderGuardChecker(Checker):
def CheckStart(self, checker, filename):
self.check = ".h" in filename
self.guard = "#ifndef " + filename[4:].replace("/", "_").replace(".hpp", "").replace(".h", "").upper() + "_H"
def CheckLine(self, checker, line):
if self.check:
#if "#" in line:
self.check = False
#if not self.check:
if line.strip() == self.guard:
pass
else:
checker.Error("malformed or missing header guard. Should be '%s'" % self.guard)
class CommentChecker(Checker):
def CheckLine(self, checker, line):
if line.strip()[-2:] == "*/" and "/*" in line:
checker.Error("single line multiline comment")
class FileChecker:
def __init__(self):
self.checkers = []
self.checkers += [FilenameExtentionChecker()]
self.checkers += [HeaderGuardChecker()]
self.checkers += [IncludeChecker()]
self.checkers += [CommentChecker()]
def Error(self, errormessage):
self.current_errors += [(self.current_line, errormessage)]
def CheckLine(self, line):
for c in self.checkers:
c.CheckLine(self, line)
return True
def CheckFile(self, filename):
self.current_file = filename
self.current_line = 0
self.current_errors = []
for c in self.checkers:
c.CheckStart(self, filename)
for line in file(filename).readlines():
self.current_line += 1
if "ignore_check" in line:
continue
self.CheckLine(line)
for c in self.checkers:
c.CheckEnd(self)
def GetErrors(self):
return self.current_errors
def cstrip(lines):
d = ""
for l in lines:
if "ignore_convention" in l:
continue
l = re.sub("^[\t ]*#.*", "", l)
l = re.sub("//.*", "", l)
l = re.sub('\".*?\"', '"String"', l) # remove strings
d += l.strip() + " "
d = re.sub('\/\*.*?\*\/', "", d) # remove /* */ comments
d = d.replace("\t", " ") # tab to space
d = re.sub(" *", " ", d) # remove double spaces
#d = re.sub("", "", d) # remove /* */ comments
d = d.strip()
# this eats up cases like 'n {'
i = 1
while i < len(d)-2:
if d[i] == ' ':
if not (d[i-1] in alphanum and d[i+1] in alphanum):
d = d[:i] + d[i+1:]
i += 1
return d
#def stripstrings(data):
# return re.sub('\".*?\"', 'STRING', data)
def get_identifiers(data):
idents = {}
data = " "+data+" "
regexp = re.compile("[^a-zA-Z0-9_][a-zA-Z_][a-zA-Z0-9_]+[^a-zA-Z0-9_]")
start = 0
while 1:
m = regexp.search(data, start)
if m == None:
break
start = m.end()-1
name = data[m.start()+1:m.end()-1]
if name in idents:
idents[name] += 1
else:
idents[name] = 1
return idents
grand_total = 0
grand_offenders = 0
gen_html = 1
if gen_html:
print "<head>"
print '<link href="/style.css" rel="stylesheet" type="text/css" />'
print "</head>"
print "<body>"
print '<div id="outer">'
print '<div id="top_left"><div id="top_right"><div id="top_mid">'
print '<a href="/"><img src="/images/twlogo.png" alt="teeworlds logo" /></a>'
print '</div></div></div>'
print '<div id="menu_left"><div id="menu_right"><div id="menu_mid">'
print '</div></div></div>'
print '<div id="tlc"><div id="trc"><div id="tb">&nbsp;</div></div></div>'
print '<div id="lb"><div id="rb"><div id="mid">'
print '<div id="container">'
print '<p class="topic_text">'
print '<h1>Code Refactoring Progress</h1>'
print '''This is generated by a script that find identifiers in the code
that doesn't conform to the code standard. Right now it only shows headers
because they need to be fixed before we can do the rest of the source.
This is a ROUGH estimate of the progress'''
print '</p>'
print '<p class="topic_text">'
print '<table>'
#print "<tr><td><b>%</b></td><td><b>#</b></td><td><b>File</b></td><td><b>Offenders</b></td></tr>"
line_order = 1
total_files = 0
complete_files = 0
total_errors = 0
for (root,dirs,files) in os.walk("src"):
for filename in files:
filename = os.path.join(root, filename)
if "/." in filename or "/external/" in filename or "/base/" in filename or "/generated/" in filename:
continue
if "src/osxlaunch/client.h" in filename: # ignore this file, ObjC file
continue
if "e_config_variables.h" in filename: # ignore config files
continue
if "src/game/variables.hpp" in filename: # ignore config files
continue
if not (".hpp" in filename or ".h" in filename or ".cpp" in filename):
continue
#total_files += 1
#if not "src/engine/client/ec_client.cpp" in filename:
# continue
f = FileChecker()
f.CheckFile(filename)
num_errors = len(f.GetErrors())
total_errors += num_errors
if num_errors:
print '<tr style="background: #e0e0e0"><td colspan="2">%s, %d errors</td></tr>' % (filename, num_errors),
for line, msg in f.GetErrors():
print '<tr"><td>%d</td><td>%s</td></tr>' % (line, msg)
#print '<table>'
#GetErrors()
if 0:
text = cstrip(file(filename).readlines()) # remove all preprocessor stuff and comments
#text = stripstrings(text) # remove strings (does not solve all cases however)
#print text
idents = get_identifiers(text)
offenders = 0
total = 0
offender_list = {}
for name in idents:
#print name
if len(name) <= 2: # skip things that are too small
continue
if name in cpp_keywords: # skip keywords
continue
if name in allowed_words: # skip allowed keywords
continue
total += idents[name]
if name != name.lower(): # strip names that are not only lower case
continue
offender_list[name] = idents[name]
if not gen_html:
print "[%d] %s"%(idents[name], name)
offenders += idents[name]
grand_total += total
grand_offenders += offenders
if total == 0:
total = 1
line_order = -line_order
done = int((1-(offenders / float(total))) * 100)
if done == 100:
complete_files += 1
if done != 100 and gen_html:
color = "#ffa0a0"
if done > 20:
color = "#ffd080"
if done > 50:
color = "#ffff80"
if done > 75:
color = "#e0ff80"
if done == 100:
color = "#80ff80"
line_color = "#f0efd5"
if line_order > 0:
line_color = "#ffffff"
offender_string = ""
count = 0
for name in offender_list:
count += 1
offender_string += "[%d]%s " % (offender_list[name], name)
if count%5 == 0:
offender_string += "<br/>"
print '<tr style="background: %s">' % line_color,
print '<td style="text-align: right; background: %s"><b>%d%%</b></td><td style="text-align: center">%d</td><td>%s</td>' % (color, done, offenders, filename),
print '<td style="text-align: right">%s</td>' % offender_string
print "</tr>"
count = 0
if gen_html:
print "</table>"
print "<h1>%d errors</h1>" % total_errors
if 0:
print "<h1>%.1f%% Identifiers done</h1>" % ((1-(grand_offenders / float(grand_total))) * 100)
print "%d left of %d" % (grand_offenders, grand_total)
print "<h1>%.1f%% Files done</h1>" % ((complete_files / float(total_files)) * 100)
print "%d left of %d" % (total_files-complete_files, total_files)
print "</p>"
print "<div style='clear:both;'></div>"
print '</div>'
print '</div></div></div>'
print '<div id="blc"><div id="brc"><div id="bb">&nbsp;</div></div></div>'
print '</div>'
print "</body>"

View file

@ -1,6 +1,6 @@
# coding: utf-8 # coding: utf-8
from socket import * # pylint: skip-file
import struct from socket import socket, AF_INET, SOCK_DGRAM
import sys import sys
import threading import threading
import time import time
@ -25,9 +25,9 @@ PACKET_GETINFO3 = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgie3" + "\x00"
class Server_Info(threading.Thread): class Server_Info(threading.Thread):
def __init__(self, address, type): def __init__(self, address, typ):
self.address = address self.address = address
self.type = type self.type = typ
self.finished = False self.finished = False
threading.Thread.__init__(self, target = self.run) threading.Thread.__init__(self, target = self.run)
@ -45,9 +45,9 @@ class Server_Info(threading.Thread):
def get_server_info(address): def get_server_info(address):
try: try:
sock = socket(AF_INET, SOCK_DGRAM) sock = socket(AF_INET, SOCK_DGRAM)
sock.settimeout(TIMEOUT); sock.settimeout(TIMEOUT)
sock.sendto(PACKET_GETINFO, address) sock.sendto(PACKET_GETINFO, address)
data, addr = sock.recvfrom(1024) data, _addr = sock.recvfrom(1024)
sock.close() sock.close()
data = data[14:] # skip header data = data[14:] # skip header
@ -64,7 +64,7 @@ def get_server_info(address):
server_info["max_players"] = int(slots[7]) server_info["max_players"] = int(slots[7])
server_info["players"] = [] server_info["players"] = []
for i in xrange(0, server_info["num_players"]): for i in range(0, server_info["num_players"]):
player = {} player = {}
player["name"] = slots[8+i*2] player["name"] = slots[8+i*2]
player["score"] = int(slots[8+i*2+1]) player["score"] = int(slots[8+i*2+1])
@ -80,9 +80,9 @@ def get_server_info(address):
def get_server_info2(address): def get_server_info2(address):
try: try:
sock = socket(AF_INET, SOCK_DGRAM) sock = socket(AF_INET, SOCK_DGRAM)
sock.settimeout(TIMEOUT); sock.settimeout(TIMEOUT)
sock.sendto(PACKET_GETINFO2, address) sock.sendto(PACKET_GETINFO2, address)
data, addr = sock.recvfrom(1024) data, _addr = sock.recvfrom(1024)
sock.close() sock.close()
data = data[14:] # skip header data = data[14:] # skip header
@ -100,7 +100,7 @@ def get_server_info2(address):
server_info["max_players"] = int(slots[8]) server_info["max_players"] = int(slots[8])
server_info["players"] = [] server_info["players"] = []
for i in xrange(0, server_info["num_players"]): for i in range(0, server_info["num_players"]):
player = {} player = {}
player["name"] = slots[9+i*2] player["name"] = slots[9+i*2]
player["score"] = int(slots[9+i*2+1]) player["score"] = int(slots[9+i*2+1])
@ -116,7 +116,7 @@ def get_server_info2(address):
def get_server_info3(address): def get_server_info3(address):
try: try:
sock = socket(AF_INET, SOCK_DGRAM) sock = socket(AF_INET, SOCK_DGRAM)
sock.settimeout(TIMEOUT); sock.settimeout(TIMEOUT)
sock.sendto(PACKET_GETINFO3, address) sock.sendto(PACKET_GETINFO3, address)
data, addr = sock.recvfrom(1400) data, addr = sock.recvfrom(1400)
sock.close() sock.close()
@ -137,7 +137,7 @@ def get_server_info3(address):
server_info["max_clients"] = int(slots[9]) server_info["max_clients"] = int(slots[9])
server_info["players"] = [] server_info["players"] = []
for i in xrange(0, server_info["num_clients"]): for i in range(0, server_info["num_clients"]):
player = {} player = {}
player["name"] = slots[10+i*5] player["name"] = slots[10+i*5]
player["clan"] = slots[10+i*5+1] player["clan"] = slots[10+i*5+1]
@ -178,7 +178,7 @@ def get_list(address):
sock.sendto(PACKET_GETLIST, address) sock.sendto(PACKET_GETLIST, address)
while 1: while 1:
data, addr = sock.recvfrom(1024) data, _addr = sock.recvfrom(1024)
data = data[14:] data = data[14:]
num_servers = len(data) / 6 num_servers = len(data) / 6
@ -203,7 +203,7 @@ def get_list2(address):
sock.sendto(PACKET_GETLIST2, address) sock.sendto(PACKET_GETLIST2, address)
while 1: while 1:
data, addr = sock.recvfrom(1400) data, _addr = sock.recvfrom(1400)
data = data[14:] data = data[14:]
num_servers = len(data) / 18 num_servers = len(data) / 18
@ -234,7 +234,7 @@ for i in range(1, NUM_MASTERSERVERS+1):
servers = [] servers = []
while len(master_servers) != 0: while len(master_servers) != 0:
if master_servers[0].finished == True: if master_servers[0].finished:
if master_servers[0].servers: if master_servers[0].servers:
servers += master_servers[0].servers servers += master_servers[0].servers
del master_servers[0] del master_servers[0]
@ -242,7 +242,7 @@ while len(master_servers) != 0:
servers_info = [] servers_info = []
print str(len(servers)) + " servers" print(str(len(servers)) + " servers")
for server in servers: for server in servers:
s = Server_Info(server[0], server[1]) s = Server_Info(server[0], server[1])
@ -254,7 +254,7 @@ num_players = 0
num_clients = 0 num_clients = 0
while len(servers_info) != 0: while len(servers_info) != 0:
if servers_info[0].finished == True: if servers_info[0].finished:
if servers_info[0].info: if servers_info[0].info:
num_players += servers_info[0].info["num_players"] num_players += servers_info[0].info["num_players"]
@ -267,4 +267,4 @@ while len(servers_info) != 0:
time.sleep(0.001) # be nice time.sleep(0.001) # be nice
print str(num_players) + " players and " + str(num_clients-num_players) + " spectators" print(str(num_players) + " players and " + str(num_clients-num_players) + " spectators")