mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-28 16:33:26 -07:00
Merge branch 'ArchipelagoMW:main' into new-options-api
This commit is contained in:
@@ -17,6 +17,12 @@
|
||||
color: "FFFFFF"
|
||||
<TabbedPanel>:
|
||||
tab_width: root.width / app.tab_count
|
||||
<TooltipLabel>:
|
||||
text_size: self.width, None
|
||||
size_hint_y: None
|
||||
height: self.texture_size[1]
|
||||
font_size: dp(20)
|
||||
markup: True
|
||||
<SelectableLabel>:
|
||||
canvas.before:
|
||||
Color:
|
||||
@@ -24,11 +30,6 @@
|
||||
Rectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
text_size: self.width, None
|
||||
size_hint_y: None
|
||||
height: self.texture_size[1]
|
||||
font_size: dp(20)
|
||||
markup: True
|
||||
<UILog>:
|
||||
messages: 1000 # amount of messages stored in client logs.
|
||||
cols: 1
|
||||
@@ -44,6 +45,70 @@
|
||||
height: self.minimum_height
|
||||
orientation: 'vertical'
|
||||
spacing: dp(3)
|
||||
<HintLabel>:
|
||||
canvas.before:
|
||||
Color:
|
||||
rgba: (.0, 0.9, .1, .3) if self.selected else (0.2, 0.2, 0.2, 1) if self.striped else (0.18, 0.18, 0.18, 1)
|
||||
Rectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
height: self.minimum_height
|
||||
receiving_text: "Receiving Player"
|
||||
item_text: "Item"
|
||||
finding_text: "Finding Player"
|
||||
location_text: "Location"
|
||||
entrance_text: "Entrance"
|
||||
found_text: "Found?"
|
||||
TooltipLabel:
|
||||
id: receiving
|
||||
text: root.receiving_text
|
||||
halign: 'center'
|
||||
valign: 'center'
|
||||
pos_hint: {"center_y": 0.5}
|
||||
TooltipLabel:
|
||||
id: item
|
||||
text: root.item_text
|
||||
halign: 'center'
|
||||
valign: 'center'
|
||||
pos_hint: {"center_y": 0.5}
|
||||
TooltipLabel:
|
||||
id: finding
|
||||
text: root.finding_text
|
||||
halign: 'center'
|
||||
valign: 'center'
|
||||
pos_hint: {"center_y": 0.5}
|
||||
TooltipLabel:
|
||||
id: location
|
||||
text: root.location_text
|
||||
halign: 'center'
|
||||
valign: 'center'
|
||||
pos_hint: {"center_y": 0.5}
|
||||
TooltipLabel:
|
||||
id: entrance
|
||||
text: root.entrance_text
|
||||
halign: 'center'
|
||||
valign: 'center'
|
||||
pos_hint: {"center_y": 0.5}
|
||||
TooltipLabel:
|
||||
id: found
|
||||
text: root.found_text
|
||||
halign: 'center'
|
||||
valign: 'center'
|
||||
pos_hint: {"center_y": 0.5}
|
||||
<HintLog>:
|
||||
cols: 1
|
||||
viewclass: 'HintLabel'
|
||||
scroll_y: self.height
|
||||
scroll_type: ["content", "bars"]
|
||||
bar_width: dp(12)
|
||||
effect_cls: "ScrollEffect"
|
||||
SelectableRecycleBoxLayout:
|
||||
default_size: None, dp(20)
|
||||
default_size_hint: 1, None
|
||||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
orientation: 'vertical'
|
||||
spacing: dp(3)
|
||||
<ServerLabel>:
|
||||
text: "Server:"
|
||||
size_hint_x: None
|
||||
|
||||
@@ -249,6 +249,24 @@ Response:
|
||||
- `err` (`string`): A description of the problem
|
||||
]]
|
||||
|
||||
local bizhawk_version = client.getversion()
|
||||
local bizhawk_major, bizhawk_minor, bizhawk_patch = bizhawk_version:match("(%d+)%.(%d+)%.?(%d*)")
|
||||
bizhawk_major = tonumber(bizhawk_major)
|
||||
bizhawk_minor = tonumber(bizhawk_minor)
|
||||
if bizhawk_patch == "" then
|
||||
bizhawk_patch = 0
|
||||
else
|
||||
bizhawk_patch = tonumber(bizhawk_patch)
|
||||
end
|
||||
|
||||
local lua_major, lua_minor = _VERSION:match("Lua (%d+)%.(%d+)")
|
||||
lua_major = tonumber(lua_major)
|
||||
lua_minor = tonumber(lua_minor)
|
||||
|
||||
if lua_major > 5 or (lua_major == 5 and lua_minor >= 3) then
|
||||
require("lua_5_3_compat")
|
||||
end
|
||||
|
||||
local base64 = require("base64")
|
||||
local socket = require("socket")
|
||||
local json = require("json")
|
||||
@@ -257,7 +275,9 @@ local json = require("json")
|
||||
-- Will cause lag due to large console output
|
||||
local DEBUG = false
|
||||
|
||||
local SOCKET_PORT = 43055
|
||||
local SOCKET_PORT_FIRST = 43055
|
||||
local SOCKET_PORT_RANGE_SIZE = 5
|
||||
local SOCKET_PORT_LAST = SOCKET_PORT_FIRST + SOCKET_PORT_RANGE_SIZE
|
||||
|
||||
local STATE_NOT_CONNECTED = 0
|
||||
local STATE_CONNECTED = 1
|
||||
@@ -277,24 +297,6 @@ local locked = false
|
||||
|
||||
local rom_hash = nil
|
||||
|
||||
local lua_major, lua_minor = _VERSION:match("Lua (%d+)%.(%d+)")
|
||||
lua_major = tonumber(lua_major)
|
||||
lua_minor = tonumber(lua_minor)
|
||||
|
||||
if lua_major > 5 or (lua_major == 5 and lua_minor >= 3) then
|
||||
require("lua_5_3_compat")
|
||||
end
|
||||
|
||||
local bizhawk_version = client.getversion()
|
||||
local bizhawk_major, bizhawk_minor, bizhawk_patch = bizhawk_version:match("(%d+)%.(%d+)%.?(%d*)")
|
||||
bizhawk_major = tonumber(bizhawk_major)
|
||||
bizhawk_minor = tonumber(bizhawk_minor)
|
||||
if bizhawk_patch == "" then
|
||||
bizhawk_patch = 0
|
||||
else
|
||||
bizhawk_patch = tonumber(bizhawk_patch)
|
||||
end
|
||||
|
||||
function queue_push (self, value)
|
||||
self[self.right] = value
|
||||
self.right = self.right + 1
|
||||
@@ -435,7 +437,7 @@ function send_receive ()
|
||||
end
|
||||
|
||||
if message == "VERSION" then
|
||||
local result, err client_socket:send(tostring(SCRIPT_VERSION).."\n")
|
||||
client_socket:send(tostring(SCRIPT_VERSION).."\n")
|
||||
else
|
||||
local res = {}
|
||||
local data = json.decode(message)
|
||||
@@ -463,14 +465,45 @@ function send_receive ()
|
||||
end
|
||||
end
|
||||
|
||||
function main ()
|
||||
server, err = socket.bind("localhost", SOCKET_PORT)
|
||||
function initialize_server ()
|
||||
local err
|
||||
local port = SOCKET_PORT_FIRST
|
||||
local res = nil
|
||||
|
||||
server, err = socket.socket.tcp4()
|
||||
while res == nil and port <= SOCKET_PORT_LAST do
|
||||
res, err = server:bind("localhost", port)
|
||||
if res == nil and err ~= "address already in use" then
|
||||
print(err)
|
||||
return
|
||||
end
|
||||
|
||||
if res == nil then
|
||||
port = port + 1
|
||||
end
|
||||
end
|
||||
|
||||
if port > SOCKET_PORT_LAST then
|
||||
print("Too many instances of connector script already running. Exiting.")
|
||||
return
|
||||
end
|
||||
|
||||
res, err = server:listen(0)
|
||||
|
||||
if err ~= nil then
|
||||
print(err)
|
||||
return
|
||||
end
|
||||
|
||||
server:settimeout(0)
|
||||
end
|
||||
|
||||
function main ()
|
||||
while true do
|
||||
if server == nil then
|
||||
initialize_server()
|
||||
end
|
||||
|
||||
current_time = socket.socket.gettime()
|
||||
timeout_timer = timeout_timer - (current_time - prev_time)
|
||||
message_timer = message_timer - (current_time - prev_time)
|
||||
@@ -482,16 +515,16 @@ function main ()
|
||||
end
|
||||
|
||||
if current_state == STATE_NOT_CONNECTED then
|
||||
if emu.framecount() % 60 == 0 then
|
||||
server:settimeout(2)
|
||||
if emu.framecount() % 30 == 0 then
|
||||
print("Looking for client...")
|
||||
local client, timeout = server:accept()
|
||||
if timeout == nil then
|
||||
print("Client connected")
|
||||
current_state = STATE_CONNECTED
|
||||
client_socket = client
|
||||
server:close()
|
||||
server = nil
|
||||
client_socket:settimeout(0)
|
||||
else
|
||||
print("No client found. Trying again...")
|
||||
end
|
||||
end
|
||||
else
|
||||
@@ -527,27 +560,27 @@ else
|
||||
emu.frameadvance()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
rom_hash = gameinfo.getromhash()
|
||||
|
||||
print("Waiting for client to connect. Emulation will freeze intermittently until a client is found.\n")
|
||||
print("Waiting for client to connect. This may take longer the more instances of this script you have open at once.\n")
|
||||
|
||||
local co = coroutine.create(main)
|
||||
function tick ()
|
||||
local status, err = coroutine.resume(co)
|
||||
|
||||
if not status then
|
||||
|
||||
if not status and err ~= "cannot resume dead coroutine" then
|
||||
print("\nERROR: "..err)
|
||||
print("Consider reporting this crash.\n")
|
||||
|
||||
if server ~= nil then
|
||||
server:close()
|
||||
end
|
||||
|
||||
|
||||
co = coroutine.create(main)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Gambatte has a setting which can cause script execution to become
|
||||
-- misaligned, so for GB and GBC we explicitly set the callback on
|
||||
-- vblank instead.
|
||||
@@ -557,7 +590,7 @@ else
|
||||
else
|
||||
event.onframeend(tick)
|
||||
end
|
||||
|
||||
|
||||
while true do
|
||||
emu.frameadvance()
|
||||
end
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
local socket = require("socket")
|
||||
local json = require('json')
|
||||
local math = require('math')
|
||||
require("common")
|
||||
local STATE_OK = "Ok"
|
||||
local STATE_TENTATIVELY_CONNECTED = "Tentatively Connected"
|
||||
local STATE_INITIAL_CONNECTION_MADE = "Initial Connection Made"
|
||||
local STATE_UNINITIALIZED = "Uninitialized"
|
||||
|
||||
local SCRIPT_VERSION = 3
|
||||
|
||||
local APIndex = 0x1A6E
|
||||
local APDeathLinkAddress = 0x00FD
|
||||
local APItemAddress = 0x00FF
|
||||
local EventFlagAddress = 0x1735
|
||||
local MissableAddress = 0x161A
|
||||
local HiddenItemsAddress = 0x16DE
|
||||
local RodAddress = 0x1716
|
||||
local DexSanityAddress = 0x1A71
|
||||
local InGameAddress = 0x1A84
|
||||
local ClientCompatibilityAddress = 0xFF00
|
||||
|
||||
local ItemsReceived = nil
|
||||
local playerName = nil
|
||||
local seedName = nil
|
||||
|
||||
local deathlink_rec = nil
|
||||
local deathlink_send = false
|
||||
|
||||
local prevstate = ""
|
||||
local curstate = STATE_UNINITIALIZED
|
||||
local gbSocket = nil
|
||||
local frame = 0
|
||||
|
||||
local compat = nil
|
||||
|
||||
local function defineMemoryFunctions()
|
||||
local memDomain = {}
|
||||
local domains = memory.getmemorydomainlist()
|
||||
memDomain["rom"] = function() memory.usememorydomain("ROM") end
|
||||
memDomain["wram"] = function() memory.usememorydomain("WRAM") end
|
||||
return memDomain
|
||||
end
|
||||
|
||||
local memDomain = defineMemoryFunctions()
|
||||
u8 = memory.read_u8
|
||||
wU8 = memory.write_u8
|
||||
u16 = memory.read_u16_le
|
||||
function uRange(address, bytes)
|
||||
data = memory.readbyterange(address - 1, bytes + 1)
|
||||
data[0] = nil
|
||||
return data
|
||||
end
|
||||
|
||||
function generateLocationsChecked()
|
||||
memDomain.wram()
|
||||
events = uRange(EventFlagAddress, 0x140)
|
||||
missables = uRange(MissableAddress, 0x20)
|
||||
hiddenitems = uRange(HiddenItemsAddress, 0x0E)
|
||||
rod = {u8(RodAddress)}
|
||||
dexsanity = uRange(DexSanityAddress, 19)
|
||||
|
||||
|
||||
data = {}
|
||||
|
||||
categories = {events, missables, hiddenitems, rod}
|
||||
if compat > 1 then
|
||||
table.insert(categories, dexsanity)
|
||||
end
|
||||
for _, category in ipairs(categories) do
|
||||
for _, v in ipairs(category) do
|
||||
table.insert(data, v)
|
||||
end
|
||||
end
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
local function arrayEqual(a1, a2)
|
||||
if #a1 ~= #a2 then
|
||||
return false
|
||||
end
|
||||
|
||||
for i, v in ipairs(a1) do
|
||||
if v ~= a2[i] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function receive()
|
||||
l, e = gbSocket:receive()
|
||||
if e == 'closed' then
|
||||
if curstate == STATE_OK then
|
||||
print("Connection closed")
|
||||
end
|
||||
curstate = STATE_UNINITIALIZED
|
||||
return
|
||||
elseif e == 'timeout' then
|
||||
return
|
||||
elseif e ~= nil then
|
||||
print(e)
|
||||
curstate = STATE_UNINITIALIZED
|
||||
return
|
||||
end
|
||||
if l ~= nil then
|
||||
block = json.decode(l)
|
||||
if block ~= nil then
|
||||
local itemsBlock = block["items"]
|
||||
if itemsBlock ~= nil then
|
||||
ItemsReceived = itemsBlock
|
||||
end
|
||||
deathlink_rec = block["deathlink"]
|
||||
|
||||
end
|
||||
end
|
||||
-- Determine Message to send back
|
||||
memDomain.rom()
|
||||
newPlayerName = uRange(0xFFF0, 0x10)
|
||||
newSeedName = uRange(0xFFDB, 21)
|
||||
if (playerName ~= nil and not arrayEqual(playerName, newPlayerName)) or (seedName ~= nil and not arrayEqual(seedName, newSeedName)) then
|
||||
print("ROM changed, quitting")
|
||||
curstate = STATE_UNINITIALIZED
|
||||
return
|
||||
end
|
||||
playerName = newPlayerName
|
||||
seedName = newSeedName
|
||||
local retTable = {}
|
||||
retTable["scriptVersion"] = SCRIPT_VERSION
|
||||
|
||||
if compat == nil then
|
||||
compat = u8(ClientCompatibilityAddress)
|
||||
if compat < 2 then
|
||||
InGameAddress = 0x1A71
|
||||
end
|
||||
end
|
||||
|
||||
retTable["clientCompatibilityVersion"] = compat
|
||||
retTable["playerName"] = playerName
|
||||
retTable["seedName"] = seedName
|
||||
memDomain.wram()
|
||||
|
||||
in_game = u8(InGameAddress)
|
||||
if in_game == 0x2A or in_game == 0xAC then
|
||||
retTable["locations"] = generateLocationsChecked()
|
||||
elseif in_game ~= 0 then
|
||||
print("Game may have crashed")
|
||||
curstate = STATE_UNINITIALIZED
|
||||
return
|
||||
end
|
||||
|
||||
retTable["deathLink"] = deathlink_send
|
||||
deathlink_send = false
|
||||
|
||||
msg = json.encode(retTable).."\n"
|
||||
local ret, error = gbSocket:send(msg)
|
||||
if ret == nil then
|
||||
print(error)
|
||||
elseif curstate == STATE_INITIAL_CONNECTION_MADE then
|
||||
curstate = STATE_TENTATIVELY_CONNECTED
|
||||
elseif curstate == STATE_TENTATIVELY_CONNECTED then
|
||||
print("Connected!")
|
||||
curstate = STATE_OK
|
||||
end
|
||||
end
|
||||
|
||||
function main()
|
||||
if not checkBizHawkVersion() then
|
||||
return
|
||||
end
|
||||
server, error = socket.bind('localhost', 17242)
|
||||
|
||||
while true do
|
||||
frame = frame + 1
|
||||
if not (curstate == prevstate) then
|
||||
print("Current state: "..curstate)
|
||||
prevstate = curstate
|
||||
end
|
||||
if (curstate == STATE_OK) or (curstate == STATE_INITIAL_CONNECTION_MADE) or (curstate == STATE_TENTATIVELY_CONNECTED) then
|
||||
if (frame % 5 == 0) then
|
||||
receive()
|
||||
in_game = u8(InGameAddress)
|
||||
if in_game == 0x2A or in_game == 0xAC then
|
||||
if u8(APItemAddress) == 0x00 then
|
||||
ItemIndex = u16(APIndex)
|
||||
if deathlink_rec == true then
|
||||
wU8(APDeathLinkAddress, 1)
|
||||
elseif u8(APDeathLinkAddress) == 3 then
|
||||
wU8(APDeathLinkAddress, 0)
|
||||
deathlink_send = true
|
||||
end
|
||||
if ItemsReceived[ItemIndex + 1] ~= nil then
|
||||
item_id = ItemsReceived[ItemIndex + 1] - 172000000
|
||||
if item_id > 255 then
|
||||
item_id = item_id - 256
|
||||
end
|
||||
wU8(APItemAddress, item_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif (curstate == STATE_UNINITIALIZED) then
|
||||
if (frame % 60 == 0) then
|
||||
|
||||
print("Waiting for client.")
|
||||
|
||||
emu.frameadvance()
|
||||
server:settimeout(2)
|
||||
print("Attempting to connect")
|
||||
local client, timeout = server:accept()
|
||||
if timeout == nil then
|
||||
curstate = STATE_INITIAL_CONNECTION_MADE
|
||||
gbSocket = client
|
||||
gbSocket:settimeout(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
emu.frameadvance()
|
||||
end
|
||||
end
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user