Merge branch 'master' of https://github.com/Berserker66/MultiWorld-Utilities
This commit is contained in:
commit
3448437815
|
@ -27,7 +27,7 @@ import Utils
|
|||
from Utils import get_item_name_from_id, get_location_name_from_address, ReceivedItem
|
||||
from NetUtils import Node, Endpoint
|
||||
|
||||
console_names = frozenset(set(Items.item_table) | set(Regions.location_table))
|
||||
console_names = frozenset(set(Items.item_table) | set(Regions.location_table) | set(Items.item_name_groups))
|
||||
|
||||
CLIENT_PLAYING = 0
|
||||
CLIENT_GOAL = 1
|
||||
|
@ -61,7 +61,7 @@ class Context(Node):
|
|||
super(Context, self).__init__()
|
||||
self.data_filename = None
|
||||
self.save_filename = None
|
||||
self.disable_save = False
|
||||
self.saving = False
|
||||
self.player_names = {}
|
||||
self.rom_names = {}
|
||||
self.remote_items = set()
|
||||
|
@ -82,12 +82,46 @@ class Context(Node):
|
|||
self.remaining_mode: str = remaining_mode
|
||||
self.item_cheat = item_cheat
|
||||
self.running = True
|
||||
self.client_activity_timers: typing.Dict[typing.Tuple[int, int], datetime.datetime] = {} # datatime of last new item check
|
||||
self.client_connection_timers: typing.Dict[typing.Tuple[int, int], datetime.datetime] = {} # datetime of last connection
|
||||
self.client_activity_timers: typing.Dict[
|
||||
typing.Tuple[int, int], datetime.datetime] = {} # datatime of last new item check
|
||||
self.client_connection_timers: typing.Dict[
|
||||
typing.Tuple[int, int], datetime.datetime] = {} # datetime of last connection
|
||||
self.client_game_state: typing.Dict[typing.Tuple[int, int], int] = collections.defaultdict(int)
|
||||
self.er_hint_data: typing.Dict[int, typing.Dict[int, str]] = {}
|
||||
self.commandprocessor = ServerCommandProcessor(self)
|
||||
|
||||
def load(self, multidatapath: str):
|
||||
with open(multidatapath, 'rb') as f:
|
||||
self._load(f)
|
||||
self.data_filename = multidatapath
|
||||
|
||||
def _load(self, fileobj):
|
||||
jsonobj = json.loads(zlib.decompress(fileobj.read()).decode("utf-8-sig"))
|
||||
for team, names in enumerate(jsonobj['names']):
|
||||
for player, name in enumerate(names, 1):
|
||||
self.player_names[(team, player)] = name
|
||||
self.rom_names = {tuple(rom): (team, slot) for slot, team, rom in jsonobj['roms']}
|
||||
self.remote_items = set(jsonobj['remote_items'])
|
||||
self.locations = {tuple(k): tuple(v) for k, v in jsonobj['locations']}
|
||||
if "er_hint_data" in jsonobj:
|
||||
self.er_hint_data = {int(player): {int(address): name for address, name in loc_data.items()}
|
||||
for player, loc_data in jsonobj["er_hint_data"].items()}
|
||||
|
||||
def init_save(self, enabled: bool):
|
||||
self.saving = enabled
|
||||
if self.saving:
|
||||
if not self.save_filename:
|
||||
self.save_filename = (self.data_filename[:-9] if self.data_filename[-9:] == 'multidata' else (
|
||||
self.data_filename + '_')) + 'multisave'
|
||||
try:
|
||||
with open(self.save_filename, 'rb') as f:
|
||||
jsonobj = json.loads(zlib.decompress(f.read()).decode("utf-8"))
|
||||
self.set_save(jsonobj)
|
||||
except FileNotFoundError:
|
||||
logging.error('No save data found, starting a new game')
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
|
||||
def get_save(self) -> dict:
|
||||
d = {
|
||||
"rom_names": list(self.rom_names.items()),
|
||||
|
@ -361,7 +395,7 @@ def notify_team(ctx: Context, team: int, text: str):
|
|||
|
||||
|
||||
def save(ctx: Context):
|
||||
if not ctx.disable_save:
|
||||
if ctx.saving:
|
||||
try:
|
||||
jsonstr = json.dumps(ctx.get_save())
|
||||
with open(ctx.save_filename, "wb") as f:
|
||||
|
@ -668,6 +702,10 @@ class ClientMessageProcessor(CommandProcessor):
|
|||
if item_name in Items.hint_blacklist:
|
||||
self.output(f"Sorry, \"{item_name}\" is marked as non-hintable.")
|
||||
hints = []
|
||||
elif item_name in Items.item_name_groups:
|
||||
hints = []
|
||||
for item in Items.item_name_groups[item_name]:
|
||||
hints.extend(collect_hints(self.ctx, self.client.team, self.client.slot, item))
|
||||
elif item_name in Items.item_table: # item name
|
||||
hints = collect_hints(self.ctx, self.client.team, self.client.slot, item_name)
|
||||
else: # location name
|
||||
|
@ -929,12 +967,15 @@ class ServerCommandProcessor(CommandProcessor):
|
|||
item = " ".join(item_or_location)
|
||||
item, usable, response = get_intended_text(item)
|
||||
if usable:
|
||||
if item in Items.item_table: # item name
|
||||
if item in Items.item_name_groups:
|
||||
hints = []
|
||||
for item in Items.item_name_groups[item]:
|
||||
hints.extend(collect_hints(self.ctx, team, slot, item))
|
||||
elif item in Items.item_table: # item name
|
||||
hints = collect_hints(self.ctx, team, slot, item)
|
||||
notify_hints(self.ctx, team, hints)
|
||||
else: # location name
|
||||
hints = collect_hints_location(self.ctx, team, slot, item)
|
||||
notify_hints(self.ctx, team, hints)
|
||||
notify_hints(self.ctx, team, hints)
|
||||
return True
|
||||
else:
|
||||
self.output(response)
|
||||
|
@ -997,51 +1038,27 @@ async def main(args: argparse.Namespace):
|
|||
ctx = Context(args.host, args.port, args.password, args.location_check_points, args.hint_cost,
|
||||
not args.disable_item_cheat, args.forfeit_mode, args.remaining_mode)
|
||||
|
||||
ctx.data_filename = args.multidata
|
||||
data_filename = args.multidata
|
||||
|
||||
try:
|
||||
if not ctx.data_filename:
|
||||
if not data_filename:
|
||||
import tkinter
|
||||
import tkinter.filedialog
|
||||
root = tkinter.Tk()
|
||||
root.withdraw()
|
||||
ctx.data_filename = tkinter.filedialog.askopenfilename(filetypes=(("Multiworld data","*multidata"),))
|
||||
data_filename = tkinter.filedialog.askopenfilename(filetypes=(("Multiworld data", "*multidata"),))
|
||||
|
||||
ctx.load(data_filename)
|
||||
|
||||
with open(ctx.data_filename, 'rb') as f:
|
||||
jsonobj = json.loads(zlib.decompress(f.read()).decode("utf-8-sig"))
|
||||
for team, names in enumerate(jsonobj['names']):
|
||||
for player, name in enumerate(names, 1):
|
||||
ctx.player_names[(team, player)] = name
|
||||
ctx.rom_names = {tuple(rom): (team, slot) for slot, team, rom in jsonobj['roms']}
|
||||
ctx.remote_items = set(jsonobj['remote_items'])
|
||||
ctx.locations = {tuple(k): tuple(v) for k, v in jsonobj['locations']}
|
||||
if "er_hint_data" in jsonobj:
|
||||
ctx.er_hint_data = {int(player): {int(address): name for address, name in loc_data.items()}
|
||||
for player, loc_data in jsonobj["er_hint_data"].items()}
|
||||
except Exception as e:
|
||||
logging.exception('Failed to read multiworld data (%s)' % e)
|
||||
return
|
||||
raise
|
||||
|
||||
ip = args.host if args.host else Utils.get_public_ipv4()
|
||||
|
||||
|
||||
|
||||
ctx.disable_save = args.disable_save
|
||||
if not ctx.disable_save:
|
||||
if not ctx.save_filename:
|
||||
ctx.save_filename = (ctx.data_filename[:-9] if ctx.data_filename[-9:] == 'multidata' else (
|
||||
ctx.data_filename + '_')) + 'multisave'
|
||||
try:
|
||||
with open(ctx.save_filename, 'rb') as f:
|
||||
jsonobj = json.loads(zlib.decompress(f.read()).decode("utf-8"))
|
||||
ctx.set_save(jsonobj)
|
||||
except FileNotFoundError:
|
||||
logging.error('No save data found, starting a new game')
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
ctx.init_save(not args.disable_save)
|
||||
|
||||
ctx.server = websockets.serve(functools.partial(server, ctx=ctx), ctx.host, ctx.port, ping_timeout=None,
|
||||
ping_interval=None)
|
||||
ip = args.host if args.host else Utils.get_public_ipv4()
|
||||
logging.info('Hosting game at %s:%d (%s)' % (ip, ctx.port,
|
||||
'No password' if not ctx.password else 'Password: %s' % ctx.password))
|
||||
await ctx.server
|
||||
|
|
Loading…
Reference in New Issue