Fix: When sending items via send or getitem, only consider items that belong to that world

Fix: Allow cheat-sending items into unconnected slots
This commit is contained in:
Fabian Dill 2021-07-12 14:35:44 +02:00
parent 38bc3d47ad
commit 9821e05386
1 changed files with 25 additions and 21 deletions

View File

@ -25,6 +25,8 @@ import prompt_toolkit
from prompt_toolkit.patch_stdout import patch_stdout
from fuzzywuzzy import process as fuzzy_process
from worlds.AutoWorld import AutoWorldRegister
proxy_worlds = {name: world(None, 0) for name, world in AutoWorldRegister.world_types.items()}
from worlds.alttp import Items, Regions
from worlds import network_data_package, lookup_any_item_id_to_name, lookup_any_item_name_to_id, \
lookup_any_location_id_to_name, lookup_any_location_name_to_id
@ -55,6 +57,7 @@ class Client(Endpoint):
self.messageprocessor = client_message_processor(ctx, self)
self.ctx = weakref.ref(ctx)
team_slot = typing.Tuple[int, int]
class Context(Node):
simple_options = {"hint_cost": int,
@ -75,7 +78,8 @@ class Context(Node):
self.data_filename = None
self.save_filename = None
self.saving = False
self.player_names = {}
self.player_names: typing.Dict[team_slot, str] = {}
self.player_name_lookup: typing.Dict[str, team_slot] = {}
self.connect_names = {} # names of slots clients can connect to
self.allow_forfeits = {}
self.remote_items = set()
@ -87,21 +91,21 @@ class Context(Node):
self.server = None
self.countdown_timer = 0
self.received_items = {}
self.name_aliases: typing.Dict[typing.Tuple[int, int], str] = {}
self.name_aliases: typing.Dict[team_slot, str] = {}
self.location_checks = collections.defaultdict(set)
self.hint_cost = hint_cost
self.location_check_points = location_check_points
self.hints_used = collections.defaultdict(int)
self.hints: typing.Dict[typing.Tuple[int, int], typing.Set[NetUtils.Hint]] = collections.defaultdict(set)
self.hints: typing.Dict[team_slot, typing.Set[NetUtils.Hint]] = collections.defaultdict(set)
self.forfeit_mode: str = forfeit_mode
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] = {} # datetime of last new item check
team_slot, datetime.datetime] = {} # datetime 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)
team_slot, datetime.datetime] = {} # datetime of last connection
self.client_game_state: typing.Dict[team_slot, int] = collections.defaultdict(int)
self.er_hint_data: typing.Dict[int, typing.Dict[int, str]] = {}
self.auto_shutdown = auto_shutdown
self.commandprocessor = ServerCommandProcessor(self)
@ -111,7 +115,7 @@ class Context(Node):
self.auto_saver_thread = None
self.save_dirty = False
self.tags = ['AP']
self.games = {}
self.games: typing.Dict[int, str] = {}
self.minimum_client_versions: typing.Dict[int, Utils.Version] = {}
self.seed_name = ""
@ -147,7 +151,8 @@ class Context(Node):
for team, names in enumerate(decoded_obj['names']):
for player, name in enumerate(names, 1):
self.player_names[(team, player)] = name
self.player_names[team, player] = name
self.player_name_lookup[name] = team, player
self.seed_name = decoded_obj["seed_name"]
self.connect_names = decoded_obj['connect_names']
self.remote_items = decoded_obj['remote_items']
@ -573,8 +578,7 @@ def json_format_send_event(net_item: NetworkItem, receiving_player: int):
"item": net_item}
def get_intended_text(input_text: str, possible_answers: typing.Iterable[str] = all_console_names) -> typing.Tuple[
str, bool, str]:
def get_intended_text(input_text: str, possible_answers) -> typing.Tuple[str, bool, str]:
picks = fuzzy_process.extract(input_text, possible_answers, limit=2)
if len(picks) > 1:
dif = picks[0][1] - picks[1][1]
@ -865,7 +869,8 @@ class ClientMessageProcessor(CommonCommandProcessor):
def _cmd_getitem(self, item_name: str) -> bool:
"""Cheat in an item, if it is enabled on this server"""
if self.ctx.item_cheat:
item_name, usable, response = get_intended_text(item_name, Items.item_table.keys())
item_name, usable, response = get_intended_text(item_name,
proxy_worlds[self.ctx.games[self.client.slot]].item_names)
if usable:
new_item = NetworkItem(Items.item_table[item_name][2], -1, self.client.slot)
get_received_items(self.ctx, self.client.team, self.client.slot).append(new_item)
@ -1224,17 +1229,16 @@ class ServerCommandProcessor(CommonCommandProcessor):
"""Sends an item to the specified player"""
seeked_player, usable, response = get_intended_text(player_name, self.ctx.player_names.values())
if usable:
team, slot = self.ctx.player_name_lookup[seeked_player]
item = " ".join(item_name)
item, usable, response = get_intended_text(item, all_items)
item, usable, response = get_intended_text(item, proxy_worlds[self.ctx.games[slot]].item_names)
if usable:
for client in self.ctx.endpoints:
if client.name == seeked_player:
new_item = NetworkItem(lookup_any_item_name_to_id[item], -1, 0)
get_received_items(self.ctx, client.team, client.slot).append(new_item)
self.ctx.notify_all('Cheat console: sending "' + item + '" to ' +
self.ctx.get_aliased_name(client.team, client.slot))
send_new_items(self.ctx)
return True
new_item = NetworkItem(lookup_any_item_name_to_id[item], -1, 0)
get_received_items(self.ctx, team, slot).append(new_item)
self.ctx.notify_all('Cheat console: sending "' + item + '" to ' +
self.ctx.get_aliased_name(team, slot))
send_new_items(self.ctx)
return True
else:
self.output(response)
return False
@ -1249,7 +1253,7 @@ class ServerCommandProcessor(CommonCommandProcessor):
for (team, slot), name in self.ctx.player_names.items():
if name == seeked_player:
item = " ".join(item_or_location)
item, usable, response = get_intended_text(item)
item, usable, response = get_intended_text(item, all_console_names)
if usable:
if item in Items.item_name_groups:
hints = []