unify clients and setup
This commit is contained in:
parent
096e682b18
commit
66514ec607
|
@ -16,7 +16,6 @@
|
||||||
*.apsave
|
*.apsave
|
||||||
|
|
||||||
build
|
build
|
||||||
/build_factorio/
|
|
||||||
bundle/components.wxs
|
bundle/components.wxs
|
||||||
dist
|
dist
|
||||||
README.html
|
README.html
|
||||||
|
|
|
@ -25,9 +25,9 @@ os.makedirs("logs", exist_ok=True)
|
||||||
# Log to file in gui case
|
# Log to file in gui case
|
||||||
if getattr(sys, "frozen", False) and not "--nogui" in sys.argv:
|
if getattr(sys, "frozen", False) and not "--nogui" in sys.argv:
|
||||||
logging.basicConfig(format='[%(name)s]: %(message)s', level=logging.INFO,
|
logging.basicConfig(format='[%(name)s]: %(message)s', level=logging.INFO,
|
||||||
filename=os.path.join("logs", "FactorioClient.txt"), filemode="w")
|
filename=os.path.join("logs", "FactorioClient.txt"), filemode="w", force=True)
|
||||||
else:
|
else:
|
||||||
logging.basicConfig(format='[%(name)s]: %(message)s', level=logging.INFO)
|
logging.basicConfig(format='[%(name)s]: %(message)s', level=logging.INFO, force=True)
|
||||||
logging.getLogger().addHandler(logging.FileHandler(os.path.join("logs", "FactorioClient.txt"), "w"))
|
logging.getLogger().addHandler(logging.FileHandler(os.path.join("logs", "FactorioClient.txt"), "w"))
|
||||||
|
|
||||||
gui_enabled = Utils.is_frozen() or "--nogui" not in sys.argv
|
gui_enabled = Utils.is_frozen() or "--nogui" not in sys.argv
|
||||||
|
@ -299,7 +299,7 @@ async def main(args):
|
||||||
|
|
||||||
if ctx.server and not ctx.server.socket.closed:
|
if ctx.server and not ctx.server.socket.closed:
|
||||||
await ctx.server.socket.close()
|
await ctx.server.socket.close()
|
||||||
if ctx.server_task is not None:
|
if ctx.server_task:
|
||||||
await ctx.server_task
|
await ctx.server_task
|
||||||
|
|
||||||
while ctx.input_requests > 0:
|
while ctx.input_requests > 0:
|
||||||
|
@ -352,7 +352,7 @@ if __name__ == '__main__':
|
||||||
if not os.path.exists(bin_dir):
|
if not os.path.exists(bin_dir):
|
||||||
raise FileNotFoundError(f"Path {bin_dir} does not exist or could not be accessed.")
|
raise FileNotFoundError(f"Path {bin_dir} does not exist or could not be accessed.")
|
||||||
if not os.path.isdir(bin_dir):
|
if not os.path.isdir(bin_dir):
|
||||||
raise FileNotFoundError(f"Path {bin_dir} is not a directory.")
|
raise NotADirectoryError(f"Path {bin_dir} is not a directory.")
|
||||||
if not os.path.exists(executable):
|
if not os.path.exists(executable):
|
||||||
if os.path.exists(executable + ".exe"):
|
if os.path.exists(executable + ".exe"):
|
||||||
executable = executable + ".exe"
|
executable = executable + ".exe"
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import argparse
|
import argparse
|
||||||
import atexit
|
import atexit
|
||||||
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import sys
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -23,11 +25,22 @@ from NetUtils import *
|
||||||
from worlds.alttp import Regions, Shops
|
from worlds.alttp import Regions, Shops
|
||||||
from worlds.alttp import Items
|
from worlds.alttp import Items
|
||||||
import Utils
|
import Utils
|
||||||
from CommonClient import CommonContext, server_loop, logger, console_loop, ClientCommandProcessor
|
from CommonClient import CommonContext, server_loop, console_loop, ClientCommandProcessor
|
||||||
|
|
||||||
|
snes_logger = logging.getLogger("SNES")
|
||||||
|
|
||||||
from MultiServer import mark_raw
|
from MultiServer import mark_raw
|
||||||
|
|
||||||
|
os.makedirs("logs", exist_ok=True)
|
||||||
|
|
||||||
|
# Log to file in gui case
|
||||||
|
if getattr(sys, "frozen", False) and not "--nogui" in sys.argv:
|
||||||
|
logging.basicConfig(format='[%(name)s]: %(message)s', level=logging.INFO,
|
||||||
|
filename=os.path.join("logs", "LttPClient.txt"), filemode="w", force=True)
|
||||||
|
else:
|
||||||
|
logging.basicConfig(format='[%(name)s]: %(message)s', level=logging.INFO, force=True)
|
||||||
|
logging.getLogger().addHandler(logging.FileHandler(os.path.join("logs", "LttPClient.txt"), "w"))
|
||||||
|
|
||||||
|
|
||||||
class LttPCommandProcessor(ClientCommandProcessor):
|
class LttPCommandProcessor(ClientCommandProcessor):
|
||||||
def _cmd_slow_mode(self, toggle: str = ""):
|
def _cmd_slow_mode(self, toggle: str = ""):
|
||||||
|
@ -71,6 +84,7 @@ class Context(CommonContext):
|
||||||
self.snes_recv_queue = asyncio.Queue()
|
self.snes_recv_queue = asyncio.Queue()
|
||||||
self.snes_request_lock = asyncio.Lock()
|
self.snes_request_lock = asyncio.Lock()
|
||||||
self.snes_write_buffer = []
|
self.snes_write_buffer = []
|
||||||
|
self.snes_connector_lock = threading.Lock()
|
||||||
|
|
||||||
self.awaiting_rom = False
|
self.awaiting_rom = False
|
||||||
self.rom = None
|
self.rom = None
|
||||||
|
@ -91,7 +105,7 @@ class Context(CommonContext):
|
||||||
await super(Context, self).server_auth(password_requested)
|
await super(Context, self).server_auth(password_requested)
|
||||||
if self.rom is None:
|
if self.rom is None:
|
||||||
self.awaiting_rom = True
|
self.awaiting_rom = True
|
||||||
logger.info(
|
snes_logger.info(
|
||||||
'No ROM detected, awaiting snes connection to authenticate to the multiworld server (/snes)')
|
'No ROM detected, awaiting snes connection to authenticate to the multiworld server (/snes)')
|
||||||
return
|
return
|
||||||
self.awaiting_rom = False
|
self.awaiting_rom = False
|
||||||
|
@ -420,19 +434,18 @@ def launch_sni(ctx: Context):
|
||||||
sni_path = os.path.join(sni_path, file)
|
sni_path = os.path.join(sni_path, file)
|
||||||
|
|
||||||
if os.path.isfile(sni_path):
|
if os.path.isfile(sni_path):
|
||||||
logger.info(f"Attempting to start {sni_path}")
|
snes_logger.info(f"Attempting to start {sni_path}")
|
||||||
import subprocess
|
import subprocess
|
||||||
subprocess.Popen(sni_path, cwd=os.path.dirname(sni_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
subprocess.Popen(sni_path, cwd=os.path.dirname(sni_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
else:
|
else:
|
||||||
logger.info(
|
snes_logger.info(
|
||||||
f"Attempt to start SNI was aborted as path {sni_path} was not found, "
|
f"Attempt to start SNI was aborted as path {sni_path} was not found, "
|
||||||
f"please start it yourself if it is not running")
|
f"please start it yourself if it is not running")
|
||||||
|
|
||||||
|
|
||||||
async def _snes_connect(ctx: Context, address: str):
|
async def _snes_connect(ctx: Context, address: str):
|
||||||
address = f"ws://{address}" if "://" not in address else address
|
address = f"ws://{address}" if "://" not in address else address
|
||||||
|
snes_logger.info("Connecting to SNI at %s ..." % address)
|
||||||
logger.info("Connecting to SNI at %s ..." % address)
|
|
||||||
seen_problems = set()
|
seen_problems = set()
|
||||||
succesful = False
|
succesful = False
|
||||||
while not succesful:
|
while not succesful:
|
||||||
|
@ -444,7 +457,7 @@ async def _snes_connect(ctx: Context, address: str):
|
||||||
# only tell the user about new problems, otherwise silently lay in wait for a working connection
|
# only tell the user about new problems, otherwise silently lay in wait for a working connection
|
||||||
if problem not in seen_problems:
|
if problem not in seen_problems:
|
||||||
seen_problems.add(problem)
|
seen_problems.add(problem)
|
||||||
logger.error(f"Error connecting to SNI ({problem})")
|
snes_logger.error(f"Error connecting to SNI ({problem})")
|
||||||
|
|
||||||
if len(seen_problems) == 1:
|
if len(seen_problems) == 1:
|
||||||
# this is the first problem. Let's try launching SNI if it isn't already running
|
# this is the first problem. Let's try launching SNI if it isn't already running
|
||||||
|
@ -467,7 +480,7 @@ async def get_snes_devices(ctx: Context):
|
||||||
devices = reply['Results'] if 'Results' in reply and len(reply['Results']) > 0 else None
|
devices = reply['Results'] if 'Results' in reply and len(reply['Results']) > 0 else None
|
||||||
|
|
||||||
if not devices:
|
if not devices:
|
||||||
logger.info('No SNES device found. Please connect a SNES device to SNI.')
|
snes_logger.info('No SNES device found. Please connect a SNES device to SNI.')
|
||||||
while not devices:
|
while not devices:
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
await socket.send(dumps(DeviceList_Request))
|
await socket.send(dumps(DeviceList_Request))
|
||||||
|
@ -482,7 +495,7 @@ async def get_snes_devices(ctx: Context):
|
||||||
async def snes_connect(ctx: Context, address):
|
async def snes_connect(ctx: Context, address):
|
||||||
global SNES_RECONNECT_DELAY
|
global SNES_RECONNECT_DELAY
|
||||||
if ctx.snes_socket is not None and ctx.snes_state == SNESState.SNES_CONNECTED:
|
if ctx.snes_socket is not None and ctx.snes_state == SNESState.SNES_CONNECTED:
|
||||||
logger.error('Already connected to snes')
|
snes_logger.error('Already connected to snes')
|
||||||
return
|
return
|
||||||
|
|
||||||
recv_task = None
|
recv_task = None
|
||||||
|
@ -505,7 +518,7 @@ async def snes_connect(ctx: Context, address):
|
||||||
await snes_disconnect(ctx)
|
await snes_disconnect(ctx)
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.info("Attaching to " + device)
|
snes_logger.info("Attaching to " + device)
|
||||||
|
|
||||||
Attach_Request = {
|
Attach_Request = {
|
||||||
"Opcode": "Attach",
|
"Opcode": "Attach",
|
||||||
|
@ -530,9 +543,9 @@ async def snes_connect(ctx: Context, address):
|
||||||
ctx.snes_socket = None
|
ctx.snes_socket = None
|
||||||
ctx.snes_state = SNESState.SNES_DISCONNECTED
|
ctx.snes_state = SNESState.SNES_DISCONNECTED
|
||||||
if not ctx.snes_reconnect_address:
|
if not ctx.snes_reconnect_address:
|
||||||
logger.error("Error connecting to snes (%s)" % e)
|
snes_logger.error("Error connecting to snes (%s)" % e)
|
||||||
else:
|
else:
|
||||||
logger.error(f"Error connecting to snes, attempt again in {SNES_RECONNECT_DELAY}s")
|
snes_logger.error(f"Error connecting to snes, attempt again in {SNES_RECONNECT_DELAY}s")
|
||||||
asyncio.create_task(snes_autoreconnect(ctx))
|
asyncio.create_task(snes_autoreconnect(ctx))
|
||||||
SNES_RECONNECT_DELAY *= 2
|
SNES_RECONNECT_DELAY *= 2
|
||||||
|
|
||||||
|
@ -559,11 +572,11 @@ async def snes_recv_loop(ctx: Context):
|
||||||
try:
|
try:
|
||||||
async for msg in ctx.snes_socket:
|
async for msg in ctx.snes_socket:
|
||||||
ctx.snes_recv_queue.put_nowait(msg)
|
ctx.snes_recv_queue.put_nowait(msg)
|
||||||
logger.warning("Snes disconnected")
|
snes_logger.warning("Snes disconnected")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if not isinstance(e, websockets.WebSocketException):
|
if not isinstance(e, websockets.WebSocketException):
|
||||||
logger.exception(e)
|
snes_logger.exception(e)
|
||||||
logger.error("Lost connection to the snes, type /snes to reconnect")
|
snes_logger.error("Lost connection to the snes, type /snes to reconnect")
|
||||||
finally:
|
finally:
|
||||||
socket, ctx.snes_socket = ctx.snes_socket, None
|
socket, ctx.snes_socket = ctx.snes_socket, None
|
||||||
if socket is not None and not socket.closed:
|
if socket is not None and not socket.closed:
|
||||||
|
@ -576,7 +589,7 @@ async def snes_recv_loop(ctx: Context):
|
||||||
ctx.rom = None
|
ctx.rom = None
|
||||||
|
|
||||||
if ctx.snes_reconnect_address:
|
if ctx.snes_reconnect_address:
|
||||||
logger.info(f"...reconnecting in {SNES_RECONNECT_DELAY}s")
|
snes_logger.info(f"...reconnecting in {SNES_RECONNECT_DELAY}s")
|
||||||
asyncio.create_task(snes_autoreconnect(ctx))
|
asyncio.create_task(snes_autoreconnect(ctx))
|
||||||
|
|
||||||
|
|
||||||
|
@ -605,10 +618,10 @@ async def snes_read(ctx: Context, address, size):
|
||||||
break
|
break
|
||||||
|
|
||||||
if len(data) != size:
|
if len(data) != size:
|
||||||
logger.error('Error reading %s, requested %d bytes, received %d' % (hex(address), size, len(data)))
|
snes_logger.error('Error reading %s, requested %d bytes, received %d' % (hex(address), size, len(data)))
|
||||||
if len(data):
|
if len(data):
|
||||||
logger.error(str(data))
|
snes_logger.error(str(data))
|
||||||
logger.warning('Communication Failure with SNI')
|
snes_logger.warning('Communication Failure with SNI')
|
||||||
if ctx.snes_socket is not None and not ctx.snes_socket.closed:
|
if ctx.snes_socket is not None and not ctx.snes_socket.closed:
|
||||||
await ctx.snes_socket.close()
|
await ctx.snes_socket.close()
|
||||||
return None
|
return None
|
||||||
|
@ -634,7 +647,7 @@ async def snes_write(ctx: Context, write_list):
|
||||||
await ctx.snes_socket.send(dumps(PutAddress_Request))
|
await ctx.snes_socket.send(dumps(PutAddress_Request))
|
||||||
await ctx.snes_socket.send(data)
|
await ctx.snes_socket.send(data)
|
||||||
else:
|
else:
|
||||||
logger.warning(f"Could not send data to SNES: {data}")
|
snes_logger.warning(f"Could not send data to SNES: {data}")
|
||||||
except websockets.ConnectionClosed:
|
except websockets.ConnectionClosed:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -673,7 +686,7 @@ async def track_locations(ctx: Context, roomid, roomdata):
|
||||||
new_locations.append(location_id)
|
new_locations.append(location_id)
|
||||||
ctx.locations_checked.add(location_id)
|
ctx.locations_checked.add(location_id)
|
||||||
location = ctx.location_name_getter(location_id)
|
location = ctx.location_name_getter(location_id)
|
||||||
logger.info(f'New Check: {location} ({len(ctx.locations_checked)}/{len(ctx.missing_locations) + len(ctx.checked_locations)})')
|
snes_logger.info(f'New Check: {location} ({len(ctx.locations_checked)}/{len(ctx.missing_locations) + len(ctx.checked_locations)})')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if roomid in location_shop_ids:
|
if roomid in location_shop_ids:
|
||||||
|
@ -682,7 +695,7 @@ async def track_locations(ctx: Context, roomid, roomdata):
|
||||||
if int(b) and (Shops.SHOP_ID_START + cnt) not in ctx.locations_checked:
|
if int(b) and (Shops.SHOP_ID_START + cnt) not in ctx.locations_checked:
|
||||||
new_check(Shops.SHOP_ID_START + cnt)
|
new_check(Shops.SHOP_ID_START + cnt)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info(f"Exception: {e}")
|
snes_logger.info(f"Exception: {e}")
|
||||||
|
|
||||||
for location_id, (loc_roomid, loc_mask) in location_table_uw_id.items():
|
for location_id, (loc_roomid, loc_mask) in location_table_uw_id.items():
|
||||||
try:
|
try:
|
||||||
|
@ -691,7 +704,7 @@ async def track_locations(ctx: Context, roomid, roomdata):
|
||||||
roomdata << 4) & loc_mask != 0:
|
roomdata << 4) & loc_mask != 0:
|
||||||
new_check(location_id)
|
new_check(location_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Exception: {e}")
|
snes_logger.exception(f"Exception: {e}")
|
||||||
|
|
||||||
uw_begin = 0x129
|
uw_begin = 0x129
|
||||||
ow_end = uw_end = 0
|
ow_end = uw_end = 0
|
||||||
|
@ -774,7 +787,7 @@ async def game_watcher(ctx: Context):
|
||||||
await ctx.server_auth(False)
|
await ctx.server_auth(False)
|
||||||
|
|
||||||
if ctx.auth and ctx.auth != ctx.rom:
|
if ctx.auth and ctx.auth != ctx.rom:
|
||||||
logger.warning("ROM change detected, please reconnect to the multiworld server")
|
snes_logger.warning("ROM change detected, please reconnect to the multiworld server")
|
||||||
await ctx.disconnect()
|
await ctx.disconnect()
|
||||||
|
|
||||||
gamemode = await snes_read(ctx, WRAM_START + 0x10, 1)
|
gamemode = await snes_read(ctx, WRAM_START + 0x10, 1)
|
||||||
|
@ -857,6 +870,8 @@ async def main():
|
||||||
parser.add_argument('--loglevel', default='info', choices=['debug', 'info', 'warning', 'error', 'critical'])
|
parser.add_argument('--loglevel', default='info', choices=['debug', 'info', 'warning', 'error', 'critical'])
|
||||||
parser.add_argument('--founditems', default=False, action='store_true',
|
parser.add_argument('--founditems', default=False, action='store_true',
|
||||||
help='Show items found by other players for themselves.')
|
help='Show items found by other players for themselves.')
|
||||||
|
if not Utils.is_frozen(): # Frozen state has no cmd window in the first place
|
||||||
|
parser.add_argument('--nogui', default=False, action='store_true', help="Turns off Client GUI.")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
logging.basicConfig(format='%(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
logging.basicConfig(format='%(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
||||||
if args.diff_file:
|
if args.diff_file:
|
||||||
|
@ -875,22 +890,33 @@ async def main():
|
||||||
asyncio.create_task(run_game(adjustedromfile if adjusted else romfile))
|
asyncio.create_task(run_game(adjustedromfile if adjusted else romfile))
|
||||||
|
|
||||||
ctx = Context(args.snes, args.connect, args.password)
|
ctx = Context(args.snes, args.connect, args.password)
|
||||||
input_task = asyncio.create_task(console_loop(ctx), name="Input")
|
|
||||||
|
|
||||||
if ctx.server_task is None:
|
if ctx.server_task is None:
|
||||||
ctx.server_task = asyncio.create_task(server_loop(ctx), name="ServerLoop")
|
ctx.server_task = asyncio.create_task(server_loop(ctx), name="ServerLoop")
|
||||||
asyncio.create_task(snes_connect(ctx, ctx.snes_address))
|
|
||||||
|
if Utils.is_frozen() or "--nogui" not in sys.argv:
|
||||||
|
input_task = None
|
||||||
|
from kvui import LttPManager
|
||||||
|
ui_app = LttPManager(ctx)
|
||||||
|
ctx.ui = ui_app
|
||||||
|
ui_task = asyncio.create_task(ui_app.async_run(), name="UI")
|
||||||
|
else:
|
||||||
|
input_task = asyncio.create_task(console_loop(ctx), name="Input")
|
||||||
|
ui_task = None
|
||||||
|
|
||||||
|
snes_connect_task = asyncio.create_task(snes_connect(ctx, ctx.snes_address))
|
||||||
watcher_task = asyncio.create_task(game_watcher(ctx), name="GameWatcher")
|
watcher_task = asyncio.create_task(game_watcher(ctx), name="GameWatcher")
|
||||||
|
|
||||||
await ctx.exit_event.wait()
|
await ctx.exit_event.wait()
|
||||||
|
if snes_connect_task:
|
||||||
|
snes_connect_task.cancel()
|
||||||
ctx.server_address = None
|
ctx.server_address = None
|
||||||
ctx.snes_reconnect_address = None
|
ctx.snes_reconnect_address = None
|
||||||
|
|
||||||
await watcher_task
|
await watcher_task
|
||||||
|
|
||||||
if ctx.server is not None and not ctx.server.socket.closed:
|
if ctx.server and not ctx.server.socket.closed:
|
||||||
await ctx.server.socket.close()
|
await ctx.server.socket.close()
|
||||||
if ctx.server_task is not None:
|
if ctx.server_task:
|
||||||
await ctx.server_task
|
await ctx.server_task
|
||||||
|
|
||||||
if ctx.snes_socket is not None and not ctx.snes_socket.closed:
|
if ctx.snes_socket is not None and not ctx.snes_socket.closed:
|
||||||
|
@ -900,7 +926,11 @@ async def main():
|
||||||
ctx.input_queue.put_nowait(None)
|
ctx.input_queue.put_nowait(None)
|
||||||
ctx.input_requests -= 1
|
ctx.input_requests -= 1
|
||||||
|
|
||||||
await input_task
|
if ui_task:
|
||||||
|
await ui_task
|
||||||
|
|
||||||
|
if input_task:
|
||||||
|
input_task.cancel()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
#define sourcepath "build_factorio\exe.win-amd64-3.8\"
|
|
||||||
#define MyAppName "Archipelago Factorio Client"
|
|
||||||
#define MyAppExeName "ArchipelagoGraphicalFactorioClient.exe"
|
|
||||||
#define MyAppIcon "data/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={{D13CEBD0-F1D5-4435-A4A6-5243F934613F}}
|
|
||||||
AppName={#MyAppName}
|
|
||||||
AppVerName={#MyAppName}
|
|
||||||
DefaultDirName={commonappdata}\{#MyAppName}
|
|
||||||
DisableProgramGroupPage=yes
|
|
||||||
DefaultGroupName=Archipelago
|
|
||||||
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: "vc_redist.x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall
|
|
||||||
Source: "{#sourcepath}*"; Excludes: "*.sfc, *.log, data\sprites\alttpr"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
|
||||||
; 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..."
|
|
||||||
|
|
||||||
[UninstallDelete]
|
|
||||||
Type: dirifempty; Name: "{app}"
|
|
||||||
|
|
||||||
|
|
||||||
[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.29.30037') < 0);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
// Not even an old version installed
|
|
||||||
Log('VC Redist x64 is not already installed');
|
|
||||||
Result := True;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#define sourcepath "build\exe.win-amd64-3.8\"
|
#define sourcepath "build\exe.win-amd64-3.8\"
|
||||||
#define MyAppName "Archipelago"
|
#define MyAppName "Archipelago"
|
||||||
#define MyAppExeName "ArchipelagoLttPClient.exe"
|
#define MyAppExeName "ArchipelagoServer.exe"
|
||||||
#define MyAppIcon "data/icon.ico"
|
#define MyAppIcon "data/icon.ico"
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
|
@ -34,40 +34,65 @@ Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||||
[Tasks]
|
[Tasks]
|
||||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}";
|
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}";
|
||||||
|
|
||||||
|
[Types]
|
||||||
|
Name: "full"; Description: "Full installation"
|
||||||
|
Name: "hosting"; Description: "Installation for hosting purposes"
|
||||||
|
Name: "playing"; Description: "Installation for playing purposes"
|
||||||
|
Name: "custom"; Description: "Custom installation"; Flags: iscustom
|
||||||
|
|
||||||
|
[Components]
|
||||||
|
Name: "core"; Description: "Core Files"; Types: full hosting playing custom; Flags: fixed
|
||||||
|
Name: "generator"; Description: "Generator"; Types: full hosting
|
||||||
|
Name: "server"; Description: "Server"; Types: full hosting
|
||||||
|
Name: "client"; Description: "Clients"; Types: full playing
|
||||||
|
Name: "client/lttp"; Description: "A Link to the Past"; Types: full playing hosting
|
||||||
|
Name: "client/factorio"; Description: "Factorio"; Types: full playing
|
||||||
|
|
||||||
[Dirs]
|
[Dirs]
|
||||||
NAME: "{app}"; Flags: setntfscompression; Permissions: everyone-modify users-modify authusers-modify;
|
NAME: "{app}"; Flags: setntfscompression; Permissions: everyone-modify users-modify authusers-modify;
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: "{code:GetROMPath}"; DestDir: "{app}"; DestName: "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc"; Flags: external
|
Source: "{code:GetROMPath}"; DestDir: "{app}"; DestName: "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc"; Flags: external; Components: client/lttp or server
|
||||||
Source: "{#sourcepath}*"; Excludes: "*.sfc, *.log, data\sprites\alttpr"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
Source: "{#sourcepath}*"; Excludes: "*.sfc, *.log, data\sprites\alttpr, SNI, EnemizerCLI, *exe"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
|
Source: "{#sourcepath}\SNI"; Excludes: "*.sfc, *.log"; DestDir: "{app}\SNI"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: client/lttp
|
||||||
|
Source: "{#sourcepath}\EnemizerCLI"; Excludes: "*.sfc, *.log"; DestDir: "{app}\EnemizerCLI"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: generator
|
||||||
|
|
||||||
|
Source: "{#sourcepath}\ArchipelagoGenerate.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: generator
|
||||||
|
Source: "{#sourcepath}\ArchipelagoServer.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: server
|
||||||
|
Source: "{#sourcepath}\ArchipelagoFactorioClient.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: client/factorio
|
||||||
|
Source: "{#sourcepath}\ArchipelagoLttPClient.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: client/lttp
|
||||||
|
Source: "{#sourcepath}\ArchipelagoLttPAdjuster.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: client/lttp
|
||||||
Source: "vc_redist.x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall
|
Source: "vc_redist.x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall
|
||||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: "{group}\{#MyAppName} Folder"; Filename: "{app}";
|
Name: "{group}\{#MyAppName} Folder"; Filename: "{app}";
|
||||||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}";
|
Name: "{group}\{#MyAppName} Server"; Filename: "{app}\{#MyAppExeName}"; Components: server
|
||||||
|
Name: "{group}\{#MyAppName} LttP Client"; Filename: "{app}\ArchipelagoLttPClient.exe"; Components: client/lttp
|
||||||
|
Name: "{group}\{#MyAppName} Factorio Client"; Filename: "{app}\ArchipelagoFactorioClient.exe"; Components: client/factorio
|
||||||
Name: "{commondesktop}\{#MyAppName} Folder"; Filename: "{app}"; Tasks: desktopicon
|
Name: "{commondesktop}\{#MyAppName} Folder"; Filename: "{app}"; Tasks: desktopicon
|
||||||
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
Name: "{commondesktop}\{#MyAppName} Server"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon; Components: server
|
||||||
|
Name: "{commondesktop}\{#MyAppName} LttP Client"; Filename: "{app}\ArchipelagoLttPClient.exe"; Tasks: desktopicon; Components: client/lttp
|
||||||
|
Name: "{commondesktop}\{#MyAppName} Factorio Client"; Filename: "{app}\ArchipelagoFactorioClient.exe"; Tasks: desktopicon; Components: client/factorio
|
||||||
|
|
||||||
[Run]
|
[Run]
|
||||||
|
|
||||||
Filename: "{tmp}\vc_redist.x64.exe"; Parameters: "/passive /norestart"; Check: IsVCRedist64BitNeeded; StatusMsg: "Installing VC++ redistributable..."
|
Filename: "{tmp}\vc_redist.x64.exe"; Parameters: "/passive /norestart"; Check: IsVCRedist64BitNeeded; StatusMsg: "Installing VC++ redistributable..."
|
||||||
Filename: "{app}\ArchipelagoLttPAdjuster"; Parameters: "--update_sprites"; StatusMsg: "Updating Sprite Library..."
|
Filename: "{app}\ArchipelagoLttPAdjuster"; Parameters: "--update_sprites"; StatusMsg: "Updating Sprite Library..."; Components: client/lttp or server
|
||||||
|
|
||||||
[UninstallDelete]
|
[UninstallDelete]
|
||||||
Type: dirifempty; Name: "{app}"
|
Type: dirifempty; Name: "{app}"
|
||||||
|
|
||||||
[Registry]
|
[Registry]
|
||||||
|
|
||||||
Root: HKCR; Subkey: ".apbp"; ValueData: "{#MyAppName}patch"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""
|
Root: HKCR; Subkey: ".apbp"; ValueData: "{#MyAppName}patch"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Components: client/lttp
|
||||||
Root: HKCR; Subkey: "{#MyAppName}patch"; ValueData: "Archipelago Binary Patch"; Flags: uninsdeletekey; ValueType: string; ValueName: ""
|
Root: HKCR; Subkey: "{#MyAppName}patch"; ValueData: "Archipelago Binary Patch"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Components: client/lttp
|
||||||
Root: HKCR; Subkey: "{#MyAppName}patch\DefaultIcon"; ValueData: "{app}\{#MyAppExeName},0"; ValueType: string; ValueName: ""
|
Root: HKCR; Subkey: "{#MyAppName}patch\DefaultIcon"; ValueData: "{app}\{#MyAppExeName},0"; ValueType: string; ValueName: ""; Components: client/lttp
|
||||||
Root: HKCR; Subkey: "{#MyAppName}patch\shell\open\command"; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; ValueType: string; ValueName: ""
|
Root: HKCR; Subkey: "{#MyAppName}patch\shell\open\command"; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; ValueType: string; ValueName: ""; Components: client/lttp
|
||||||
|
|
||||||
Root: HKCR; Subkey: ".archipelago"; ValueData: "{#MyAppName}multidata"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""
|
Root: HKCR; Subkey: ".archipelago"; ValueData: "{#MyAppName}multidata"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Components: server
|
||||||
Root: HKCR; Subkey: "{#MyAppName}multidata"; ValueData: "Archipelago Server Data"; Flags: uninsdeletekey; ValueType: string; ValueName: ""
|
Root: HKCR; Subkey: "{#MyAppName}multidata"; ValueData: "Archipelago Server Data"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Components: server
|
||||||
Root: HKCR; Subkey: "{#MyAppName}multidata\DefaultIcon"; ValueData: "{app}\ArchipelagoServer.exe,0"; ValueType: string; ValueName: ""
|
Root: HKCR; Subkey: "{#MyAppName}multidata\DefaultIcon"; ValueData: "{app}\ArchipelagoServer.exe,0"; ValueType: string; ValueName: ""; Components: server
|
||||||
Root: HKCR; Subkey: "{#MyAppName}multidata\shell\open\command"; ValueData: """{app}\ArchipelagoServer.exe"" ""%1"""; ValueType: string; ValueName: ""
|
Root: HKCR; Subkey: "{#MyAppName}multidata\shell\open\command"; ValueData: """{app}\ArchipelagoServer.exe"" ""%1"""; ValueType: string; ValueName: ""; Components: server
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,141 +0,0 @@
|
||||||
#define sourcepath "build\exe.win-amd64-3.9\"
|
|
||||||
#define MyAppName "Archipelago"
|
|
||||||
#define MyAppExeName "ArchipelagoLttPClient.exe"
|
|
||||||
#define MyAppIcon "data/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={{918BA46A-FAB8-460C-9DFF-AE691E1C865B}}
|
|
||||||
AppName={#MyAppName}
|
|
||||||
AppVerName={#MyAppName}
|
|
||||||
DefaultDirName={commonappdata}\{#MyAppName}
|
|
||||||
DisableProgramGroupPage=yes
|
|
||||||
DefaultGroupName=Archipelago
|
|
||||||
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}\ArchipelagoLttPAdjuster"; Parameters: "--update_sprites"; StatusMsg: "Updating Sprite Library..."
|
|
||||||
|
|
||||||
[UninstallDelete]
|
|
||||||
Type: dirifempty; Name: "{app}"
|
|
||||||
|
|
||||||
[Registry]
|
|
||||||
|
|
||||||
Root: HKCR; Subkey: ".apbp"; ValueData: "{#MyAppName}patch"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""
|
|
||||||
Root: HKCR; Subkey: "{#MyAppName}patch"; ValueData: "Archipelago 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: ".archipelago"; ValueData: "{#MyAppName}multidata"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""
|
|
||||||
Root: HKCR; Subkey: "{#MyAppName}multidata"; ValueData: "Archipelago Server Data"; Flags: uninsdeletekey; ValueType: string; ValueName: ""
|
|
||||||
Root: HKCR; Subkey: "{#MyAppName}multidata\DefaultIcon"; ValueData: "{app}\ArchipelagoServer.exe,0"; ValueType: string; ValueName: ""
|
|
||||||
Root: HKCR; Subkey: "{#MyAppName}multidata\shell\open\command"; ValueData: """{app}\ArchipelagoServer.exe"" ""%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.29.30037') < 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;
|
|
9
kvui.py
9
kvui.py
|
@ -83,9 +83,12 @@ class FactorioManager(GameManager):
|
||||||
]
|
]
|
||||||
title = "Archipelago Factorio Client"
|
title = "Archipelago Factorio Client"
|
||||||
|
|
||||||
def __init__(self, ctx):
|
class LttPManager(GameManager):
|
||||||
super(FactorioManager, self).__init__(ctx)
|
logging_pairs = [
|
||||||
|
("Client", "Archipelago"),
|
||||||
|
("SNES", "SNES"),
|
||||||
|
]
|
||||||
|
title = "Archipelago LttP Client"
|
||||||
|
|
||||||
class LogtoUI(logging.Handler):
|
class LogtoUI(logging.Handler):
|
||||||
def __init__(self, on_log):
|
def __init__(self, on_log):
|
||||||
|
|
107
setup.py
107
setup.py
|
@ -4,12 +4,13 @@ import sys
|
||||||
import sysconfig
|
import sysconfig
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import cx_Freeze
|
import cx_Freeze
|
||||||
|
from kivy_deps import sdl2, glew
|
||||||
|
|
||||||
is_64bits = sys.maxsize > 2 ** 32
|
is_64bits = sys.maxsize > 2 ** 32
|
||||||
|
|
||||||
folder = "exe.{platform}-{version}".format(platform=sysconfig.get_platform(),
|
arch_folder = "exe.{platform}-{version}".format(platform=sysconfig.get_platform(),
|
||||||
version=sysconfig.get_python_version())
|
version=sysconfig.get_python_version())
|
||||||
buildfolder = Path("build", folder)
|
buildfolder = Path("build", arch_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")
|
||||||
|
@ -56,20 +57,31 @@ def manifest_creation(folder):
|
||||||
print("Created Manifest")
|
print("Created Manifest")
|
||||||
|
|
||||||
|
|
||||||
|
def remove_sprites_from_folder(folder):
|
||||||
|
for file in os.listdir(folder):
|
||||||
|
if file != ".gitignore":
|
||||||
|
os.remove(folder / file)
|
||||||
|
|
||||||
|
|
||||||
scripts = {
|
scripts = {
|
||||||
"LttPClient.py": "ArchipelagoLttPClient",
|
# Core
|
||||||
"MultiServer.py": "ArchipelagoServer",
|
"MultiServer.py": ("ArchipelagoServer", False),
|
||||||
"Generate.py": "ArchipelagoGenerate",
|
"Generate.py": ("ArchipelagoGenerate", False),
|
||||||
"LttPAdjuster.py": "ArchipelagoLttPAdjuster"
|
# LttP
|
||||||
|
"LttPClient.py": ("ArchipelagoLttPClient", True),
|
||||||
|
"LttPAdjuster.py": ("ArchipelagoLttPAdjuster", True),
|
||||||
|
# Factorio
|
||||||
|
"FactorioClient.py": ("ArchipelagoFactorioClient", True),
|
||||||
}
|
}
|
||||||
|
|
||||||
exes = []
|
exes = []
|
||||||
|
|
||||||
for script, scriptname in scripts.items():
|
for script, (scriptname, gui) in scripts.items():
|
||||||
exes.append(cx_Freeze.Executable(
|
exes.append(cx_Freeze.Executable(
|
||||||
script=script,
|
script=script,
|
||||||
target_name=scriptname + ("" if sys.platform == "linux" else ".exe"),
|
target_name=scriptname + ("" if sys.platform == "linux" else ".exe"),
|
||||||
icon=icon,
|
icon=icon,
|
||||||
|
base="Win32GUI" if sys.platform == "win32" and gui else None
|
||||||
))
|
))
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -83,14 +95,14 @@ cx_Freeze.setup(
|
||||||
executables=exes,
|
executables=exes,
|
||||||
options={
|
options={
|
||||||
"build_exe": {
|
"build_exe": {
|
||||||
"packages": ["websockets", "worlds"],
|
"packages": ["websockets", "worlds", "kivy"],
|
||||||
"includes": [],
|
"includes": [],
|
||||||
"excludes": ["numpy", "Cython", "PySide2", "PIL",
|
"excludes": ["numpy", "Cython", "PySide2", "PIL",
|
||||||
"pandas"],
|
"pandas"],
|
||||||
"zip_include_packages": ["*"],
|
"zip_include_packages": ["*"],
|
||||||
"zip_exclude_packages": ["worlds"],
|
"zip_exclude_packages": ["worlds", "kivy"],
|
||||||
"include_files": [],
|
"include_files": [],
|
||||||
"include_msvcr": True,
|
"include_msvcr": False,
|
||||||
"replace_paths": [("*", "")],
|
"replace_paths": [("*", "")],
|
||||||
"optimize": 1,
|
"optimize": 1,
|
||||||
"build_exe": buildfolder
|
"build_exe": buildfolder
|
||||||
|
@ -112,6 +124,9 @@ def installfile(path, keep_content=False):
|
||||||
else:
|
else:
|
||||||
print('Warning,', path, 'not found')
|
print('Warning,', path, 'not found')
|
||||||
|
|
||||||
|
for folder in sdl2.dep_bins+glew.dep_bins:
|
||||||
|
shutil.copytree(folder, libfolder, dirs_exist_ok=True)
|
||||||
|
print('copying', folder, '->', libfolder)
|
||||||
|
|
||||||
extra_data = ["LICENSE", "data", "EnemizerCLI", "host.yaml", "SNI", "meta.yaml"]
|
extra_data = ["LICENSE", "data", "EnemizerCLI", "host.yaml", "SNI", "meta.yaml"]
|
||||||
|
|
||||||
|
@ -138,76 +153,6 @@ if signtool:
|
||||||
print(f"Signing SNI")
|
print(f"Signing SNI")
|
||||||
os.system(signtool + os.path.join(buildfolder, "SNI", "SNI.exe"))
|
os.system(signtool + os.path.join(buildfolder, "SNI", "SNI.exe"))
|
||||||
|
|
||||||
alttpr_sprites_folder = buildfolder / "data" / "sprites" / "alttpr"
|
remove_sprites_from_folder(buildfolder / "data" / "sprites" / "alttpr")
|
||||||
for file in os.listdir(alttpr_sprites_folder):
|
|
||||||
if file != ".gitignore":
|
|
||||||
os.remove(alttpr_sprites_folder / file)
|
|
||||||
|
|
||||||
manifest_creation(buildfolder)
|
|
||||||
|
|
||||||
buildfolder = Path("build_factorio", folder)
|
|
||||||
sbuildfolder = str(buildfolder)
|
|
||||||
libfolder = Path(buildfolder, "lib")
|
|
||||||
library = Path(libfolder, "library.zip")
|
|
||||||
print("Outputting Factorio Client to: " + sbuildfolder)
|
|
||||||
|
|
||||||
os.makedirs(buildfolder, exist_ok=True)
|
|
||||||
|
|
||||||
|
|
||||||
exes = [
|
|
||||||
cx_Freeze.Executable(
|
|
||||||
script="FactorioClient.py",
|
|
||||||
target_name="ArchipelagoFactorioClient" + ("" if sys.platform == "linux" else ".exe"),
|
|
||||||
icon=icon,
|
|
||||||
base="Win32GUI" if sys.platform == "win32" else None
|
|
||||||
)]
|
|
||||||
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
buildtime = datetime.datetime.utcnow()
|
|
||||||
|
|
||||||
cx_Freeze.setup(
|
|
||||||
name="Archipelago Factorio Client",
|
|
||||||
version=f"{buildtime.year}.{buildtime.month}.{buildtime.day}.{buildtime.hour}",
|
|
||||||
description="Archipelago Factorio Client",
|
|
||||||
executables=exes,
|
|
||||||
options={
|
|
||||||
"build_exe": {
|
|
||||||
"packages": ["websockets", "kivy", "worlds"],
|
|
||||||
"includes": [],
|
|
||||||
"excludes": ["numpy", "Cython", "PySide2", "PIL",
|
|
||||||
"pandas"],
|
|
||||||
"zip_include_packages": ["*"],
|
|
||||||
"zip_exclude_packages": ["kivy", "worlds"],
|
|
||||||
"include_files": [],
|
|
||||||
"include_msvcr": True,
|
|
||||||
"replace_paths": [("*", "")],
|
|
||||||
"optimize": 1,
|
|
||||||
"build_exe": buildfolder
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
extra_data = ["LICENSE", "data", "host.yaml", "meta.yaml"]
|
|
||||||
from kivy_deps import sdl2, glew
|
|
||||||
for folder in sdl2.dep_bins+glew.dep_bins:
|
|
||||||
shutil.copytree(folder, buildfolder, dirs_exist_ok=True)
|
|
||||||
for data in extra_data:
|
|
||||||
installfile(Path(data))
|
|
||||||
|
|
||||||
|
|
||||||
os.makedirs(buildfolder / "Players", exist_ok=True)
|
|
||||||
shutil.copyfile("playerSettings.yaml", buildfolder / "Players" / "weightedSettings.yaml")
|
|
||||||
|
|
||||||
if signtool:
|
|
||||||
for exe in exes:
|
|
||||||
print(f"Signing {exe.target_name}")
|
|
||||||
os.system(signtool + os.path.join(buildfolder, exe.target_name))
|
|
||||||
|
|
||||||
alttpr_sprites_folder = buildfolder / "data" / "sprites" / "alttpr"
|
|
||||||
for file in os.listdir(alttpr_sprites_folder):
|
|
||||||
if file != ".gitignore":
|
|
||||||
os.remove(alttpr_sprites_folder / file)
|
|
||||||
|
|
||||||
manifest_creation(buildfolder)
|
manifest_creation(buildfolder)
|
||||||
|
|
Loading…
Reference in New Issue