Skip to content

Commit

Permalink
v1.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesbrq committed Jan 6, 2025
1 parent bdddc2f commit 1b6e42c
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 98 deletions.
177 changes: 85 additions & 92 deletions GauntletLegendsClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,10 @@ async def read(self, message: str) -> Optional[bytes]:
self.send(message)
try:
response = await asyncio.wait_for(asyncio.get_event_loop().sock_recv(self.socket, 30000), 1.0)
data = response.decode().split(" ")
data = response.decode().strip("\n").split(" ")
b = b""
for s in data[2:]:
if "-1" in s:
logger.info("-1 response")
raise Exception("Client tried to read from an invalid address or ROM is not open.")
b += bytes.fromhex(s)
return b
Expand Down Expand Up @@ -423,7 +422,7 @@ async def inv_update(self, name: str, count: int, one=None):
item.count = count
elif "Health" in name:
max_health = await self.item_from_name("Max", player)
item.count = min(max(item.count + count, 0), max_health.count)
item.count = min(max(item.count + count, 1), max_health.count)
elif "Runestone" in name or "Mirror" in name or "Obelisk" in name:
item.count |= count
else:
Expand All @@ -447,7 +446,9 @@ async def inv_refactor(self, new=None, one=None):
self.inventory[player] += [new]
else:
self.inventory[one] += [new]
for player in range(self.players):

players_to_check = range(self.players) if one is None else [one]
for player in players_to_check:
for i, item in enumerate(self.inventory[player]):
if item.name is not None:
if "Potion" in item.name and item.count != 0:
Expand Down Expand Up @@ -533,6 +534,7 @@ def on_package(self, cmd: str, args: dict):
self.slot = args["slot"]
self.glslotdata = args["slot_data"]
self.players = self.glslotdata["players"]
self.deathlink_enabled = self.glslotdata["death_link"]
self.var_reset()
logger.info(f"Players set to {self.players}.")
logger.info("If this is incorrect, Use /players to set the number of people playing locally.")
Expand Down Expand Up @@ -628,87 +630,81 @@ async def scale(self):

# Prepare locations that are going to be in the currently loading level
async def scout_locations(self, ctx: "GauntletLegendsContext") -> None:
level = await self.read_level()
if level in boss_level:
for i in range(4):
self.socket.send(
message_format(
WRITE,
param_format(
BOSS_ADDR + (0x10 * i), bytes([self.glslotdata["shards"][i][1], 0x0, self.glslotdata["shards"][i][0]]),
try:
level = await self.read_level()
if level in boss_level:
for i in range(4):
self.socket.send(
message_format(
WRITE,
param_format(
BOSS_ADDR + (0x10 * i), bytes([self.glslotdata["shards"][i][1], 0x0, self.glslotdata["shards"][i][0]]),
),
),
),
)
if self.movement != 0x12:
level = [0x1, 0xF]
self.current_level = level
players = await self.active_players()
player_level = await self.player_level()
if self.clear_counts.get(str(level), 0) != 0:
self.difficulty = min(players + (min(player_level // vanilla[level[1]], 3)), 4)
else:
self.difficulty = players
_id = level[0]
if level[1] == 1:
_id = castle_id.index(level[0]) + 1
raw_locations = []
for location in [location for location in level_locations.get((level[1] << 4) + _id, []) if self.difficulty >= location.difficulty]:
if "Chest" in location.name:
if self.glslotdata["chests"]:
raw_locations += [location]
elif "Barrel" in location.name and "Barrel of Gold" not in location.name:
if self.glslotdata["barrels"]:
)
if self.movement != 0x12:
level = [0x1, 0xF]
self.current_level = level
players = await self.active_players()
player_level = await self.player_level()
if self.clear_counts.get(str(level), 0) != 0:
self.difficulty = min(players + (min(player_level // vanilla[level[1]], 3)), 4)
else:
self.difficulty = players
_id = level[0]
if level[1] == 1:
_id = castle_id.index(level[0]) + 1
raw_locations = []
for location in [location for location in level_locations.get((level[1] << 4) + _id, []) if min(self.difficulty, self.glslotdata["max"]) >= location.difficulty]:
if "Chest" in location.name:
if self.glslotdata["chests"]:
raw_locations += [location]
elif "Barrel" in location.name and "Barrel of Gold" not in location.name:
if self.glslotdata["barrels"]:
raw_locations += [location]
elif "Mirror" not in location.name:
raw_locations += [location]
elif "Mirror" not in location.name:
raw_locations += [location]
await ctx.send_msgs(
[
{
"cmd": "LocationScouts",
"locations": [
location.id
for location in [location for location in raw_locations if min(self.difficulty, self.glslotdata["max"]) >= location.difficulty]
if len(raw_locations) > 0:
await ctx.send_msgs(
[
{
"cmd": "LocationScouts",
"locations": [location.id for location in raw_locations],
"create_as_hint": 0,
},
],
"create_as_hint": 0,
},
],
)
while len(self.location_scouts) == 0:
await asyncio.sleep(0.1)
self.obelisks = [
item
for item in self.location_scouts
if "Obelisk" in items_by_id.get(item.item, ItemData(0, "", ItemClassification.filler)).item_name
and item.player == self.slot
]
self.useful = [
item
for item in self.location_scouts
if "Obelisk" not in items_by_id.get(item.item, ItemData(0, "", ItemClassification.filler)).item_name
and (items_by_id.get(item.item, ItemData(0, "", ItemClassification.filler)).progression == ItemClassification.useful
or items_by_id.get(item.item, ItemData(0, "", ItemClassification.filler)).progression == ItemClassification.progression)
and item.player == self.slot
]
self.obelisk_locations = [
location for location in raw_locations if location.id in [item.location for item in self.obelisks]
]
self.item_locations = [
location for location in raw_locations
if ("Chest" not in location.name
and ("Barrel" not in location.name or "Barrel of Gold" in location.name))
and location not in self.obelisk_locations
or location.id in [item.location for item in self.useful]
]
logger.info(f"Item Locations: {len(self.item_locations)}")
self.chest_locations = [
location for location in raw_locations
if location not in self.obelisk_locations and location not in self.item_locations]
logger.info(f"Chest Locations: {len(self.chest_locations)}")
max_value: int = self.glslotdata['max']
logger.info(f"Items: {len(self.item_locations)} Chests: {len(self.chest_locations)} Obelisks: {len(self.obelisk_locations)}")
logger.info(
f"Locations: {len([location for location in self.obelisk_locations + self.item_locations + self.chest_locations if location.difficulty <= max_value and location.id not in self.locations_checked])} Difficulty: { max_value if self.glslotdata['instant_max'] else self.difficulty}",
)
)
while len(self.location_scouts) == 0:
await asyncio.sleep(0.1)
self.obelisks = [
item
for item in self.location_scouts
if "Obelisk" in items_by_id.get(item.item, ItemData(0, "", ItemClassification.filler)).item_name
and item.player == self.slot
]
self.useful = [
item
for item in self.location_scouts
if "Obelisk" not in items_by_id.get(item.item, ItemData(0, "", ItemClassification.filler)).item_name
and (items_by_id.get(item.item, ItemData(0, "", ItemClassification.filler)).progression == ItemClassification.useful
or items_by_id.get(item.item, ItemData(0, "", ItemClassification.filler)).progression == ItemClassification.progression)
and item.player == self.slot
]
self.obelisk_locations = [
location for location in raw_locations if location.id in [item.location for item in self.obelisks]
]
self.item_locations = [
location for location in raw_locations
if ("Chest" not in location.name
and ("Barrel" not in location.name or "Barrel of Gold" in location.name)
and location not in self.obelisk_locations)
or location.id in [item.location for item in self.useful]
]
self.chest_locations = [
location for location in raw_locations
if location not in self.obelisk_locations and location not in self.item_locations]
except Exception:
logger.error(traceback.format_exc())

# Compare values of loaded objects to see if they have been collected
# Sends locations out to server based on object lists read in obj_read()
Expand Down Expand Up @@ -812,6 +808,7 @@ def var_reset(self):
self.chest_objects = []
self.obelisk_locations = []
self.obelisks = []
self.useful = []
self.item_objects_init = []
self.chest_objects_init = []
self.in_game = False
Expand Down Expand Up @@ -898,6 +895,10 @@ async def gl_sync_task(ctx: GauntletLegendsContext):
},
],
)
bitwise = await ctx.inv_bitwise("Hell", 0x100, 0)
if not ctx.finished_game and bitwise:
await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}])
ctx.finished_game = True
if ctx.limbo:
limbo = await ctx.limbo_check(0x78)
if limbo:
Expand All @@ -923,14 +924,13 @@ async def gl_sync_task(ctx: GauntletLegendsContext):
ctx.in_portal = False
ctx.init_refactor = False
if not ctx.scaled:
logger.info("Scaling level...")
await asyncio.sleep(0.2)
await ctx.scale()
ctx.in_game = not await ctx.check_loading()
loading = await ctx.check_loading()
ctx.in_game = not loading
if ctx.in_game:
ctx.level_loading = False
if not ctx.objects_loaded:
logger.info("Loading Objects...")
await ctx.load_objects(ctx)
await asyncio.sleep(1)
status = await ctx.level_status(ctx)
Expand Down Expand Up @@ -959,27 +959,20 @@ async def gl_sync_task(ctx: GauntletLegendsContext):
if len(checking) > 0:
ctx.locations_checked += checking
await ctx.send_msgs([{"cmd": "LocationChecks", "locations": checking}])
bitwise = await ctx.inv_bitwise("Hell", 0x100, 0)
if not ctx.finished_game and bitwise:
await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}])
ctx.finished_game = True
await asyncio.sleep(0.1)
except TimeoutError:
logger.info("Connection Timed Out, Reconnecting")
ctx.var_reset()
ctx.socket = RetroSocket()
ctx.retro_connected = False
await asyncio.sleep(2)
except ConnectionResetError:
logger.info("Connection Lost, Reconnecting")
ctx.var_reset()
ctx.socket = RetroSocket()
ctx.retro_connected = False
await asyncio.sleep(2)
except Exception as e:
logger.error(f"Unknown Error Occurred: {e}")
logger.info(traceback.format_exc())
ctx.var_reset()
ctx.socket = RetroSocket()
ctx.retro_connected = False
await asyncio.sleep(2)
Expand Down
4 changes: 2 additions & 2 deletions Items.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ class GLItem(Item):
"Meat": 100,
"Gold": 150,
"Anti-Death Halo": 30,
"Death": 75,
"Poison Fruit": 75,
"Death": 50,
"Poison Fruit": 50,
}

item_table: typing.Dict[str, ItemData] = {item.item_name: item for item in item_list}
Expand Down
2 changes: 0 additions & 2 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ class GauntletLegendsWorld(World):
settings: typing.ClassVar[GLSettings]
item_name_to_id = {name: data.code for name, data in item_table.items()}
location_name_to_id = {loc_data.name: loc_data.id for loc_data in all_locations}
required_client_version = (0, 5, 0)
crc32: str = None
death: List[Item] = []

disabled_locations: typing.List[LocationData]
Expand Down
1 change: 1 addition & 0 deletions docs/en_Gauntlet Legends.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Items that can be placed into locations:
- Runestones
- Obelisks
- Mirror Shards
- Death

## What does another world's item look like in Gauntlet Legends?

Expand Down
4 changes: 2 additions & 2 deletions docs/setup_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ Double-click on your `.apgl` file to start the ROM patch process. Once the proce
This game uses its own custom client, named Gauntlet Legends Client.
Retroarch is only emulator this client will accept.

Once both the client and the emulator are started, you must connect them. Once your ROM is open in Retroach,
as long as the client is open they will be connected to eachother.
Once both the client and the emulator are started, you must connect them. Once your ROM is open in Retroarch,
as long as the client is open they will be connected to each other.

To connect the client to the multiserver simply put `<address>:<port>` on the textfield on top and press enter (if the
server uses password, type in the bottom textfield `/connect <address>:<port> [password]`).
Expand Down

0 comments on commit 1b6e42c

Please sign in to comment.