mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Fully implement ringlink
This commit is contained in:
@@ -3,6 +3,8 @@ from typing import TYPE_CHECKING
|
|||||||
import asyncio
|
import asyncio
|
||||||
import NetUtils
|
import NetUtils
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
import Utils
|
||||||
from .Locations import grinch_locations, GrinchLocation
|
from .Locations import grinch_locations, GrinchLocation
|
||||||
from .Items import ALL_ITEMS_TABLE, MISSION_ITEMS_TABLE, GADGETS_TABLE, KEYS_TABLE, GrinchItemData #, SLEIGH_PARTS_TABLE
|
from .Items import ALL_ITEMS_TABLE, MISSION_ITEMS_TABLE, GADGETS_TABLE, KEYS_TABLE, GrinchItemData #, SLEIGH_PARTS_TABLE
|
||||||
import worlds._bizhawk as bizhawk
|
import worlds._bizhawk as bizhawk
|
||||||
@@ -24,6 +26,10 @@ MAX_DEMO_MODE_CHECK = 30
|
|||||||
# List of Menu Map IDs
|
# List of Menu Map IDs
|
||||||
MENU_MAP_IDS: list[int] = [0x00, 0x02, 0x35, 0x36, 0x37]
|
MENU_MAP_IDS: list[int] = [0x00, 0x02, 0x35, 0x36, 0x37]
|
||||||
|
|
||||||
|
MAX_EGGS: int = 200
|
||||||
|
EGG_COUNT_ADDR: int = 0x010058
|
||||||
|
EGG_ADDR_BYTESIZE: int = 2
|
||||||
|
|
||||||
class GrinchClient(BizHawkClient):
|
class GrinchClient(BizHawkClient):
|
||||||
game = "The Grinch"
|
game = "The Grinch"
|
||||||
system = "PSX"
|
system = "PSX"
|
||||||
@@ -32,6 +38,7 @@ class GrinchClient(BizHawkClient):
|
|||||||
demo_mode_buffer = 0
|
demo_mode_buffer = 0
|
||||||
last_map_location = -1
|
last_map_location = -1
|
||||||
ingame_log = False
|
ingame_log = False
|
||||||
|
previous_egg_count: int = 0
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -71,7 +78,7 @@ class GrinchClient(BizHawkClient):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def on_package(self, ctx: "BizHawkClientContext", cmd: str, args: dict) -> None:
|
async def on_package(self, ctx: "BizHawkClientContext", cmd: str, args: dict) -> None:
|
||||||
from CommonClient import logger
|
from CommonClient import logger
|
||||||
super().on_package(ctx, cmd, args)
|
super().on_package(ctx, cmd, args)
|
||||||
match cmd:
|
match cmd:
|
||||||
@@ -79,9 +86,25 @@ class GrinchClient(BizHawkClient):
|
|||||||
self.loc_unlimited_eggs = bool(ctx.slot_data["give_unlimited_eggs"])
|
self.loc_unlimited_eggs = bool(ctx.slot_data["give_unlimited_eggs"])
|
||||||
logger.info("You are now connected to the client. "+
|
logger.info("You are now connected to the client. "+
|
||||||
"There may be a slight delay to check you are not in demo mode before locations start to send.")
|
"There may be a slight delay to check you are not in demo mode before locations start to send.")
|
||||||
# tags = args.get("tags", [])
|
|
||||||
# if "RingLink" in tags:
|
ring_link_enabled = bool(ctx.slot_data["ring_link"])
|
||||||
# ring_link_input(self, args["data"])
|
|
||||||
|
tags = copy.deepcopy(ctx.tags)
|
||||||
|
if ring_link_enabled:
|
||||||
|
Utils.async_start(self.ring_link_output(ctx), name="EggLink")
|
||||||
|
ctx.tags.add("RingLink")
|
||||||
|
else:
|
||||||
|
ctx.tags -= { "RingLink" }
|
||||||
|
|
||||||
|
if tags != ctx.tags:
|
||||||
|
await ctx.send_msgs([{"cmd": "ConnectUpdate", "tags": ctx.tags}])
|
||||||
|
|
||||||
|
case "Bounced":
|
||||||
|
if "tags" not in args:
|
||||||
|
return
|
||||||
|
|
||||||
|
if "RingLink" in ctx.tags and "RingLink" in args["tags"] and args["data"]["source"] != ctx.player_names[ctx.slot]:
|
||||||
|
await self.ring_link_input(args["data"]["amount"], ctx)
|
||||||
|
|
||||||
async def set_auth(self, ctx: "BizHawkClientContext") -> None:
|
async def set_auth(self, ctx: "BizHawkClientContext") -> None:
|
||||||
await ctx.get_username()
|
await ctx.get_username()
|
||||||
@@ -178,8 +201,7 @@ class GrinchClient(BizHawkClient):
|
|||||||
|
|
||||||
# Write the updated value back into RAM
|
# Write the updated value back into RAM
|
||||||
await self.update_and_validate_address(ctx, addr_to_update.ram_address, current_ram_address_value, addr_to_update.bit_size)
|
await self.update_and_validate_address(ctx, addr_to_update.ram_address, current_ram_address_value, addr_to_update.bit_size)
|
||||||
# await bizhawk.write(ctx.bizhawk_ctx, [(addr_to_update.ram_address,
|
|
||||||
# current_ram_address_value.to_bytes(addr_to_update.bit_size, "little"), "MainRAM")])
|
|
||||||
|
|
||||||
self.last_received_index += 1
|
self.last_received_index += 1
|
||||||
await self.update_and_validate_address(ctx, RECV_ITEM_ADDR, self.last_received_index, RECV_ITEM_BITSIZE)
|
await self.update_and_validate_address(ctx, RECV_ITEM_ADDR, self.last_received_index, RECV_ITEM_BITSIZE)
|
||||||
@@ -291,8 +313,7 @@ class GrinchClient(BizHawkClient):
|
|||||||
|
|
||||||
async def option_handler(self, ctx: "BizHawkClientContext"):
|
async def option_handler(self, ctx: "BizHawkClientContext"):
|
||||||
if self.loc_unlimited_eggs:
|
if self.loc_unlimited_eggs:
|
||||||
max_eggs: int = 200
|
await bizhawk.write(ctx.bizhawk_ctx, [(EGG_COUNT_ADDR, MAX_EGGS.to_bytes(2,"little"), "MainRAM")])
|
||||||
await bizhawk.write(ctx.bizhawk_ctx, [(0x010058, max_eggs.to_bytes(2,"little"), "MainRAM")])
|
|
||||||
|
|
||||||
async def update_and_validate_address(self, ctx: "BizHawkClientContext", address_to_validate: int, expected_value: int, byte_size: int):
|
async def update_and_validate_address(self, ctx: "BizHawkClientContext", address_to_validate: int, expected_value: int, byte_size: int):
|
||||||
await bizhawk.write(ctx.bizhawk_ctx, [(address_to_validate, expected_value.to_bytes(byte_size, "little"), "MainRAM")])
|
await bizhawk.write(ctx.bizhawk_ctx, [(address_to_validate, expected_value.to_bytes(byte_size, "little"), "MainRAM")])
|
||||||
@@ -302,38 +323,30 @@ class GrinchClient(BizHawkClient):
|
|||||||
return
|
return
|
||||||
raise Exception("Unable to update address as expected. Address: "+ str(address_to_validate)+"; Expected Value: "+str(expected_value))
|
raise Exception("Unable to update address as expected. Address: "+ str(address_to_validate)+"; Expected Value: "+str(expected_value))
|
||||||
|
|
||||||
# async def ring_link_output(self, ctx: "BizHawkClientContext", byte_size: int):
|
async def ring_link_output(self, ctx: "BizHawkClientContext"):
|
||||||
# bizhawk.seek(0x010058)
|
if not ctx.slot:
|
||||||
# byte_size = 2
|
return
|
||||||
# current_eggs = int.from_bytes(byte_size=2, byteorder="little")
|
try:
|
||||||
# difference = current_eggs - ctx.previous_eggs
|
current_egg_count = int.from_bytes(
|
||||||
# ctx.previous_eggs = current_eggs + ctx.ring_link_eggs
|
(await bizhawk.read(ctx.bizhawk_ctx, [(EGG_COUNT_ADDR, EGG_ADDR_BYTESIZE, "MainRAM")]))[0], "little")
|
||||||
#
|
|
||||||
# if difference != 0:
|
if (current_egg_count - self.previous_egg_count) != 0:
|
||||||
# # logger.info("got here with a difference of " + str(difference))
|
msg = {
|
||||||
# msg = {
|
"cmd": "Bounce",
|
||||||
# "cmd": "Bounce",
|
"data": {
|
||||||
# "slots": [ctx.slot],
|
"time": time.time(),
|
||||||
# "data": {
|
"source": ctx.player_names[ctx.slot],
|
||||||
# "time": time.time(),
|
"amount": current_egg_count - self.previous_egg_count
|
||||||
# "source": ctx.slot,
|
},
|
||||||
# "amount": difference
|
"tags": ["RingLink"]
|
||||||
# },
|
}
|
||||||
# "tags": ["RingLink"]
|
await ctx.send_msgs([msg])
|
||||||
# }
|
self.previous_egg_count = current_egg_count
|
||||||
# await ctx.send_msgs([msg])
|
except Exception as ex:
|
||||||
#
|
logger.error("While monitoring grinch's egg count ingame, an error occured. Details:"+ str(ex))
|
||||||
# # here write new ring value back into file
|
|
||||||
# bizhawk.seek(0x010058)
|
async def ring_link_input(self, egg_amount: int, ctx: "BizHawkClientContext"):
|
||||||
# if current_eggs + ctx.ring_link_eggs < 0:
|
current_egg_count = int.from_bytes(
|
||||||
# ctx.ring_link_eggs = -current_eggs
|
(await bizhawk.read(ctx.bizhawk_ctx, [(EGG_COUNT_ADDR, EGG_ADDR_BYTESIZE, "MainRAM")]))[0], "little")
|
||||||
# bizhawk.write(int(current_eggs + ctx.ring_link_eggs).to_bytes(byte_size=2, byteorder="little"))
|
current_egg_count = min(current_egg_count + egg_amount, MAX_EGGS)
|
||||||
# ctx.ring_link_eggs = 0
|
await self.update_and_validate_address(ctx, EGG_COUNT_ADDR, current_egg_count, EGG_ADDR_BYTESIZE)
|
||||||
#
|
|
||||||
# async def ring_link_input(self, data):
|
|
||||||
# amount = data["amount"]
|
|
||||||
# source = data["source"]
|
|
||||||
# if source == self.slot:
|
|
||||||
# return
|
|
||||||
# else:
|
|
||||||
# self.ring_link_eggs += amount
|
|
@@ -69,7 +69,7 @@ class UnlimitedEggs(Toggle):
|
|||||||
display_name = "Unlimited Rotten Eggs"
|
display_name = "Unlimited Rotten Eggs"
|
||||||
|
|
||||||
class RingLinkOption(Toggle):
|
class RingLinkOption(Toggle):
|
||||||
"""Whenever this is toggled, your ammo is linked with other ringlink-compatible games that also have this enabled. [NOT IMPLEMENTED]"""
|
"""Whenever this is toggled, your ammo is linked with other ringlink-compatible games that also have this enabled."""
|
||||||
|
|
||||||
class TrapLinkOption(Toggle):
|
class TrapLinkOption(Toggle):
|
||||||
"""If a trap is sent from Grinch, traps that are compatible with other games are triggered aswell. [NOT IMPLEMENTED]"""
|
"""If a trap is sent from Grinch, traps that are compatible with other games are triggered aswell. [NOT IMPLEMENTED]"""
|
||||||
|
@@ -8,6 +8,7 @@ from .Client import *
|
|||||||
from typing import ClassVar
|
from typing import ClassVar
|
||||||
|
|
||||||
from worlds.AutoWorld import World
|
from worlds.AutoWorld import World
|
||||||
|
import Options
|
||||||
|
|
||||||
from . import Options
|
from . import Options
|
||||||
from .Rules import access_rules_dict
|
from .Rules import access_rules_dict
|
||||||
@@ -28,7 +29,10 @@ class GrinchWorld(World):
|
|||||||
super(GrinchWorld, self).__init__(*args, **kwargs)
|
super(GrinchWorld, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def generate_early(self) -> None: #Special conditions changed before generation occurs
|
def generate_early(self) -> None: #Special conditions changed before generation occurs
|
||||||
pass
|
if self.options.ring_link == 1 and self.options.unlimited_eggs == 1:
|
||||||
|
raise Options.OptionError("Cannot enable both unlimited rotten eggs and ring links. You can only enable one of these at a time."+
|
||||||
|
f"The following player's YAML needs to be fixed: {self.player_name}")
|
||||||
|
|
||||||
|
|
||||||
def create_regions(self): #Generates all regions for the multiworld
|
def create_regions(self): #Generates all regions for the multiworld
|
||||||
for region_name in access_rules_dict.keys():
|
for region_name in access_rules_dict.keys():
|
||||||
|
Reference in New Issue
Block a user