mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
229 lines
8.5 KiB
Lua
229 lines
8.5 KiB
Lua
local U = require("tests.drivers.util")
|
|
|
|
local SEAT = tonumber(os.getenv("G3TRADE_SEAT") or "0") or 0
|
|
local ROOMFILE = os.getenv("G3TRADE_ROOMFILE")
|
|
or ((os.getenv("TMPDIR") or "/tmp"):gsub("/+$", "") .. "/g3trade_room.txt")
|
|
local DIR = os.getenv("POKEPORT_SHOT_DIR") or ".bazinga/BSA/09-23-26-03-gen3online/shots/gen3trade"
|
|
local TAG = "g3trade_seat" .. SEAT
|
|
local TRADE_CENTER = "FR_TRADE_CENTER"
|
|
-- pokefirered/include/constants/flags.h:1375
|
|
local FLAG_SYS_POKEDEX_GET = 0x829
|
|
local MACHOKE, MACHAMP, BULBASAUR, SQUIRTLE, PIKACHU = 67, 68, 1, 7, 25
|
|
|
|
local failures = 0
|
|
local function result(ok, label)
|
|
print((ok and "PASS " or "FAIL ") .. TAG .. " " .. label)
|
|
if not ok then failures = failures + 1 end
|
|
return ok
|
|
end
|
|
|
|
local function now()
|
|
return love.timer.getTime()
|
|
end
|
|
|
|
return function(game)
|
|
print("PASS " .. TAG .. " driver_started")
|
|
local Link, Client
|
|
|
|
local function finish()
|
|
if Link then pcall(Link.closeLink, "driver_done") end
|
|
if Client then pcall(Client.disconnect) end
|
|
if failures == 0 then
|
|
print("PASS " .. TAG .. " relay_trade")
|
|
love.event.quit(0)
|
|
else
|
|
print("FAIL " .. TAG .. " relay_trade failures=" .. failures)
|
|
love.event.quit(1)
|
|
end
|
|
end
|
|
|
|
for _ = 1, 900 do
|
|
if game.phase == "boot" and game.boot then break end
|
|
U.wait(1)
|
|
end
|
|
game:_handleBootAction({ action = "new_game", name = SEAT == 0 and "RED" or "LEAF" })
|
|
U.wait(240)
|
|
|
|
local Runtime = require("src.core.game3.runtime")
|
|
local Map = require("src.core.game3.map")
|
|
local Space = require("src.core.game3.scripting.space")
|
|
local Flags = require("src.core.game3.scripting.flags")
|
|
local Player = require("src.core.game3.player")
|
|
local Party = require("src.core.game3.party")
|
|
local LT = require("src.core.game3.link.trade")
|
|
local TradeScene = require("src.core.game3.trade_scene")
|
|
local Menu = require("src.ui.game3.link_trade_menu")
|
|
local Game3Link = require("src.link.Game3Link")
|
|
local RelayTransport = require("src.core.game3.link.relay_transport")
|
|
local ArenaData = require("src.online.ArenaData")
|
|
Link = require("src.core.game3.link")
|
|
Client = require("src.online.Client")
|
|
|
|
local session = Runtime.getSession()
|
|
if not result(session ~= nil, "new game reached the game3 field") then return finish() end
|
|
local g3 = Runtime._game or game
|
|
|
|
Flags.setFlag(Space.store, Space.vm and Space.vm.ctx, FLAG_SYS_POKEDEX_GET, true)
|
|
session.name = SEAT == 0 and "RED" or "LEAF"
|
|
session.trainerId = SEAT == 0 and 0x1234 or 0x2222
|
|
session.party = {}
|
|
if SEAT == 0 then
|
|
Party.giveMon(session, MACHOKE, 30)
|
|
Party.giveMon(session, BULBASAUR, 10)
|
|
else
|
|
Party.giveMon(session, SQUIRTLE, 11)
|
|
Party.giveMon(session, PIKACHU, 14)
|
|
end
|
|
local expectFirst = SEAT == 0 and SQUIRTLE or MACHAMP
|
|
|
|
local saves, savedLead = 0, nil
|
|
local realSave = g3.saveGame
|
|
g3.saveGame = function(self, ...)
|
|
saves = saves + 1
|
|
savedLead = session.party[1] and session.party[1].species
|
|
if realSave then return realSave(self, ...) end
|
|
end
|
|
|
|
local function waitUntil(pred, seconds)
|
|
local deadline = now() + (seconds or 10)
|
|
while not pred() do
|
|
if now() > deadline then return false end
|
|
U.wait(1)
|
|
end
|
|
return true
|
|
end
|
|
|
|
local profile, why = ArenaData.liveProfile3(g3, "g3_link")
|
|
if not result(profile ~= nil, "the running game has a live Gen 3 profile (" .. tostring(why) .. ")") then
|
|
return finish()
|
|
end
|
|
local okC, errC = Client.connect({ name = session.name, profiles = { profile },
|
|
presence = { where = "game", status = "busy" } })
|
|
result(okC, "Client.connect to " .. tostring(os.getenv("POKEPORT_RELAY_ADDR")) .. " " .. tostring(errC))
|
|
if not result(waitUntil(function() return Client.state() == "online" end, 10), "online on the relay") then
|
|
return finish()
|
|
end
|
|
|
|
if SEAT == 0 then
|
|
os.remove(ROOMFILE)
|
|
Client.createRoom({ intent = "trade", profile = profile, seats = 2 })
|
|
if not result(waitUntil(function() return Client.room() ~= nil end, 10), "seat 0 opened a trade room") then
|
|
return finish()
|
|
end
|
|
local fh = io.open(ROOMFILE, "w")
|
|
if fh then
|
|
fh:write(tostring(Client.room().room))
|
|
fh:close()
|
|
end
|
|
else
|
|
local roomId
|
|
waitUntil(function()
|
|
local fh = io.open(ROOMFILE, "r")
|
|
if fh then
|
|
roomId = fh:read("*l")
|
|
fh:close()
|
|
end
|
|
return roomId ~= nil and roomId ~= ""
|
|
end, 15)
|
|
if not result(roomId ~= nil, "seat 1 found the room id") then return finish() end
|
|
Client.joinRoom(roomId, "player", profile)
|
|
end
|
|
|
|
local paired = waitUntil(function()
|
|
local room = Client.room()
|
|
return room and Client.seat() ~= nil and #(room.players or {}) == 2 and room.match ~= nil
|
|
end, 15)
|
|
if not result(paired, "both seats are in the room and the match started") then return finish() end
|
|
result(Client.seat() == SEAT, "this process holds seat " .. SEAT)
|
|
|
|
local transport = RelayTransport.new(Client.roomSession())
|
|
local live = Game3Link.attach(transport, {
|
|
seat = Client.seat(), seats = 2, game = g3, linkType = Game3Link.LINKTYPE.TRADE,
|
|
})
|
|
Link.attach(live)
|
|
if not result(waitUntil(function() return live:isReady() end, 10), "the Game3Link handshake is full") then
|
|
return finish()
|
|
end
|
|
|
|
-- pokefirered/data/maps/TradeCenter/map.json:1 TradeCenter_EventScript_Chair0 / Chair1
|
|
Map.load(nil, g3, TRADE_CENTER, { x = SEAT == 0 and 4 or 7, y = 5, facing = SEAT == 0 and "right" or "left" })
|
|
Player.cellX, Player.cellY = SEAT == 0 and 4 or 7, 5
|
|
Player.px, Player.py = Player.cellX * 16, Player.cellY * 16
|
|
Player.targetX, Player.targetY = Player.cellX, Player.cellY
|
|
U.wait(60)
|
|
-- pokefirered/src/cable_club.c:958
|
|
LT.startMenu()
|
|
if not result(waitUntil(function() return Menu.isOpen() and Menu.cb == "main" and Menu.fade == 0 end, 15),
|
|
"the trade menu is up with the other party on it") then
|
|
return finish()
|
|
end
|
|
result(#LT.peerParty == 2, "the other seat's two mons arrived unpacked")
|
|
U.wait(10)
|
|
U.still(game, DIR .. "/" .. TAG .. "_trade_menu.png")
|
|
|
|
U.tap(game, "a")
|
|
U.wait(4)
|
|
U.tap(game, "down")
|
|
U.wait(4)
|
|
U.tap(game, "a")
|
|
if not result(waitUntil(function() return Menu.cb == "confirm_prompt" and Menu.confirming end, 20),
|
|
"both offered their lead and IS THIS TRADE OKAY? came up") then
|
|
return finish()
|
|
end
|
|
U.wait(4)
|
|
U.still(game, DIR .. "/" .. TAG .. "_confirm.png")
|
|
if SEAT == 1 then
|
|
local realConfirm, holdUntil = LT.tryConfirm, nil
|
|
LT.tryConfirm = function(...)
|
|
holdUntil = holdUntil or (now() + 3)
|
|
if now() < holdUntil then return false end
|
|
LT.tryConfirm = realConfirm
|
|
return realConfirm(...)
|
|
end
|
|
end
|
|
U.tap(game, "a")
|
|
|
|
result(waitUntil(function() return LT.state == "commit_wait" or LT._committed end, 10),
|
|
"the confirm went to the relay")
|
|
result(saves == 0, "nothing was written before trade_commit")
|
|
print("INFO " .. TAG .. " digest=" .. tostring(LT._digest))
|
|
if SEAT == 0 then
|
|
U.wait(10)
|
|
if result(LT.state == "commit_wait", "seat 0 waits on Communication standby for the other confirm") then
|
|
U.still(game, DIR .. "/" .. TAG .. "_commit_wait.png")
|
|
end
|
|
end
|
|
if not result(waitUntil(function() return TradeScene.isOpen() end, 15),
|
|
"trade_commit arrived and the trade scene started") then
|
|
return finish()
|
|
end
|
|
if result(waitUntil(function() return TradeScene.phase() == "bye_bye" end, 15),
|
|
"the scene put the outgoing mon on screen") then
|
|
U.wait(10)
|
|
U.still(game, DIR .. "/" .. TAG .. "_scene.png")
|
|
end
|
|
|
|
local done = waitUntil(function()
|
|
if not TradeScene.isOpen() and LT.completed >= 1 then return true end
|
|
local Evo = package.loaded["src.ui.game3.evolution_scene"]
|
|
local Message = package.loaded["src.ui.game3.message"]
|
|
if (Evo and Evo.isOpen and Evo.isOpen()) or (Message and Message.isOpen and Message.isOpen()) then
|
|
table.insert(game.input.pressQueue, "a")
|
|
end
|
|
return false
|
|
end, 25)
|
|
if not result(done, "the scene, evolution and save ran to the end") then return finish() end
|
|
result(saves == 1, "the save was written exactly once (" .. saves .. ")")
|
|
result(savedLead == expectFirst, "the save holds the received mon (" .. tostring(savedLead) .. ")")
|
|
result(session.party[1] and session.party[1].species == expectFirst,
|
|
"the party lead is now species " .. tostring(expectFirst))
|
|
result(LT._saveFailed == false, "the post-trade save reported success")
|
|
|
|
if result(waitUntil(function() return Menu.isOpen() and Menu.cb == "main" and Menu.fade == 0 end, 15),
|
|
"the Trade Center returned to the trade menu with the new party") then
|
|
U.wait(10)
|
|
U.still(game, DIR .. "/" .. TAG .. "_after_save_party.png")
|
|
end
|
|
return finish()
|
|
end
|