Merge branch 'main' into expanded_tests

This commit is contained in:
Fabian Dill 2020-12-19 19:40:12 +01:00
commit c87dd5d2d3
39 changed files with 2270 additions and 369 deletions

2
.gitignore vendored
View File

@ -32,3 +32,5 @@ mystery_result_*.yaml
/db.db3 /db.db3
*-errors.txt *-errors.txt
success.txt success.txt
output/
Output Logs/

View File

@ -139,7 +139,7 @@ def link_entrances(world, player):
dw_must_exits = list(DW_Entrances_Must_Exit) dw_must_exits = list(DW_Entrances_Must_Exit)
old_man_entrances = list(Old_Man_Entrances) old_man_entrances = list(Old_Man_Entrances)
caves = list(Cave_Exits + Cave_Three_Exits) caves = list(Cave_Exits + Cave_Three_Exits)
single_doors = list(Single_Cave_Doors)
bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors + Bomb_Shop_Multi_Cave_Doors) bomb_shop_doors = list(Bomb_Shop_Single_Cave_Doors + Bomb_Shop_Multi_Cave_Doors)
blacksmith_doors = list(Blacksmith_Single_Cave_Doors + Blacksmith_Multi_Cave_Doors) blacksmith_doors = list(Blacksmith_Single_Cave_Doors + Blacksmith_Multi_Cave_Doors)
door_targets = list(Single_Cave_Targets) door_targets = list(Single_Cave_Targets)

16
Gui.py
View File

@ -1525,8 +1525,8 @@ class SpriteSelector():
title_link.pack(side=LEFT) title_link.pack(side=LEFT)
title_link.bind("<Button-1>", open_custom_sprite_dir) title_link.bind("<Button-1>", open_custom_sprite_dir)
self.icon_section(alttpr_frametitle, self.alttpr_sprite_dir + '/*', 'ALTTPR sprites not found. Click "Update alttpr sprites" to download them.') self.icon_section(alttpr_frametitle, self.alttpr_sprite_dir, 'ALTTPR sprites not found. Click "Update alttpr sprites" to download them.')
self.icon_section(custom_frametitle, self.custom_sprite_dir + '/*', 'Put sprites in the custom sprites folder (see open link above) to have them appear here.') self.icon_section(custom_frametitle, self.custom_sprite_dir, 'Put sprites in the custom sprites folder (see open link above) to have them appear here.')
frame = Frame(self.window) frame = Frame(self.window)
frame.pack(side=BOTTOM, fill=X, pady=5) frame.pack(side=BOTTOM, fill=X, pady=5)
@ -1585,19 +1585,21 @@ class SpriteSelector():
sprites = [] sprites = []
for file in glob(output_path(path)): for file in os.listdir(path):
sprites.append(Sprite(file)) sprites.append((file, Sprite(os.path.join(path, file))))
sprites.sort(key=lambda s: str.lower(s.name or "").strip()) sprites.sort(key=lambda s: str.lower(s[1].name or "").strip())
frame.buttons = [] frame.buttons = []
for sprite in sprites: for file, sprite in sprites:
image = get_image_for_sprite(sprite) image = get_image_for_sprite(sprite)
if image is None: if image is None:
continue continue
self.all_sprites.append(sprite) self.all_sprites.append(sprite)
button = Button(frame, image=image, command=lambda spr=sprite: self.select_sprite(spr)) button = Button(frame, image=image, command=lambda spr=sprite: self.select_sprite(spr))
ToolTips.register(button, sprite.name + ("\nBy: %s" % sprite.author_name if sprite.author_name else "")) ToolTips.register(button, sprite.name +
("\nBy: %s" % sprite.author_name if sprite.author_name else "") +
f"\nFrom: {file}")
button.image = image button.image = image
frame.buttons.append(button) frame.buttons.append(button)

View File

@ -1,4 +1,5 @@
import collections import collections
import typing
from BaseClasses import Region, Location, Entrance, RegionType, Shop, TakeAny, UpgradeShop, ShopType from BaseClasses import Region, Location, Entrance, RegionType, Shop, TakeAny, UpgradeShop, ShopType
@ -450,7 +451,17 @@ key_drop_data = {
'Ganons Tower - Mini Helmasaur Key Drop': [0x14001e, 0x14001f] 'Ganons Tower - Mini Helmasaur Key Drop': [0x14001e, 0x14001f]
} }
location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), # tuple contents:
# address to write to for item
# address to write to for player getting the item
# can this location drop a crystal
# hint tile/npc text for this location
location_table: typing.Dict[str,
typing.Tuple[typing.Optional[typing.Union[int, typing.List[int]]],
typing.Optional[int],
bool,
typing.Optional[str]]] = \
{'Mushroom': (0x180013, 0x186338, False, 'in the woods'),
'Bottle Merchant': (0x2eb18, 0x186339, False, 'with a merchant'), 'Bottle Merchant': (0x2eb18, 0x186339, False, 'with a merchant'),
'Flute Spot': (0x18014a, 0x18633d, False, 'underground'), 'Flute Spot': (0x18014a, 0x18633d, False, 'underground'),
'Sunken Treasure': (0x180145, 0x186354, False, 'underwater'), 'Sunken Treasure': (0x180145, 0x186354, False, 'underwater'),

10
Text.py
View File

@ -258,6 +258,16 @@ TavernMan_texts = [
] ]
junk_texts = [ junk_texts = [
"{C:GREEN}\nAgitha's good\nin Hyrule\nWarriors. >",
"{C:GREEN}\nConsult Fi if\nthe batteries\nare low. >",
"{C:GREEN}\nThere is no\n3rd quest in\nthis game. >",
"{C:GREEN}\nI am Error.\n \n >",
"{C:GREEN}\nThe Wind Fish\nknows all in\nhere. Hoot! >",
"{C:GREEN}\nThere are no\nwallets in\nthis game. >",
"{C:GREEN}\nCrossbow\nTraining is\na fun game. >",
"{C:GREEN}\nThe shrine\ncontains\nMagnesis. >",
"{C:GREEN}\nThe loftwing\nlet the duck\ntake over. >",
"{C:GREEN}\nStasis would\nbe very\noverpowered.>",
"{C:GREEN}\nIts a secret\nto everybody.\n >", "{C:GREEN}\nIts a secret\nto everybody.\n >",
"{C:GREEN}\nDodongo\ndislikes\nsmoke. >", "{C:GREEN}\nDodongo\ndislikes\nsmoke. >",
"{C:GREEN}\n> Digdogger\nhates certain\nkind of sound.", "{C:GREEN}\n> Digdogger\nhates certain\nkind of sound.",

View File

@ -6,7 +6,7 @@ def tuplize_version(version: str) -> typing.Tuple[int, ...]:
return tuple(int(piece, 10) for piece in version.split(".")) return tuple(int(piece, 10) for piece in version.split("."))
__version__ = "3.4.1" __version__ = "3.4.2"
_version_tuple = tuplize_version(__version__) _version_tuple = tuplize_version(__version__)
import os import os

View File

@ -7,7 +7,8 @@ from ..models import Room
api_endpoints = Blueprint('api', __name__, url_prefix="/api") api_endpoints = Blueprint('api', __name__, url_prefix="/api")
from . import generate from . import generate, user # trigger registration
# unsorted/misc endpoints # unsorted/misc endpoints

33
WebHostLib/api/user.py Normal file
View File

@ -0,0 +1,33 @@
from flask import session, jsonify
from WebHostLib.models import *
from . import api_endpoints
@api_endpoints.route('/get_rooms')
def get_rooms():
response = []
for room in select(room for room in Room if room.owner == session["_id"]):
response.append({
"room_id": room.id,
"seed_id": room.seed.id,
"creation_time": room.creation_time,
"last_activity": room.last_activity,
"last_port": room.last_port,
"timeout": room.timeout,
"tracker": room.tracker,
"players": room.seed.multidata["names"] if room.seed.multidata else [["Singleplayer"]],
})
return jsonify(response)
@api_endpoints.route('/get_seeds')
def get_seeds():
response = []
for seed in select(seed for seed in Seed if seed.owner == session["_id"]):
response.append({
"seed_id": seed.id,
"creation_time": seed.creation_time,
"players": seed.multidata["names"] if seed.multidata else [["Singleplayer"]],
})
return jsonify(response)

View File

@ -45,8 +45,14 @@ def generate(race=False):
return redirect(url_for("wait_seed", seed=gen.id)) return redirect(url_for("wait_seed", seed=gen.id))
else: else:
try:
seed_id = gen_game({name: vars(options) for name, options in gen_options.items()}, seed_id = gen_game({name: vars(options) for name, options in gen_options.items()},
race=race, owner=session["_id"].int) race=race, owner=session["_id"].int)
except BaseException as e:
from .autolauncher import handle_generation_failure
handle_generation_failure(e)
return render_template("seedError.html", seed_error=(e.__class__.__name__ + ": "+ str(e)))
return redirect(url_for("viewSeed", seed=seed_id)) return redirect(url_for("viewSeed", seed=seed_id))
return render_template("generate.html", race=race) return render_template("generate.html", race=race)
@ -114,8 +120,7 @@ def wait_seed(seed: UUID):
if not generation: if not generation:
return "Generation not found." return "Generation not found."
elif generation.state == STATE_ERROR: elif generation.state == STATE_ERROR:
import html return render_template("seedError.html", seed_error=generation.meta.decode())
return f"Generation failed, please retry. <br> {html.escape(generation.meta.decode())}"
return render_template("waitSeed.html", seed_id=seed_id) return render_template("waitSeed.html", seed_id=seed_id)

View File

@ -0,0 +1,9 @@
window.addEventListener('load', () => {
let tables = $(".autodatatable").DataTable({
"paging": false,
"ordering": true,
"info": false,
"dom": "t",
});
console.log(tables);
});

View File

@ -5,6 +5,10 @@ window.addEventListener('load', () => {
const cookieNotice = document.createElement('div'); const cookieNotice = document.createElement('div');
cookieNotice.innerText = "This website uses cookies to store information about the games you play."; cookieNotice.innerText = "This website uses cookies to store information about the games you play.";
cookieNotice.setAttribute('id', 'cookie-notice'); cookieNotice.setAttribute('id', 'cookie-notice');
const closeButton = document.createElement('span');
closeButton.setAttribute('id', 'close-button');
closeButton.innerText = 'X';
cookieNotice.appendChild(closeButton);
document.body.appendChild(cookieNotice); document.body.appendChild(cookieNotice);
cookieNotice.addEventListener('click', () => { cookieNotice.addEventListener('click', () => {
localStorage.setItem('cookieNotice', "1"); localStorage.setItem('cookieNotice', "1");

View File

@ -7,12 +7,5 @@ window.addEventListener('load', () => {
document.getElementById('host-game-form').submit(); document.getElementById('host-game-form').submit();
}); });
$("#host-game-table").DataTable({
"paging": false,
"ordering": true,
"order": [[ 3, "desc" ]],
"info": false,
"dom": "t",
});
adjustFooterHeight(); adjustFooterHeight();
}); });

View File

@ -19,12 +19,12 @@ window.addEventListener('load', () => {
// Sprite options // Sprite options
const spriteData = JSON.parse(results[1]); const spriteData = JSON.parse(results[1]);
const spriteSelect = document.getElementById('sprite'); const spriteSelect = document.getElementById('sprite');
Object.keys(spriteData).forEach((sprite) => { spriteData.sprites.forEach((sprite) => {
if (sprite.trim().length === 0) { return; } if (sprite.name.trim().length === 0) { return; }
const option = document.createElement('option'); const option = document.createElement('option');
option.setAttribute('value', spriteData[sprite]); option.setAttribute('value', sprite.name.trim());
if (playerSettings.rom.sprite === sprite) { option.selected = true; } if (playerSettings.rom.sprite === sprite.name.trim()) { option.selected = true; }
option.innerText = sprite; option.innerText = sprite.name;
spriteSelect.appendChild(option); spriteSelect.appendChild(option);
}); });
}).catch((error) => { }).catch((error) => {

View File

@ -9,7 +9,7 @@
## Logiciels requis ## Logiciels requis
- [Utilitaires du MultiWorld](https://github.com/Berserker66/MultiWorld-Utilities/releases) - [Utilitaires du MultiWorld](https://github.com/Berserker66/MultiWorld-Utilities/releases)
- [QUsb2Snes](https://github.com/Skarsnik/QUsb2snes/releases) (Inclus dans les utilitaires précédents) - [QUsb2Snes](https://github.com/Skarsnik/QUsb2snes/releases) (Inclus dans les utilitaires précédents)
- Une solution logicielle ou matérielle capable de charger et de jouer des fichiers ROM de SNES - Une solution logicielle ou matérielle capable de charger et de lancer des fichiers ROM de SNES
- Un émulateur capable d'éxécuter des scripts Lua - Un émulateur capable d'éxécuter des scripts Lua
([snes9x Multitroid](https://drive.google.com/drive/folders/1_ej-pwWtCAHYXIrvs5Hro16A1s9Hi3Jz), ([snes9x Multitroid](https://drive.google.com/drive/folders/1_ej-pwWtCAHYXIrvs5Hro16A1s9Hi3Jz),
[BizHawk](http://tasvideos.org/BizHawk.html)) [BizHawk](http://tasvideos.org/BizHawk.html))
@ -21,17 +21,17 @@
### Installation sur Windows ### Installation sur Windows
1. Téléchargez et installez les utilitaires du MultiWorld à l'aide du lien au-dessus, faites attention à bien installer la version la plus récente. 1. Téléchargez et installez les utilitaires du MultiWorld à l'aide du lien au-dessus, faites attention à bien installer la version la plus récente.
**Le fichier se situe dans la section "assets" en bas des informations de version**. Si vous voulez jouer des parties classiques de multiworld, **Le fichier se situe dans la section "assets" en bas des informations de version**. Si vous voulez jouer des parties classiques de multiworld,
vous voudrez télécharger `Setup.BerserkerMultiWorld.exe` téléchargez `Setup.BerserkerMultiWorld.exe`
- Si vous voulez jouer à la version alternative avec le mélangeur de portes dans les donjons, vous voudrez télécharger le fichier - Si vous voulez jouer à la version alternative avec le mélangeur de portes dans les donjons, vous téléchargez le fichier
`Setup.BerserkerMultiWorld.Doors.exe`. `Setup.BerserkerMultiWorld.Doors.exe`.
- Durant le processus d'installation, il vous sera demandé de localiser votre ROM v1.0 japonaise. Si vous avez déjà installé le logiciel - Durant le processus d'installation, il vous sera demandé de localiser votre ROM v1.0 japonaise. Si vous avez déjà installé le logiciel
auparavant et qu'il s'agit simplement d'une mise à jour, la localisation de la ROM originale ne sera pas requise. auparavant et qu'il s'agit simplement d'une mise à jour, la localisation de la ROM originale ne sera pas requise.
- Il vous sera peut-être également demandé d'installer Microsoft Visual C++. Si vous le possédez déjà (possiblement parce qu'un - Il vous sera peut-être également demandé d'installer Microsoft Visual C++. Si vous le possédez déjà (possiblement parce qu'un
jeu Steam l'a déjà installé), l'installateur ne reproposera pas de l'installer. jeu Steam l'a déjà installé), l'installateur ne reproposera pas de l'installer.
2. Si vous utilisez un émulateur, vous devriez assigner votre émulateur capable d'éxécuter des scripts Lua comme programme 2. Si vous utilisez un émulateur, il est recommandé d'assigner votre émulateur capable d'éxécuter des scripts Lua comme programme
par défaut pour ouvrir vos ROMs. par défaut pour ouvrir vos ROMs.
1. Extrayez votre dossier d'émulateur sur votre Bureau, ou quelque part dont vous vous souviendrez. 1. Extrayez votre dossier d'émulateur sur votre Bureau, ou à un endroit dont vous vous souviendrez.
2. Faites un clic droit sur un fichier ROM et sélectionnez **Ouvrir avec...** 2. Faites un clic droit sur un fichier ROM et sélectionnez **Ouvrir avec...**
3. Cochez la case à côté de **Toujours utiliser cette application pour ouvrir les fichiers .sfc** 3. Cochez la case à côté de **Toujours utiliser cette application pour ouvrir les fichiers .sfc**
4. Descendez jusqu'en bas de la liste et sélectionnez **Rechercher une autre application sur ce PC** 4. Descendez jusqu'en bas de la liste et sélectionnez **Rechercher une autre application sur ce PC**
@ -49,14 +49,12 @@ sur comment il devrait générer votre seed. Chaque joueur d'un multiwolrd devra
joueur d'apprécier une expérience customisée selon ses goûts, et les différents joueurs d'un même multiworld peuvent avoir différentes options. joueur d'apprécier une expérience customisée selon ses goûts, et les différents joueurs d'un même multiworld peuvent avoir différentes options.
### Où est-ce que j'obtiens un fichier YAML ? ### Où est-ce que j'obtiens un fichier YAML ?
Un fichier YAML de base est disponible dans le dossier où les utilitaires du MultiWorld sont installés. Il est situé dans le dossier La page [Génération de partie](/player-settings) vous permet de configurer vos paramètres personnels et de les exporter vers un fichier YAML.
`players` et se nomme `easy.yaml`
La page des [paramètres du joueur](/player-settings) vous permet de configurer vos paramètres personnels et de télécharger un fichier `yaml`.
Vous pouvez configurez jusqu'à trois pré-paramétrages sur cette page.
### Votre fichier YAML est pondéré ### Configuration avancée du fichier YAML
La page de paramétrage a de nombreuses options qui sont essentiellement représentées avec des curseurs glissants. Cela vous permet de choisir quelles Une version plus avancée du fichier YAML peut être créée en utilisant la page des [paramètres de pondération](/weighted-settings), qui vous permet
sont les chances qu'une certaine option apparaisse par rapport aux autres disponibles. de configurer jusqu'à trois préréglages. Cette page a de nombreuses options qui sont essentiellement représentées avec des curseurs glissants.
Cela vous permet de choisir quelles sont les chances qu'une certaine option apparaisse par rapport aux autres disponibles dans une même catégorie.
Par exemple, imaginez que le générateur crée un seau étiqueté "Mélange des cartes", et qu'il place un morceau de papier Par exemple, imaginez que le générateur crée un seau étiqueté "Mélange des cartes", et qu'il place un morceau de papier
pour chaque sous-option. Imaginez également que la valeur pour "On" est 20 et la valeur pour "Off" est 40. pour chaque sous-option. Imaginez également que la valeur pour "On" est 20 et la valeur pour "Off" est 40.
@ -65,14 +63,15 @@ Dans cet exemple, il y a soixante morceaux de papier dans le seau : vingt pour "
décide s'il doit oui ou non activer le mélange des cartes pour votre partie, , il tire aléatoirement un papier dans le seau. décide s'il doit oui ou non activer le mélange des cartes pour votre partie, , il tire aléatoirement un papier dans le seau.
Dans cet exemple, il y a de plus grandes chances d'avoir le mélange de cartes désactivé. Dans cet exemple, il y a de plus grandes chances d'avoir le mélange de cartes désactivé.
S'il y a une option dont vous ne voulez jamais, mettez simplement sa valeur à zéro. S'il y a une option dont vous ne voulez jamais, mettez simplement sa valeur à zéro. N'oubliez pas qu'il faut que pour chaque paramètre il faut
au moins une option qui soit paramétrée sur un nombre strictement positif.
### Vérifier son fichier YAML ### Vérifier son fichier YAML
Si vous voulez valider votre fichier YAML pour être sûr qu'il fonctionne, vous pouvez le vérifier sur la page du Si vous voulez valider votre fichier YAML pour être sûr qu'il fonctionne, vous pouvez le vérifier sur la page du
[Validateur de YAML](/mysterycheck). [Validateur de YAML](/mysterycheck).
## Générer une partie pour un joueur ## Générer une partie pour un joueur
1. Aller sur la [page du générateur](/generate) et téléversez votre fichier YAML. 1. Aller sur la page [Génération de partie](/player-settings), configurez vos options, et cliquez sur le bouton "Generate Game".
2. Il vous sera alors présenté une page d'informations sur la seed, où vous pourrez télécharger votre patch. 2. Il vous sera alors présenté une page d'informations sur la seed, où vous pourrez télécharger votre patch.
3. Double-cliquez sur le patch et l'émulateur devrait se lancer automatiquement avec la seed. Etant donné que le client 3. Double-cliquez sur le patch et l'émulateur devrait se lancer automatiquement avec la seed. Etant donné que le client
n'est pas requis pour les parties à un joueur, vous pouvez le fermer ainsi que l'interface Web (WebUI). n'est pas requis pour les parties à un joueur, vous pouvez le fermer ainsi que l'interface Web (WebUI).
@ -120,10 +119,6 @@ Les utilisateurs de SD2SNES et de FXPak Pro peuvent télécharger le micro-logic
[ici](https://github.com/RedGuyyyy/sd2snes/releases). Pour les autres solutions, de l'aide peut être trouvée [ici](https://github.com/RedGuyyyy/sd2snes/releases). Pour les autres solutions, de l'aide peut être trouvée
[sur cette page](http://usb2snes.com/#supported-platforms). [sur cette page](http://usb2snes.com/#supported-platforms).
**Pour vous connecter avec une solution matérielle vous devez utiliser une ancienne version de QUsb2Snes
([v0.7.16](https://github.com/Skarsnik/QUsb2snes/releases/tag/v0.7.16)).**
Les versions postérieures brisent la compatibilité avec le multiworld.
1. Fermez votre émulateur, qui s'est potentiellement lancé automatiquement. 1. Fermez votre émulateur, qui s'est potentiellement lancé automatiquement.
2. Fermez QUsb2Snes, qui s'est lancé automatiquement avec le client. 2. Fermez QUsb2Snes, qui s'est lancé automatiquement avec le client.
3. Lancez la version appropriée de QUsb2Snes (v0.7.16). 3. Lancez la version appropriée de QUsb2Snes (v0.7.16).
@ -149,13 +144,31 @@ La méthode recommandée pour héberger une partie est d'utiliser le service d'h
1. Récupérez les fichiers YAML des joueurs. 1. Récupérez les fichiers YAML des joueurs.
2. Créez une archive zip contenant ces fichiers YAML. 2. Créez une archive zip contenant ces fichiers YAML.
3. Téléversez l'archive zip sur le lien au-dessus. 3. Téléversez l'archive zip sur le lien ci-dessus.
4. Attendez un moment que les seed soient générées. 4. Attendez un moment que les seed soient générées.
5. Lorsque les seeds sont générées, vous serez redirigé vers une page d'informations. 5. Lorsque les seeds sont générées, vous serez redirigé vers une page d'informations "Seed Info".
6. Cliquez sur "Create New Room". Cela vous amènera à la page du serveur. Fournissez le lien de cette page aux autres joueurs 6. Cliquez sur "Create New Room". Cela vous amènera à la page du serveur. Fournissez le lien de cette page aux autres joueurs
afin qu'ils puissent récupérer leurs patchs. afin qu'ils puissent récupérer leurs patchs.
**Note:** Les patchs fournis sur cette page permettront aux joueurs de se connecteur automatiquement au serveur, **Note:** Les patchs fournis sur cette page permettront aux joueurs de se connecteur automatiquement au serveur,
tandis que ceux de la page "Seed Info" non. tandis que ceux de la page "Seed Info" non.
7. Remarquez qu'un lien vers le traqueur du MultiWorld est en haut de la page de la salle. Vous devriez également fournir ce lien aux joueurs 7. Remarquez qu'un lien vers le traqueur du MultiWorld est en haut de la page de la salle. Vous devriez également fournir ce lien aux joueurs
pour qu'ils puissent la progression de la partie. N'importe quel personne voulant observer devrait avoir accès à ce lien. pour qu'ils puissent suivre la progression de la partie. N'importe quel personne voulant observer devrait avoir accès à ce lien.
8. Une fois que tous les joueurs ont rejoint, vous pouvez commencer à jouer. 8. Une fois que tous les joueurs ont rejoint, vous pouvez commencer à jouer.
## Auto-tracking
Si vous voulez utiliser l'auto-tracking, plusieurs logiciels offrent cette possibilité.
Le logiciel recommandé pour l'auto-tracking actuellement est
[OpenTracker](https://github.com/trippsc2/OpenTracker/releases).
### Installation
1. Téléchargez le fichier d'installation approprié pour votre ordinateur (Les utilisateurs Windows voudront le fichier `.msi`).
2. Durant le processus d'installation, il vous sera peut-être demandé d'installer les outils "Microsoft Visual Studio Build Tools". Un
lien est fourni durant l'installation d'OpenTracker, et celle des outils doit se faire manuellement.
### Activer l'auto-tracking
1. Une fois OpenTracker démarré, cliquez sur le menu "Tracking" en haut de la fenêtre, puis choisissez **AutoTracker...**
2. Appuyez sur le bouton **Get Devices**
3. Sélectionnez votre appareil SNES dans la liste déroulante.
4. Si vous voulez tracquer les petites clés ainsi que les objets des donjons, cochez la case **Race Illegal Tracking**
5. Cliquez sur le bouton **Start Autotracking**
6. Fermez la fenêtre "AutoTracker" maintenant, elle n'est plus nécessaire

View File

@ -0,0 +1,17 @@
window.addEventListener('load', () => {
console.log("loaded");
$("#rooms-table").DataTable({
"paging": false,
"ordering": true,
"order": [[ 3, "desc" ]],
"info": false,
"dom": "t",
});
$("#seeds-table").DataTable({
"paging": false,
"ordering": true,
"order": [[ 2, "desc" ]],
"info": false,
"dom": "t",
});
});

View File

@ -13,11 +13,8 @@ window.addEventListener('load', () => {
localStorage.setItem(`weightedSettings${i}`, JSON.stringify(updatedObj)); localStorage.setItem(`weightedSettings${i}`, JSON.stringify(updatedObj));
} }
// Parse spriteData into useful sets
spriteData = JSON.parse(results[2]);
// Build the entire UI // Build the entire UI
buildUI(JSON.parse(results[1])); buildUI(JSON.parse(results[1]), JSON.parse(results[2]));
// Populate the UI and add event listeners // Populate the UI and add event listeners
populateSettings(); populateSettings();
@ -29,6 +26,7 @@ window.addEventListener('load', () => {
document.getElementById('reset-to-default').addEventListener('click', resetToDefaults); document.getElementById('reset-to-default').addEventListener('click', resetToDefaults);
adjustHeaderWidth(); adjustHeaderWidth();
}).catch((error) => { }).catch((error) => {
console.error(error);
gameSettings.innerHTML = ` gameSettings.innerHTML = `
<h2>Something went wrong while loading your game settings page.</h2> <h2>Something went wrong while loading your game settings page.</h2>
<h2>${error}</h2> <h2>${error}</h2>
@ -170,7 +168,7 @@ const download = (filename, text) => {
document.body.removeChild(downloadLink); document.body.removeChild(downloadLink);
}; };
const buildUI = (settings) => { const buildUI = (settings, spriteData) => {
const settingsWrapper = document.getElementById('settings-wrapper'); const settingsWrapper = document.getElementById('settings-wrapper');
const settingTypes = { const settingTypes = {
gameOptions: 'Game Options', gameOptions: 'Game Options',
@ -244,7 +242,7 @@ const buildUI = (settings) => {
settingsWrapper.appendChild(spriteOptionsWrapper); settingsWrapper.appendChild(spriteOptionsWrapper);
// Append sprite picker // Append sprite picker
settingsWrapper.appendChild(buildSpritePicker()); settingsWrapper.appendChild(buildSpritePicker(spriteData));
}; };
const buildRangeSettings = (parentElement, settings) => { const buildRangeSettings = (parentElement, settings) => {
@ -404,7 +402,7 @@ const removeSpriteOption = (event) => {
tr.parentNode.removeChild(tr); tr.parentNode.removeChild(tr);
}; };
const buildSpritePicker = () => { const buildSpritePicker = (spriteData) => {
const spritePicker = document.createElement('div'); const spritePicker = document.createElement('div');
spritePicker.setAttribute('id', 'sprite-picker'); spritePicker.setAttribute('id', 'sprite-picker');
@ -415,18 +413,18 @@ const buildSpritePicker = () => {
const sprites = document.createElement('div'); const sprites = document.createElement('div');
sprites.setAttribute('id', 'sprite-picker-sprites'); sprites.setAttribute('id', 'sprite-picker-sprites');
Object.keys(spriteData).forEach((spriteName) => { spriteData.sprites.forEach((sprite) => {
const spriteImg = document.createElement('img'); const spriteImg = document.createElement('img');
spriteImg.setAttribute('src', `static/static/sprites/${spriteName}.gif`); spriteImg.setAttribute('src', `static/static/sprites/${sprite.name}.gif`);
spriteImg.setAttribute('data-sprite', spriteName); spriteImg.setAttribute('data-sprite', sprite.name);
spriteImg.setAttribute('alt', spriteName); spriteImg.setAttribute('alt', sprite.name);
// Wrap the image in a span to allow for tooltip presence // Wrap the image in a span to allow for tooltip presence
const imgWrapper = document.createElement('span'); const imgWrapper = document.createElement('span');
imgWrapper.className = 'sprite-img-wrapper'; imgWrapper.className = 'sprite-img-wrapper';
imgWrapper.setAttribute('data-tooltip', spriteName); imgWrapper.setAttribute('data-tooltip', `${sprite.name}${sprite.author ? `, by ${sprite.author}` : ''}`);
imgWrapper.appendChild(spriteImg); imgWrapper.appendChild(spriteImg);
imgWrapper.setAttribute('data-sprite', spriteName); imgWrapper.setAttribute('data-sprite', sprite.name);
sprites.appendChild(imgWrapper); sprites.appendChild(imgWrapper);
imgWrapper.addEventListener('click', addSpriteOption); imgWrapper.addEventListener('click', addSpriteOption);
}); });

View File

@ -37,9 +37,17 @@
"name": "Master Sword Pedestal", "name": "Master Sword Pedestal",
"value": "pedestal" "value": "pedestal"
}, },
{
"name": "Master Sword Pedestal + Ganon",
"value": "ganon_pedestal"
},
{ {
"name": "Triforce Hunt", "name": "Triforce Hunt",
"value": "triforce_hunt" "value": "triforce_hunt"
},
{
"name": "Triforce Hunt + Ganon",
"value": "ganon_triforce_hunt"
} }
] ]
}, },
@ -209,7 +217,7 @@
}, },
"hints": { "hints": {
"type": "select", "type": "select",
"friendlyName": "Tile Hints", "friendlyName": "Hints",
"description": "Choose to enable or disable tile hints", "description": "Choose to enable or disable tile hints",
"defaultValue": "on", "defaultValue": "on",
"options": [ "options": [
@ -313,6 +321,10 @@
"name": "Big Keys Only", "name": "Big Keys Only",
"value": "b" "value": "b"
}, },
{
"name": "Small and Big Keys",
"value": "sb"
},
{ {
"name": "Full Keysanity", "name": "Full Keysanity",
"value": "mscb" "value": "mscb"
@ -334,15 +346,15 @@
"value": "none" "value": "none"
}, },
{ {
"name": "Dungeon Entrances", "name": "Only Dungeons, Simple",
"value": "dungeonssimple" "value": "dungeonssimple"
}, },
{ {
"name": "Dungeon Interiors", "name": "Only Dungeons, Full",
"value": "dungeonsfull" "value": "dungeonsfull"
}, },
{ {
"name": "Simple Entrances", "name": "Simple",
"value": "simple" "value": "simple"
}, },
{ {
@ -350,15 +362,15 @@
"value": "restricted" "value": "restricted"
}, },
{ {
"name": "Full Shuffle", "name": "Full",
"value": "full" "value": "full"
}, },
{ {
"name": "Crossed Shuffle", "name": "Crossed",
"value": "crossed" "value": "crossed"
}, },
{ {
"name": "Insanity Shuffle", "name": "Insanity",
"value": "insanity" "value": "insanity"
} }
] ]
@ -466,16 +478,24 @@
"value": "none" "value": "none"
}, },
{ {
"name": "Shuffle Inventory", "name": "Inventory",
"value": "i" "value": "i"
}, },
{ {
"name": "Shuffle Prices", "name": "Prices",
"value": "p" "value": "p"
}, },
{ {
"name": "Shuffle Both", "name": "Capacity Upgrades",
"value": "u"
},
{
"name": "Inventory and Prices",
"value": "ip" "value": "ip"
},
{
"name": "Inventory, Prices, and Upgrades",
"value": "ipu"
} }
] ]
} }
@ -612,7 +632,7 @@
"value": "default" "value": "default"
}, },
{ {
"name": "Shuffled", "name": "Randomized",
"value": "random" "value": "random"
} }
] ]
@ -628,7 +648,7 @@
"value": "default" "value": "default"
}, },
{ {
"name": "Shuffled", "name": "Randomized",
"value": "random" "value": "random"
} }
] ]
@ -644,7 +664,7 @@
"value": "default" "value": "default"
}, },
{ {
"name": "Shuffled", "name": "Randomized",
"value": "random" "value": "random"
} }
] ]
@ -660,7 +680,7 @@
"value": "default" "value": "default"
}, },
{ {
"name": "Shuffled", "name": "Randomized",
"value": "random" "value": "random"
} }
] ]

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 B

View File

Before

Width:  |  Height:  |  Size: 541 B

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 B

View File

@ -9,3 +9,8 @@
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
} }
#cookie-notice #close-button{
float: right;
padding-right: 10px;
}

View File

@ -28,25 +28,3 @@
#host-game button{ #host-game button{
margin-top: 5px; margin-top: 5px;
} }
#host-game-table{
margin-right: auto;
text-align: left;
}
#host-game-table th{
padding: 0 20px 0 0;
}
#host-game-table td{
padding: 6px 20px 0 0;
}
#host-game-table td.center{
text-align: center;
}
#host-game-table.dataTable{
width: unset;
}

View File

@ -75,6 +75,7 @@ html{
padding: 3px; padding: 3px;
border-radius: 3px; border-radius: 3px;
min-width: 150px; min-width: 150px;
background-color: #ffffff;
} }
#player-settings #game-options, #player-settings #rom-options{ #player-settings #game-options, #player-settings #rom-options{
@ -97,7 +98,7 @@ html{
cursor: default; cursor: default;
} }
@media all and (max-width: 1000px){ @media all and (max-width: 1000px), all and (orientation: portrait){
#player-settings #game-options, #player-settings #rom-options{ #player-settings #game-options, #player-settings #rom-options{
justify-content: flex-start; justify-content: flex-start;
flex-wrap: wrap; flex-wrap: wrap;

View File

@ -5,12 +5,14 @@ html{
} }
#tutorial-wrapper{ #tutorial-wrapper{
width: 70rem; display: flex;
flex-direction: column;
max-width: 70rem;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
background-color: rgba(0, 0, 0, 0.15); background-color: rgba(0, 0, 0, 0.15);
border-radius: 8px; border-radius: 8px;
padding: 1rem; padding: 1rem 1rem 3rem;
color: #eeffeb; color: #eeffeb;
} }

View File

@ -31,3 +31,24 @@
#user-content .center{ #user-content .center{
text-align: center; text-align: center;
} }
#user-content-table{
margin-right: auto;
text-align: left;
}
#user-content .table td.center{
text-align: center;
}
#user-content table.dataTable{
width: unset;
}
table.dataTable thead th{
padding: 0 20px 0 0;
}
table.dataTable tbody td{
padding: 6px 20px 0 0;
}

View File

@ -148,5 +148,6 @@ html{
padding: 3px; padding: 3px;
border-radius: 3px; border-radius: 3px;
min-width: 150px; min-width: 150px;
background-color: #ffffff;
} }

View File

@ -0,0 +1,5 @@
{% extends "tablepage.html" %}
{% block head %}
{{ super() }}
<script type="application/ecmascript" src="{{ static_autoversion("assets/autodatatable.js") }}"></script>
{% endblock %}

View File

@ -1,8 +1,8 @@
{% extends 'pageWrapper.html' %} {% extends 'autotablepage.html' %}
{% block head %} {% block head %}
{{ super() }} {{ super() }}
<title>Upload Mystery YAML</title> <title>Mystery YAML Test Roll Results</title>
<link rel="stylesheet" type="text/css" href="{{ static_autoversion("styles/checkResult.css") }}" /> <link rel="stylesheet" type="text/css" href="{{ static_autoversion("styles/checkResult.css") }}" />
{% endblock %} {% endblock %}
@ -12,7 +12,7 @@
<div id="check-result" class="grass-island"> <div id="check-result" class="grass-island">
<h1>Verification Results</h1> <h1>Verification Results</h1>
<p>The results of your requested file check are below.</p> <p>The results of your requested file check are below.</p>
<table> <table class="table autodatatable">
<thead> <thead>
<tr> <tr>
<th>File</th> <th>File</th>

View File

@ -1,4 +1,4 @@
{% extends 'tablepage.html' %} {% extends 'pageWrapper.html' %}
{% block head %} {% block head %}
{{ super() }} {{ super() }}

View File

@ -11,10 +11,10 @@
{% block body %} {% block body %}
{% include 'header/grassHeader.html' %} {% include 'header/grassHeader.html' %}
<div id="player-settings"> <div id="player-settings">
<h1>Generate Game</h1> <h1>Start Game</h1>
<p>Choose the options you would like to play with! You may generate a single-player game from this page, <p>Choose the options you would like to play with! You may generate a single-player game from this page,
or download a settings file you can use to participate in a MultiWorld. If you would like to make or download a settings file you can use to participate in a MultiWorld. If you would like to make
your settings extra random, check out the <a href="/weighted-settings">weighted settings</a> your settings extra random, check out the advanced <a href="/weighted-settings">weighted settings</a>
page. There, you will find examples of all available sprites as well.</p> page. There, you will find examples of all available sprites as well.</p>
<p>A list of all games you have generated can be found <a href="/user-content">here</a>.</p> <p>A list of all games you have generated can be found <a href="/user-content">here</a>.</p>

View File

@ -0,0 +1,19 @@
{% extends 'pageWrapper.html' %}
{% import "macros.html" as macros %}
{% block head %}
<title>Generation failed, please retry.</title>
<link rel="stylesheet" type="text/css" href="{{ static_autoversion("styles/waitSeed.css") }}"/>
{% endblock %}
{% block body %}
{% include 'header/oceanHeader.html' %}
<div id="wait-seed-wrapper" class="grass-island">
<div id="wait-seed">
<h1>Generation failed</h1>
<h2>please retry</h2>
{{ seed_error }}
</div>
</div>
{% include 'islandFooter.html' %}
{% endblock %}

View File

@ -1,9 +1,10 @@
{% extends 'pageWrapper.html' %} {% extends 'tablepage.html' %}
{% block head %} {% block head %}
{{ super() }} {{ super() }}
<title>Generate Game</title> <title>Generate Game</title>
<link rel="stylesheet" type="text/css" href="{{ static_autoversion("styles/userContent.css") }}" /> <link rel="stylesheet" type="text/css" href="{{ static_autoversion("styles/userContent.css") }}" />
<script type="application/ecmascript" src="{{ static_autoversion("assets/userContent.js") }}"></script>
{% endblock %} {% endblock %}
{% block body %} {% block body %}
@ -15,7 +16,7 @@
<h2>Your Rooms</h2> <h2>Your Rooms</h2>
{% if rooms %} {% if rooms %}
<table> <table id="rooms-table" class="table">
<thead> <thead>
<tr> <tr>
<th>Seed</th> <th>Seed</th>
@ -46,7 +47,7 @@
<h2>Your Seeds</h2> <h2>Your Seeds</h2>
{% if seeds %} {% if seeds %}
<table> <table id="seeds-table" class="table">
<thead> <thead>
<tr> <tr>
<th>Seed</th> <th>Seed</th>

View File

@ -5694,9 +5694,9 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
}, },
"inquirer": { "inquirer": {
"version": "7.1.0", "version": "7.1.0",

View File

@ -15,7 +15,7 @@ while not done.isSet():
print("Done updating sprites") print("Done updating sprites")
spriteData = {} spriteData = []
for file in os.listdir(input_dir): for file in os.listdir(input_dir):
sprite = Sprite(os.path.join(input_dir, file)) sprite = Sprite(os.path.join(input_dir, file))
@ -27,9 +27,9 @@ for file in os.listdir(input_dir):
if sprite.valid: if sprite.valid:
with open(os.path.join(output_dir, "sprites", f"{sprite.name}.gif"), 'wb') as image: with open(os.path.join(output_dir, "sprites", f"{sprite.name}.gif"), 'wb') as image:
image.write(get_image_for_sprite(sprite, True)) image.write(get_image_for_sprite(sprite, True))
spriteData[sprite.name] = file spriteData.append({"file": file, "author": sprite.author_name, "name": sprite.name})
else: else:
print(file, "dropped, as it has no valid sprite data.") print(file, "dropped, as it has no valid sprite data.")
spriteData.sort(key=lambda entry: entry["name"])
with open(f'{output_dir}/spriteData.json', 'w') as file: with open(f'{output_dir}/spriteData.json', 'w') as file:
json.dump(spriteData, file) json.dump({"sprites": spriteData}, file, indent=1)

BIN
icon.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 214 KiB

141
inno_setup_38.iss Normal file
View File

@ -0,0 +1,141 @@
#define sourcepath "build\exe.win-amd64-3.8\"
#define MyAppName "BerserkerMultiWorld"
#define MyAppExeName "BerserkerMultiClient.exe"
#define MyAppIcon "icon.ico"
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
AppId={{6D826EE0-49BE-4B36-BACE-09C6971CD85C}}
AppName={#MyAppName}
AppVerName={#MyAppName}
DefaultDirName={commonappdata}\{#MyAppName}
DisableProgramGroupPage=yes
DefaultGroupName=Berserker's Multiworld
OutputDir=setups
OutputBaseFilename=Setup {#MyAppName}
Compression=lzma2
SolidCompression=yes
LZMANumBlockThreads=8
ArchitecturesInstallIn64BitMode=x64
ChangesAssociations=yes
ArchitecturesAllowed=x64
AllowNoIcons=yes
SetupIconFile={#MyAppIcon}
UninstallDisplayIcon={app}\{#MyAppExeName}
SignTool= signtool
LicenseFile= LICENSE
WizardStyle= modern
SetupLogging=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}";
[Dirs]
NAME: "{app}"; Flags: setntfscompression; Permissions: everyone-modify users-modify authusers-modify;
[Files]
Source: "{code:GetROMPath}"; DestDir: "{app}"; DestName: "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc"; Flags: external
Source: "{#sourcepath}*"; Excludes: "*.sfc, *.log, data\sprites\alttpr"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "vc_redist.x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{group}\{#MyAppName} Folder"; Filename: "{app}";
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}";
Name: "{commondesktop}\{#MyAppName} Folder"; Filename: "{app}"; Tasks: desktopicon
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{tmp}\vc_redist.x64.exe"; Parameters: "/passive /norestart"; Check: IsVCRedist64BitNeeded; StatusMsg: "Installing VC++ redistributable..."
Filename: "{app}\BerserkerMultiCreator"; Parameters: "update_sprites"; StatusMsg: "Updating Sprite Library..."
[UninstallDelete]
Type: dirifempty; Name: "{app}"
[Registry]
Root: HKCR; Subkey: ".bmbp"; ValueData: "{#MyAppName}patch"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""
Root: HKCR; Subkey: "{#MyAppName}patch"; ValueData: "Berserker's Multiworld Binary Patch"; Flags: uninsdeletekey; ValueType: string; ValueName: ""
Root: HKCR; Subkey: "{#MyAppName}patch\DefaultIcon"; ValueData: "{app}\{#MyAppExeName},0"; ValueType: string; ValueName: ""
Root: HKCR; Subkey: "{#MyAppName}patch\shell\open\command"; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; ValueType: string; ValueName: ""
Root: HKCR; Subkey: ".multidata"; ValueData: "{#MyAppName}multidata"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""
Root: HKCR; Subkey: "{#MyAppName}multidata"; ValueData: "Berserker's Multiworld Server Data"; Flags: uninsdeletekey; ValueType: string; ValueName: ""
Root: HKCR; Subkey: "{#MyAppName}multidata\DefaultIcon"; ValueData: "{app}\BerserkerMultiServer.exe,0"; ValueType: string; ValueName: ""
Root: HKCR; Subkey: "{#MyAppName}multidata\shell\open\command"; ValueData: """{app}\BerserkerMultiServer.exe"" --multidata ""%1"""; ValueType: string; ValueName: ""
[Code]
// See: https://stackoverflow.com/a/51614652/2287576
function IsVCRedist64BitNeeded(): boolean;
var
strVersion: string;
begin
if (RegQueryStringValue(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64', 'Version', strVersion)) then
begin
// Is the installed version at least the packaged one ?
Log('VC Redist x64 Version : found ' + strVersion);
Result := (CompareStr(strVersion, 'v14.28.29325') < 0);
end
else
begin
// Not even an old version installed
Log('VC Redist x64 is not already installed');
Result := True;
end;
end;
var ROMFilePage: TInputFileWizardPage;
var R : longint;
var rom: string;
procedure InitializeWizard();
begin
rom := FileSearch('Zelda no Densetsu - Kamigami no Triforce (Japan).sfc', WizardDirValue());
if Length(rom) > 0 then
begin
log('existing ROM found');
log(IntToStr(CompareStr(GetMD5OfFile(rom), '03a63945398191337e896e5771f77173')));
if CompareStr(GetMD5OfFile(rom), '03a63945398191337e896e5771f77173') = 0 then
begin
log('existing ROM verified');
exit;
end;
log('existing ROM failed verification');
end;
rom := ''
ROMFilePage :=
CreateInputFilePage(
wpLicense,
'Select ROM File',
'Where is your Zelda no Densetsu - Kamigami no Triforce (Japan).sfc located?',
'Select the file, then click Next.');
ROMFilePage.Add(
'Location of ROM file:',
'SNES ROM files|*.sfc|All files|*.*',
'.sfc');
end;
function GetROMPath(Param: string): string;
begin
if Length(rom) > 0 then
Result := rom
else if Assigned(RomFilePage) then
begin
R := CompareStr(GetMD5OfFile(ROMFilePage.Values[0]), '03a63945398191337e896e5771f77173')
if R <> 0 then
MsgBox('ROM validation failed. Very likely wrong file.', mbInformation, MB_OK);
Result := ROMFilePage.Values[0]
end
else
Result := '';
end;

View File

@ -13,8 +13,8 @@ buildfolder = Path("build", folder)
sbuildfolder = str(buildfolder) sbuildfolder = str(buildfolder)
libfolder = Path(buildfolder, "lib") libfolder = Path(buildfolder, "lib")
library = Path(libfolder, "library.zip") library = Path(libfolder, "library.zip")
print("Outputting to: " + str(buildfolder)) print("Outputting to: " + sbuildfolder)
compress = False
icon = "icon.ico" icon = "icon.ico"
if os.path.exists("X:/pw.txt"): if os.path.exists("X:/pw.txt"):
@ -28,13 +28,16 @@ else:
from hashlib import sha3_512 from hashlib import sha3_512
import base64 import base64
def _threaded_hash(filepath): def _threaded_hash(filepath):
hasher = sha3_512() hasher = sha3_512()
hasher.update(open(filepath, "rb").read()) hasher.update(open(filepath, "rb").read())
return base64.b85encode(hasher.digest()).decode() return base64.b85encode(hasher.digest()).decode()
os.makedirs(buildfolder, exist_ok=True) os.makedirs(buildfolder, exist_ok=True)
def manifest_creation(): def manifest_creation():
hashes = {} hashes = {}
manifestpath = os.path.join(buildfolder, "manifest.json") manifestpath = os.path.join(buildfolder, "manifest.json")
@ -66,7 +69,6 @@ for script, scriptname in scripts.items():
icon=icon, icon=icon,
)) ))
import datetime import datetime
buildtime = datetime.datetime.utcnow() buildtime = datetime.datetime.utcnow()
@ -137,5 +139,4 @@ if signtool:
print(f"Signing {exe.targetName}") print(f"Signing {exe.targetName}")
os.system(signtool + exe.targetName) os.system(signtool + exe.targetName)
manifest_creation() manifest_creation()