Compare commits
7 Commits
3c804a9b8b
...
d055090dd2
Author | SHA1 | Date | |
---|---|---|---|
d055090dd2 | |||
c49d4eedd0 | |||
8519eb9b86 | |||
0efaf5ac4b | |||
eeb0f1cce6 | |||
2a06eea08a | |||
393ad6c8a6 |
5
.gitignore
vendored
5
.gitignore
vendored
@ -96,3 +96,8 @@ Thumbs.db
|
||||
|
||||
# macOS specific data
|
||||
.DS_Store
|
||||
|
||||
# IDE files
|
||||
/.vs/
|
||||
/.vscode/
|
||||
/.idea/
|
||||
|
@ -518,8 +518,13 @@ enabled = true ; The STUN protocol allows hosting games wi
|
||||
; If STUN is disabled, the game relies on direct connection, UPnP and port forwarding.
|
||||
server = "lobby.wildfiregames.com" ; Address of the STUN server.
|
||||
port = 3478 ; Port of the STUN server.
|
||||
delay = 200 ; Duration in milliseconds that is waited between STUN messages.
|
||||
; Smaller numbers speed up joins but also become less stable.
|
||||
delay = 10 ; Duration in milliseconds that is waited between checking for retrieved STUN responses.
|
||||
; Smaller numbers speed up joins but may make them less stable, if max_tries isn't increased proportionally as well.
|
||||
max_tries = 100 ; Maximum number of tries for receiving STUN responses.
|
||||
|
||||
[lobby.fw_punch]
|
||||
delay = 200 ; Duration in milliseconds between sending hole punching messages.
|
||||
num_msg = 3 ; Number of hole punching messages to send.
|
||||
|
||||
[mod]
|
||||
enabledmods = "mod public"
|
||||
|
@ -43,11 +43,23 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
stage("Debug Build") {
|
||||
steps {
|
||||
bat("cd build\\workspaces\\vs2017 && ${visualStudioPath} pyrogenesis.sln /p:Configuration=Debug ${buildOptions}")
|
||||
timeout(time: 15) {
|
||||
bat "cd binaries\\system && test_dbg.exe > cxxtest-debug.xml"
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit 'binaries/system/cxxtest-debug.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage ("Release Build") {
|
||||
steps {
|
||||
dir('build\\workspaces\\vs2017'){
|
||||
bat("${visualStudioPath} pyrogenesis.sln /p:Configuration=Release ${buildOptions}")
|
||||
}
|
||||
bat("cd build\\workspaces\\vs2017 && ${visualStudioPath} pyrogenesis.sln /p:Configuration=Release ${buildOptions}")
|
||||
timeout(time: 5) {
|
||||
bat "cd binaries\\system && test.exe > cxxtest-release.xml"
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* Copyright (C) 2013-2016 SuperTuxKart-Team.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
@ -183,12 +183,13 @@ bool ReceiveStunResponse(ENetHost& transactionHost, std::vector<u8>& buffer)
|
||||
ENetAddress sender = m_StunServer;
|
||||
int len = enet_socket_receive(transactionHost.socket, &sender, &enetBuffer, 1);
|
||||
|
||||
int delay = 200;
|
||||
int delay = 10;
|
||||
CFG_GET_VAL("lobby.stun.delay", delay);
|
||||
int maxTries = 100;
|
||||
CFG_GET_VAL("lobby.stun.max_tries", maxTries);
|
||||
|
||||
// Wait to receive the message because enet sockets are non-blocking
|
||||
const int max_tries = 5;
|
||||
for (int count = 0; len <= 0 && (count < max_tries || max_tries == -1); ++count)
|
||||
for (int count = 0; len <= 0 && (count < maxTries || maxTries == -1); ++count)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
|
||||
len = enet_socket_receive(transactionHost.socket, &sender, &enetBuffer, 1);
|
||||
@ -359,10 +360,12 @@ void SendHolePunchingMessages(ENetHost& enetClient, const std::string& serverAdd
|
||||
enet_address_set_host(&addr, serverAddress.c_str());
|
||||
|
||||
int delay = 200;
|
||||
CFG_GET_VAL("lobby.stun.delay", delay);
|
||||
CFG_GET_VAL("lobby.fw_punch.delay", delay);
|
||||
int numMsg = 3;
|
||||
CFG_GET_VAL("lobby.fw_punch.num_msg", numMsg);
|
||||
|
||||
// Send an UDP message from enet host to ip:port
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int i = 0; i < numMsg || numMsg == -1; ++i)
|
||||
{
|
||||
SendStunRequest(enetClient, addr);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
|
||||
|
@ -39,6 +39,7 @@ class CheckRefs:
|
||||
self.supportedAudioFormats = "ogg"
|
||||
self.mods = []
|
||||
self.__init_logger
|
||||
self.inError = False
|
||||
|
||||
@property
|
||||
def __init_logger(self):
|
||||
@ -133,13 +134,17 @@ class CheckRefs:
|
||||
from validate_grammar import RelaxNGValidator
|
||||
|
||||
validate = RelaxNGValidator(self.vfs_root, self.mods)
|
||||
validate.run()
|
||||
if not validate.run():
|
||||
self.inError = True
|
||||
if args.validate_actors:
|
||||
sys.path.append("../xmlvalidator/")
|
||||
from validator import Validator
|
||||
|
||||
validator = Validator(self.vfs_root, self.mods)
|
||||
validator.run()
|
||||
if not validator.run():
|
||||
self.inError = True
|
||||
|
||||
return self.inError
|
||||
|
||||
def get_mod_dependencies(self, *mods):
|
||||
modjsondeps = []
|
||||
@ -212,7 +217,8 @@ class CheckRefs:
|
||||
# ignore terrains.xml
|
||||
if name != "terrains":
|
||||
if name in terrains:
|
||||
self.logger.warning(
|
||||
self.inError = True
|
||||
self.logger.error(
|
||||
f"Duplicate terrain name '{name}' (from '{terrains[name]}' and '{ffp}')"
|
||||
)
|
||||
terrains[name] = str(fp)
|
||||
@ -287,11 +293,10 @@ class CheckRefs:
|
||||
if not str(fp).startswith("template_"):
|
||||
self.roots.append(str(fp))
|
||||
if (
|
||||
entity
|
||||
and entity.find("VisualActor") is not None
|
||||
entity.find("VisualActor") is not None
|
||||
and entity.find("VisualActor").find("Actor") is not None
|
||||
):
|
||||
if entity.find("Identity"):
|
||||
if entity.find("Identity") is not None:
|
||||
phenotype_tag = entity.find("Identity").find("Phenotype")
|
||||
phenotypes = split(
|
||||
r"\s",
|
||||
@ -309,9 +314,9 @@ class CheckRefs:
|
||||
actor_path = actor.text
|
||||
self.deps.append((str(fp), f"art/actors/{actor_path}"))
|
||||
foundation_actor = entity.find("VisualActor").find("FoundationActor")
|
||||
if foundation_actor:
|
||||
if foundation_actor is not None:
|
||||
self.deps.append((str(fp), f"art/actors/{foundation_actor.text}"))
|
||||
if entity.find("Sound"):
|
||||
if entity.find("Sound") is not None:
|
||||
phenotype_tag = entity.find("Identity").find("Phenotype")
|
||||
phenotypes = split(
|
||||
r"\s",
|
||||
@ -322,18 +327,19 @@ class CheckRefs:
|
||||
lang_tag = entity.find("Identity").find("Lang")
|
||||
lang = lang_tag.text if lang_tag is not None and lang_tag.text else "greek"
|
||||
sound_groups = entity.find("Sound").find("SoundGroups")
|
||||
for sound_group in sound_groups:
|
||||
if sound_group.text and sound_group.text.strip():
|
||||
if "{phenotype}" in sound_group.text:
|
||||
for phenotype in phenotypes:
|
||||
# see simulation/components/Sound.js and Identity.js for explanation
|
||||
sound_path = sound_group.text.replace(
|
||||
"{phenotype}", phenotype
|
||||
).replace("{lang}", lang)
|
||||
if sound_groups is not None and len(sound_groups) > 0:
|
||||
for sound_group in sound_groups:
|
||||
if sound_group.text and sound_group.text.strip():
|
||||
if "{phenotype}" in sound_group.text:
|
||||
for phenotype in phenotypes:
|
||||
# see simulation/components/Sound.js and Identity.js for explanation
|
||||
sound_path = sound_group.text.replace(
|
||||
"{phenotype}", phenotype
|
||||
).replace("{lang}", lang)
|
||||
self.deps.append((str(fp), f"audio/{sound_path}"))
|
||||
else:
|
||||
sound_path = sound_group.text.replace("{lang}", lang)
|
||||
self.deps.append((str(fp), f"audio/{sound_path}"))
|
||||
else:
|
||||
sound_path = sound_group.text.replace("{lang}", lang)
|
||||
self.deps.append((str(fp), f"audio/{sound_path}"))
|
||||
if entity.find("Identity") is not None:
|
||||
icon = entity.find("Identity").find("Icon")
|
||||
if icon is not None and icon.text:
|
||||
@ -540,7 +546,7 @@ class CheckRefs:
|
||||
material_elem = ElementTree.parse(ffp).getroot()
|
||||
for alternative in material_elem.findall("alternative"):
|
||||
material = alternative.get("material")
|
||||
if material:
|
||||
if material is not None:
|
||||
self.deps.append((str(fp), f"art/materials/{material}"))
|
||||
|
||||
def add_particles(self):
|
||||
@ -550,7 +556,7 @@ class CheckRefs:
|
||||
self.roots.append(str(fp))
|
||||
particle = ElementTree.parse(ffp).getroot()
|
||||
texture = particle.find("texture")
|
||||
if texture:
|
||||
if texture is not None:
|
||||
self.deps.append((str(fp), texture.text))
|
||||
|
||||
def add_soundgroups(self):
|
||||
@ -811,9 +817,8 @@ class CheckRefs:
|
||||
continue
|
||||
|
||||
callers = [str(self.vfs_to_relative_to_mods(ref)) for ref in reverse_deps[dep]]
|
||||
self.logger.warning(
|
||||
f"Missing file '{dep}' referenced by: {', '.join(sorted(callers))}"
|
||||
)
|
||||
self.logger.error(f"Missing file '{dep}' referenced by: {', '.join(sorted(callers))}")
|
||||
self.inError = True
|
||||
if dep.lower() in lower_case_files:
|
||||
self.logger.warning(
|
||||
f"### Case-insensitive match (found '{lower_case_files[dep.lower()]}')"
|
||||
@ -859,4 +864,5 @@ class CheckRefs:
|
||||
|
||||
if __name__ == "__main__":
|
||||
check_ref = CheckRefs()
|
||||
check_ref.main()
|
||||
if not check_ref.main():
|
||||
sys.exit(1)
|
||||
|
@ -50,6 +50,7 @@ class RelaxNGValidator:
|
||||
errorch.setFormatter(Formatter("%(levelname)s - %(message)s"))
|
||||
logger.addHandler(errorch)
|
||||
self.logger = logger
|
||||
self.inError = False
|
||||
|
||||
def run(self):
|
||||
self.validate_actors()
|
||||
@ -62,13 +63,14 @@ class RelaxNGValidator:
|
||||
self.validate_soundgroups()
|
||||
self.validate_terrains()
|
||||
self.validate_textures()
|
||||
return self.inError
|
||||
|
||||
def main(self):
|
||||
"""Program entry point, parses command line arguments and launches the validation"""
|
||||
# ordered uniq mods (dict maintains ordered keys from python 3.6)
|
||||
self.logger.info(f"Checking {'|'.join(self.mods)}'s integrity.")
|
||||
self.logger.info(f"The following mods will be loaded: {'|'.join(self.mods)}.")
|
||||
self.run()
|
||||
return self.run()
|
||||
|
||||
def find_files(self, vfs_root, mods, vfs_path, *ext_list):
|
||||
"""
|
||||
@ -207,6 +209,7 @@ class RelaxNGValidator:
|
||||
self.logger.info(f"{error_count} {name} validation errors")
|
||||
elif error_count > 0:
|
||||
self.logger.error(f"{error_count} {name} validation errors")
|
||||
self.inError = True
|
||||
|
||||
|
||||
def get_mod_dependencies(vfs_root, *mods):
|
||||
@ -247,4 +250,5 @@ if __name__ == "__main__":
|
||||
dict.fromkeys([*args.mods, *get_mod_dependencies(args.root, *args.mods), "mod"]).keys()
|
||||
)
|
||||
relax_ng_validator = RelaxNGValidator(args.root, mods=mods, verbose=args.verbose)
|
||||
relax_ng_validator.main()
|
||||
if not relax_ng_validator.main():
|
||||
sys.exit(1)
|
||||
|
@ -113,6 +113,7 @@ class Validator:
|
||||
errorch.setFormatter(Formatter("%(levelname)s - %(message)s"))
|
||||
logger.addHandler(errorch)
|
||||
self.logger = logger
|
||||
self.inError = False
|
||||
|
||||
def get_mod_path(self, mod_name, vfs_path):
|
||||
return os.path.join(mod_name, vfs_path)
|
||||
@ -182,6 +183,7 @@ class Validator:
|
||||
'"%s": unknown material "%s"'
|
||||
% (self.get_mod_path(actor.mod_name, actor.vfs_path), actor.material)
|
||||
)
|
||||
self.inError = True
|
||||
if actor.material not in self.materials:
|
||||
continue
|
||||
material = self.materials[actor.material]
|
||||
@ -204,6 +206,7 @@ class Validator:
|
||||
material.name,
|
||||
)
|
||||
)
|
||||
self.inError = True
|
||||
|
||||
extra_textures = ", ".join(
|
||||
set(
|
||||
@ -223,6 +226,9 @@ class Validator:
|
||||
material.name,
|
||||
)
|
||||
)
|
||||
self.inError = True
|
||||
|
||||
return self.inError
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@ -233,4 +239,5 @@ if __name__ == "__main__":
|
||||
parser.add_argument("-m", "--mods", action="store", dest="mods", default="mod,public")
|
||||
args = parser.parse_args()
|
||||
validator = Validator(args.root, args.mods.split(","))
|
||||
validator.run()
|
||||
if not validator.run():
|
||||
sys.exit(1)
|
||||
|
Loading…
Reference in New Issue
Block a user