Kingdom Hearts: Adding a bunch of new features (#5078)
* Change vanilla_emblem_pieces to randomize_emblem_pieces * Add jungle slider and starting tools options * Update option name and add preset * GICU changes * unnecessary * Update Options.py * Fix has_all * Update Options.py * Update Options.py * Some potenitial logic changes * Oops * Oops 2 * Cups choice options * typos * Logic tweaks * Ice Titan and Superboss changes * Suggested change and one more * Updating some other option descriptions for clarity/typos * Update Locations.py * commit * SYNTHESIS * commit * commit * commit * Add command to change communication path I'm not a python programmer, so do excuse the code etiquette. This aims to allow Linux users to communicate to their proton directory. * commit * commit * commit * commit * commit * commit * commit * commit * Update Client.py * Update Locations.py * Update Regions.py * commit * commit * commit * Update Rules.py * commit * commit * commit * commit logic changes and linux fix from other branch * commit * commit * Update __init__.py * Update Rules.py * commit * commit * commit * commit * add starting accessory setting * fix starting accessories bug * Update Locations.py * commit * add ap cost rando * fix some problem locations * add raft materials * Update Client.py * OK WORK THIS TIME PLEASE * Corrected typos * setting up for logic difficulty * commit 1 * commit 2 * commit 3 * minor error fix * some logic changes and fixed some typos * tweaks * commit * SYNTHESIS * commit * commit * commit * commit * commit * commit * commit * commit * commit * commit * commit * Update Client.py * Update Locations.py * Update Regions.py * commit * commit * commit * Update Rules.py * commit * commit * commit * commit logic changes and linux fix from other branch * commit * commit * Update __init__.py * Update Rules.py * commit * commit * commit * commit * add starting accessory setting * fix starting accessories bug * Update Locations.py * commit * add ap cost rando * fix some problem locations * add raft materials * Update Client.py * cleanup * commit 4 * tweaks 2 * tweaks 3 * Reset * Update __init__.py * Change vanilla_emblem_pieces to randomize_emblem_pieces * Add jungle slider and starting tools options * unnecessary * Vanilla Puppies Part 1 The easy part * Update __init__.py I'm not certain this is the exact right chest for Tea Party Garden, Waterfall Cavern, HT Cemetery, or Neverland Hold but logically it's the same. Will do a test run later and fix if need be * Vanilla Puppies Part 3 Wrong toggle cause I just copied over Emblem Pieces oops * Vanilla Puppies Part 4 Forgor commented out code * Vanilla Puppies Part 5 I now realize how this works and that what I had before was redundant * Update __init__.py Learning much about strings * cleanup * Update __init__.py Only missed one! * Update option name and add preset * GICU changes * Update Options.py * Fix has_all * Update Options.py * Update Options.py * Cups choice options * typos * Ice Titan and Superboss changes * Some potenitial logic changes * Oops * Oops 2 * Logic tweaks * Suggested change and one more * Updating some other option descriptions for clarity/typos * Update Locations.py * Add command to change communication path I'm not a python programmer, so do excuse the code etiquette. This aims to allow Linux users to communicate to their proton directory. * Moving over changes from REVAMP * whoops * Fix patch files on the website * Update test_goal.py * commit * Update worlds/kh1/__init__.py Co-authored-by: Scipio Wright <scipiowright@gmail.com> * change some default options * Missed a condition * let's try that * Update Options.py * unnecessary sub check * Some more cleanup * tuples * add icon * merge cleanup * merge cleanup 2 * merge clean up 3 * Update Data.py * Fix cups option * commit * Update Rules.py * Update Rules.py * phantom tweak * review commit * minor fixes * review 2 * minor typo fix * minor logic tweak * Update Client.py * Update __init__.py * Update Rules.py * Olympus Cup fixes * Update Options.py * even MORE tweaks * commit * Update Options.py * Update has_x_worlds * Update Rules.py * commit * Update Options.py * Update Options.py * Update Options.py * tweak 5 * Add Stacking Key Items and Halloween Town Key Item Bundle * Update worlds/kh1/Rules.py Co-authored-by: Scipio Wright <scipiowright@gmail.com> * Update Rules.py * commit * Update worlds/kh1/__init__.py Co-authored-by: Scipio Wright <scipiowright@gmail.com> * Update __init__.py * Update __init__.py * whoops * Update Rules.py * Update Rules.py * Fix documentation styling * Clean up option help text * Reordering options so they're consistent and fixing a logic bug when EOTW Unlock is item but door is emblems * Make have x world logic consider if the player has HAW on or not * Fix Atlantica beginner logic things, vanilla keyblade stats being broken, and some behind boss locations * Fix vanilla puppy option * hotfix for crabclaw logic * Fix defaults and some boss locations * Fix server spam * Remove 3 High Jump Item Workshop Logic, small client changes * Updates for PR --------- Co-authored-by: esutley <ecsutley@gmail.com> Co-authored-by: Goblin God <37878138+esutley@users.noreply.github.com> Co-authored-by: River Buizel <4911928+rocket0634@users.noreply.github.com> Co-authored-by: omnises <OmnisGamers@gmail.com> Co-authored-by: Omnises Nihilis <38057571+Omnises@users.noreply.github.com> Co-authored-by: Scipio Wright <scipiowright@gmail.com>
This commit is contained in:
@@ -13,8 +13,6 @@ import ModuleUpdate
|
||||
ModuleUpdate.update()
|
||||
|
||||
import Utils
|
||||
death_link = False
|
||||
item_num = 1
|
||||
|
||||
logger = logging.getLogger("Client")
|
||||
|
||||
@@ -34,62 +32,57 @@ class KH1ClientCommandProcessor(ClientCommandProcessor):
|
||||
def __init__(self, ctx):
|
||||
super().__init__(ctx)
|
||||
|
||||
def _cmd_slot_data(self):
|
||||
"""Prints slot data settings for the connected seed"""
|
||||
for key in self.ctx.slot_data.keys():
|
||||
if key not in ["remote_location_ids", "synthesis_item_name_byte_arrays"]:
|
||||
self.output(str(key) + ": " + str(self.ctx.slot_data[key]))
|
||||
|
||||
def _cmd_deathlink(self):
|
||||
"""Toggles Deathlink"""
|
||||
global death_link
|
||||
if death_link:
|
||||
death_link = False
|
||||
self.output(f"Death Link turned off")
|
||||
else:
|
||||
death_link = True
|
||||
self.output(f"Death Link turned on")
|
||||
|
||||
def _cmd_goal(self):
|
||||
"""Prints goal setting"""
|
||||
if "goal" in self.ctx.slot_data.keys():
|
||||
self.output(str(self.ctx.slot_data["goal"]))
|
||||
else:
|
||||
self.output("Unknown")
|
||||
|
||||
def _cmd_eotw_unlock(self):
|
||||
"""Prints End of the World Unlock setting"""
|
||||
if "required_reports_door" in self.ctx.slot_data.keys():
|
||||
if self.ctx.slot_data["required_reports_door"] > 13:
|
||||
self.output("Item")
|
||||
"""If your Death Link setting is set to "Toggle", use this command to turn Death Link on and off."""
|
||||
if "death_link" in self.ctx.slot_data.keys():
|
||||
if self.ctx.slot_data["death_link"] == "toggle":
|
||||
if self.ctx.death_link:
|
||||
self.ctx.death_link = False
|
||||
self.output(f"Death Link turned off")
|
||||
else:
|
||||
self.ctx.death_link = True
|
||||
self.output(f"Death Link turned on")
|
||||
else:
|
||||
self.output(str(self.ctx.slot_data["required_reports_eotw"]) + " reports")
|
||||
self.output(f"'death_link' is not set to 'toggle' for this seed.")
|
||||
self.output(f"'death_link' = " + str(self.ctx.slot_data["death_link"]))
|
||||
else:
|
||||
self.output("Unknown")
|
||||
self.output(f"No 'death_link' in slot_data keys. You probably aren't connected or are playing an older seed.")
|
||||
|
||||
def _cmd_door_unlock(self):
|
||||
"""Prints Final Rest Door Unlock setting"""
|
||||
if "door" in self.ctx.slot_data.keys():
|
||||
if self.ctx.slot_data["door"] == "reports":
|
||||
self.output(str(self.ctx.slot_data["required_reports_door"]) + " reports")
|
||||
else:
|
||||
self.output(str(self.ctx.slot_data["door"]))
|
||||
def _cmd_communication_path(self):
|
||||
"""Opens a file browser to allow Linux users to manually set their %LOCALAPPDATA% path"""
|
||||
directory = Utils.open_directory("Select %LOCALAPPDATA% dir", "~/.local/share/Steam/steamapps/compatdata/2552430/pfx/drive_c/users/steamuser/AppData/Local")
|
||||
if directory:
|
||||
directory += "/KH1FM"
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
self.ctx.game_communication_path = directory
|
||||
else:
|
||||
self.output("Unknown")
|
||||
|
||||
def _cmd_advanced_logic(self):
|
||||
"""Prints advanced logic setting"""
|
||||
if "advanced_logic" in self.ctx.slot_data.keys():
|
||||
self.output(str(self.ctx.slot_data["advanced_logic"]))
|
||||
else:
|
||||
self.output("Unknown")
|
||||
self.output(self.ctx.game_communication_path)
|
||||
|
||||
class KH1Context(CommonContext):
|
||||
command_processor: int = KH1ClientCommandProcessor
|
||||
game = "Kingdom Hearts"
|
||||
items_handling = 0b111 # full remote
|
||||
items_handling = 0b011 # full remote except start inventory
|
||||
|
||||
def __init__(self, server_address, password):
|
||||
super(KH1Context, self).__init__(server_address, password)
|
||||
self.send_index: int = 0
|
||||
self.syncing = False
|
||||
self.awaiting_bridge = False
|
||||
self.hinted_synth_location_ids = False
|
||||
self.slot_data = {}
|
||||
self.hinted_location_ids: list[int] = []
|
||||
self.slot_data: dict = {}
|
||||
|
||||
# Moved globals into instance attributes
|
||||
self.death_link: bool = False
|
||||
self.item_num: int = 1
|
||||
self.remote_location_ids: list[int] = []
|
||||
|
||||
# self.game_communication_path: files go in this path to pass data between us and the actual game
|
||||
if "localappdata" in os.environ:
|
||||
self.game_communication_path = os.path.expandvars(r"%localappdata%/KH1FM")
|
||||
@@ -103,6 +96,10 @@ class KH1Context(CommonContext):
|
||||
os.remove(root+"/"+file)
|
||||
|
||||
async def server_auth(self, password_requested: bool = False):
|
||||
for root, dirs, files in os.walk(self.game_communication_path):
|
||||
for file in files:
|
||||
if file.find("obtain") <= -1:
|
||||
os.remove(root+"/"+file)
|
||||
if password_requested and not self.password:
|
||||
await super(KH1Context, self).server_auth(password_requested)
|
||||
await self.get_username()
|
||||
@@ -114,8 +111,7 @@ class KH1Context(CommonContext):
|
||||
for file in files:
|
||||
if file.find("obtain") <= -1:
|
||||
os.remove(root + "/" + file)
|
||||
global item_num
|
||||
item_num = 1
|
||||
self.item_num = 1
|
||||
|
||||
@property
|
||||
def endpoints(self):
|
||||
@@ -130,8 +126,7 @@ class KH1Context(CommonContext):
|
||||
for file in files:
|
||||
if file.find("obtain") <= -1:
|
||||
os.remove(root+"/"+file)
|
||||
global item_num
|
||||
item_num = 1
|
||||
self.item_num = 1
|
||||
|
||||
def on_package(self, cmd: str, args: dict):
|
||||
if cmd in {"Connected"}:
|
||||
@@ -142,38 +137,34 @@ class KH1Context(CommonContext):
|
||||
with open(os.path.join(self.game_communication_path, filename), 'w') as f:
|
||||
f.close()
|
||||
|
||||
#Handle Slot Data
|
||||
# Handle Slot Data
|
||||
self.slot_data = args['slot_data']
|
||||
for key in list(args['slot_data'].keys()):
|
||||
with open(os.path.join(self.game_communication_path, key + ".cfg"), 'w') as f:
|
||||
f.write(str(args['slot_data'][key]))
|
||||
f.close()
|
||||
|
||||
###Support Legacy Games
|
||||
if "Required Reports" in list(args['slot_data'].keys()) and "required_reports_eotw" not in list(args['slot_data'].keys()):
|
||||
reports_required = args['slot_data']["Required Reports"]
|
||||
with open(os.path.join(self.game_communication_path, "required_reports.cfg"), 'w') as f:
|
||||
f.write(str(reports_required))
|
||||
f.close()
|
||||
###End Support Legacy Games
|
||||
|
||||
#End Handle Slot Data
|
||||
if key == "remote_location_ids":
|
||||
self.remote_location_ids = args['slot_data'][key]
|
||||
if key == "death_link":
|
||||
if args['slot_data']["death_link"] != "off":
|
||||
self.death_link = True
|
||||
# End Handle Slot Data
|
||||
|
||||
if cmd in {"ReceivedItems"}:
|
||||
start_index = args["index"]
|
||||
if start_index != len(self.items_received):
|
||||
global item_num
|
||||
for item in args['items']:
|
||||
found = False
|
||||
item_filename = f"AP_{str(item_num)}.item"
|
||||
item_filename = f"AP_{str(self.item_num)}.item"
|
||||
for filename in os.listdir(self.game_communication_path):
|
||||
if filename == item_filename:
|
||||
found = True
|
||||
if not found:
|
||||
with open(os.path.join(self.game_communication_path, item_filename), 'w') as f:
|
||||
f.write(str(NetworkItem(*item).item) + "\n" + str(NetworkItem(*item).location) + "\n" + str(NetworkItem(*item).player))
|
||||
f.close()
|
||||
item_num = item_num + 1
|
||||
if (NetworkItem(*item).player == self.slot and (NetworkItem(*item).location in self.remote_location_ids) or (NetworkItem(*item).location < 0)) or NetworkItem(*item).player != self.slot:
|
||||
with open(os.path.join(self.game_communication_path, item_filename), 'w') as f:
|
||||
f.write(str(NetworkItem(*item).item) + "\n" + str(NetworkItem(*item).location) + "\n" + str(NetworkItem(*item).player))
|
||||
f.close()
|
||||
self.item_num += 1
|
||||
|
||||
if cmd in {"RoomUpdate"}:
|
||||
if "checked_locations" in args:
|
||||
@@ -186,21 +177,39 @@ class KH1Context(CommonContext):
|
||||
if args["type"] == "ItemSend":
|
||||
item = args["item"]
|
||||
networkItem = NetworkItem(*item)
|
||||
recieverID = args["receiving"]
|
||||
receiverID = args["receiving"]
|
||||
senderID = networkItem.player
|
||||
locationID = networkItem.location
|
||||
if recieverID != self.slot and senderID == self.slot:
|
||||
itemName = self.item_names.lookup_in_slot(networkItem.item, recieverID)
|
||||
if receiverID == self.slot or senderID == self.slot:
|
||||
itemName = self.item_names.lookup_in_slot(networkItem.item, receiverID)[:20]
|
||||
itemCategory = networkItem.flags
|
||||
recieverName = self.player_names[recieverID]
|
||||
filename = "sent"
|
||||
with open(os.path.join(self.game_communication_path, filename), 'w') as f:
|
||||
f.write(
|
||||
re.sub('[^A-Za-z0-9 ]+', '',str(itemName))[:15] + "\n"
|
||||
+ re.sub('[^A-Za-z0-9 ]+', '',str(recieverName))[:6] + "\n"
|
||||
+ str(itemCategory) + "\n"
|
||||
+ str(locationID))
|
||||
f.close()
|
||||
receiverName = self.player_names[receiverID][:20]
|
||||
senderName = self.player_names[senderID][:20]
|
||||
message = ""
|
||||
if receiverID == self.slot and receiverID != senderID: # Item received from someone else
|
||||
message = "From " + senderName + "\n" + itemName
|
||||
elif senderID == self.slot and receiverID != senderID: # Item sent to someone else
|
||||
message = itemName + "\nTo " + receiverName
|
||||
elif locationID in self.remote_location_ids: # Found a remote item
|
||||
message = itemName
|
||||
filename = "msg"
|
||||
if message != "":
|
||||
if not os.path.exists(self.game_communication_path + "/" + filename):
|
||||
with open(os.path.join(self.game_communication_path, filename), 'w') as f:
|
||||
f.write(message)
|
||||
f.close()
|
||||
if args["type"] == "ItemCheat":
|
||||
item = args["item"]
|
||||
networkItem = NetworkItem(*item)
|
||||
receiverID = args["receiving"]
|
||||
if receiverID == self.slot:
|
||||
itemName = self.item_names.lookup_in_slot(networkItem.item, receiverID)[:20]
|
||||
filename = "msg"
|
||||
message = "Received " + itemName + "\nfrom server"
|
||||
if not os.path.exists(self.game_communication_path + "/" + filename):
|
||||
with open(os.path.join(self.game_communication_path, filename), 'w') as f:
|
||||
f.write(message)
|
||||
f.close()
|
||||
|
||||
def on_deathlink(self, data: dict[str, object]):
|
||||
self.last_death_link = max(data["time"], self.last_death_link)
|
||||
@@ -230,12 +239,11 @@ class KH1Context(CommonContext):
|
||||
async def game_watcher(ctx: KH1Context):
|
||||
from .Locations import lookup_id_to_name
|
||||
while not ctx.exit_event.is_set():
|
||||
global death_link
|
||||
if death_link and "DeathLink" not in ctx.tags:
|
||||
await ctx.update_death_link(death_link)
|
||||
if not death_link and "DeathLink" in ctx.tags:
|
||||
await ctx.update_death_link(death_link)
|
||||
if ctx.syncing == True:
|
||||
if ctx.death_link and "DeathLink" not in ctx.tags:
|
||||
await ctx.update_death_link(ctx.death_link)
|
||||
if not ctx.death_link and "DeathLink" in ctx.tags:
|
||||
await ctx.update_death_link(ctx.death_link)
|
||||
if ctx.syncing is True:
|
||||
sync_msg = [{'cmd': 'Sync'}]
|
||||
if ctx.locations_checked:
|
||||
sync_msg.append({"cmd": "LocationChecks", "locations": list(ctx.locations_checked)})
|
||||
@@ -256,17 +264,17 @@ async def game_watcher(ctx: KH1Context):
|
||||
if st != "nil":
|
||||
if timegm(time.strptime(st, '%Y%m%d%H%M%S')) > ctx.last_death_link and int(time.time()) % int(timegm(time.strptime(st, '%Y%m%d%H%M%S'))) < 10:
|
||||
await ctx.send_death(death_text = "Sora was defeated!")
|
||||
if file.find("insynthshop") > -1:
|
||||
if not ctx.hinted_synth_location_ids:
|
||||
if file.find("hint") > -1:
|
||||
hint_location_id = int(file.split("hint", -1)[1])
|
||||
if hint_location_id not in ctx.hinted_location_ids:
|
||||
await ctx.send_msgs([{
|
||||
"cmd": "LocationScouts",
|
||||
"locations": [2656401,2656402,2656403,2656404,2656405,2656406],
|
||||
"locations": [hint_location_id],
|
||||
"create_as_hint": 2
|
||||
}])
|
||||
ctx.hinted_synth_location_ids = True
|
||||
ctx.hinted_location_ids.append(hint_location_id)
|
||||
ctx.locations_checked = sending
|
||||
message = [{"cmd": 'LocationChecks', "locations": sending}]
|
||||
await ctx.send_msgs(message)
|
||||
await ctx.check_locations(sending)
|
||||
if not ctx.finished_game and victory:
|
||||
await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}])
|
||||
ctx.finished_game = True
|
||||
|
||||
Reference in New Issue
Block a user