mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
651 lines
26 KiB
Lua
651 lines
26 KiB
Lua
local ADDR = os.getenv("POKEPORT_RELAY_ADDR") or "127.0.0.1:28100"
|
|
|
|
local peers = {}
|
|
local hooks = {}
|
|
local log = function(...) print("[final]", ...) end
|
|
|
|
local function Main()
|
|
return require("src.online.Client")
|
|
end
|
|
|
|
local function newPeer()
|
|
local saved = package.loaded["src.online.Client"]
|
|
package.loaded["src.online.Client"] = nil
|
|
local C = require("src.online.Client")
|
|
package.loaded["src.online.Client"] = saved
|
|
C.reset()
|
|
C.configure({ relayAddress = ADDR })
|
|
peers[#peers + 1] = C
|
|
return C
|
|
end
|
|
|
|
local function pumpAll(OnlinePanel, imp)
|
|
pcall(Main().update, 1 / 60)
|
|
for _, C in ipairs(peers) do pcall(C.update, 1 / 60) end
|
|
for _, fn in ipairs(hooks) do pcall(fn) end
|
|
OnlinePanel.update(imp, 1 / 60)
|
|
end
|
|
|
|
local function waitUntil(OnlinePanel, imp, fn, what, seconds)
|
|
local deadline = love.timer.getTime() + (seconds or 8)
|
|
while love.timer.getTime() < deadline do
|
|
pumpAll(OnlinePanel, imp)
|
|
if fn() then return true end
|
|
love.timer.sleep(0.01)
|
|
end
|
|
log("TIMEOUT", what)
|
|
return false
|
|
end
|
|
|
|
local function settle(OnlinePanel, imp, seconds)
|
|
local deadline = love.timer.getTime() + (seconds or 0.3)
|
|
while love.timer.getTime() < deadline do
|
|
pumpAll(OnlinePanel, imp)
|
|
love.timer.sleep(0.01)
|
|
end
|
|
end
|
|
|
|
local function copy(t)
|
|
local out = {}
|
|
for k, v in pairs(t) do out[k] = type(v) == "table" and copy(v) or v end
|
|
return out
|
|
end
|
|
|
|
local function variant(base, version, ruleset, size)
|
|
local p = copy(base)
|
|
p.version = version or p.version
|
|
p.rulesetId = ruleset or p.rulesetId
|
|
p.rule = { partySize = size or 3 }
|
|
return p
|
|
end
|
|
|
|
local function hookUpdate(OnlinePanel)
|
|
if OnlinePanel._finalHooked then return end
|
|
OnlinePanel._finalHooked = true
|
|
local orig = OnlinePanel.update
|
|
OnlinePanel.update = function(imp, dt)
|
|
for _, C in ipairs(peers) do pcall(C.update, dt) end
|
|
for _, fn in ipairs(hooks) do pcall(fn) end
|
|
return orig(imp, dt)
|
|
end
|
|
end
|
|
|
|
local function setup(OnlinePanel, imp, version, picks)
|
|
local st = OnlinePanel.state(imp)
|
|
st.version, st.kind, st.cartId = version, "vanilla", nil
|
|
st.versionPicked = true
|
|
st.slotId = nil
|
|
for _, row in ipairs(OnlinePanel.slotsIn(imp, version, nil)) do
|
|
if row.exists and not st.slotId then st.slotId = row.id end
|
|
end
|
|
st.setupDone = st.slotId ~= nil
|
|
st.team = {}
|
|
st.slotRead = nil
|
|
local pick = OnlinePanel.readTeamSlot(imp)
|
|
if pick then
|
|
require("src.online.OnlineSprites").prime(version, pick.party)
|
|
for index = 1, math.min(picks or 3, #pick.party) do
|
|
OnlinePanel.toggleTeam(st.team, index)
|
|
end
|
|
st.focusMon = OnlinePanel.refKey(st.team[1])
|
|
end
|
|
OnlinePanel.invalidate(imp)
|
|
return st
|
|
end
|
|
|
|
local function goOnline(OnlinePanel, imp, version, picks, ruleset)
|
|
local st = setup(OnlinePanel, imp, version, picks)
|
|
if ruleset then OnlinePanel.setRuleset(imp, ruleset) end
|
|
waitUntil(OnlinePanel, imp, function() return OnlinePanel.myProfile(imp) ~= nil end,
|
|
"the panel profile", 20)
|
|
OnlinePanel.connect(imp)
|
|
waitUntil(OnlinePanel, imp, function() return Main().state() == "online" end,
|
|
"the panel online", 10)
|
|
local base = OnlinePanel.myProfile(imp)
|
|
log("panel", tostring(Main().state()), "profile", tostring(base and base.fingerprint),
|
|
"slot", tostring(st.slotId), "team", #st.team)
|
|
return st, base and copy(base) or nil
|
|
end
|
|
|
|
local function connectPeer(OnlinePanel, imp, name, profiles, where, version)
|
|
local C = newPeer()
|
|
C.connect({ name = name, profiles = profiles,
|
|
presence = { where = where, status = "idle", version = version } })
|
|
waitUntil(OnlinePanel, imp, function() return C.state() == "online" end,
|
|
name .. " online", 8)
|
|
return C
|
|
end
|
|
|
|
local function hostRoom(OnlinePanel, imp, C, opts)
|
|
local made = C.createRoom(opts)
|
|
waitUntil(OnlinePanel, imp, function() return made.done end, "room create", 8)
|
|
log("room", tostring(made.id), tostring(made.error))
|
|
return made.id
|
|
end
|
|
|
|
local function avatarOf(name, version, gender)
|
|
return { name = name, trainerId = #name * 1111, gender = gender or 0, version = version }
|
|
end
|
|
|
|
local function joinUnion(OnlinePanel, imp, C, profile, name, version, gender)
|
|
C.joinPlaza("union", profile, avatarOf(name, version, gender))
|
|
waitUntil(OnlinePanel, imp, function() return C.plaza() ~= nil end, name .. " in the Union Room", 6)
|
|
end
|
|
|
|
local function directHost(OnlinePanel, imp, C, activity, profile, pin, name, version)
|
|
C.queueDirect({ activity = activity, profile = profile, pin = pin, auto = false,
|
|
avatar = avatarOf(name, version) })
|
|
waitUntil(OnlinePanel, imp, function() return C.room() ~= nil end, name .. " hosting in Direct Corner", 6)
|
|
log("direct", name, tostring(C.room() and C.room().room), tostring(C.error()))
|
|
end
|
|
|
|
local function seedLobby(OnlinePanel, imp, base)
|
|
local fr, lg = "firered", "leafgreen"
|
|
local P = {}
|
|
P.leaf = connectPeer(OnlinePanel, imp, "LEAF#102",
|
|
{ variant(base, lg, "g3_single") }, "launcher", lg)
|
|
hostRoom(OnlinePanel, imp, P.leaf, { intent = "battle", profile = variant(base, lg, "g3_single"),
|
|
playing = true, maxSpectators = 8, private = true, pin = "0427", seats = 2, auto = false,
|
|
note = "no legends" })
|
|
P.gold = connectPeer(OnlinePanel, imp, "GOLD#103",
|
|
{ variant(base, fr, "g3_double") }, "launcher", fr)
|
|
directHost(OnlinePanel, imp, P.gold, "battle_double", variant(base, fr, "g3_double"), nil,
|
|
"GOLD", fr)
|
|
P.wally = connectPeer(OnlinePanel, imp, "WALLY#110",
|
|
{ variant(base, lg, "g3_single") }, "launcher", lg)
|
|
directHost(OnlinePanel, imp, P.wally, "battle_single", variant(base, lg, "g3_single"), "5555",
|
|
"WALLY", lg)
|
|
P.may = connectPeer(OnlinePanel, imp, "MAY#104",
|
|
{ variant(base, lg, "g3_link") }, "launcher", lg)
|
|
hostRoom(OnlinePanel, imp, P.may, { intent = "trade", profile = variant(base, lg, "g3_link"),
|
|
playing = true, maxSpectators = 0, private = true, pin = "1234", seats = 2, auto = false })
|
|
P.kris = connectPeer(OnlinePanel, imp, "KRIS#105",
|
|
{ variant(base, fr, "g3_multi") }, "launcher", fr)
|
|
P.krisRoom = hostRoom(OnlinePanel, imp, P.kris, { intent = "battle",
|
|
profile = variant(base, fr, "g3_multi"), playing = true, maxSpectators = 8,
|
|
private = false, seats = 4, auto = false })
|
|
P.lyra = connectPeer(OnlinePanel, imp, "LYRA#106",
|
|
{ variant(base, lg, "g3_multi") }, "launcher", lg)
|
|
if P.krisRoom then
|
|
local j = P.lyra.joinRoom(P.krisRoom, "player", variant(base, lg, "g3_multi"))
|
|
waitUntil(OnlinePanel, imp, function() return j.done end, "lyra joins kris", 6)
|
|
end
|
|
P.brock = connectPeer(OnlinePanel, imp, "BROCK#107",
|
|
{ variant(base, fr, "g3_single") }, "launcher", fr)
|
|
P.brock.directList("battle_single", variant(base, fr, "g3_single"))
|
|
P.misty = connectPeer(OnlinePanel, imp, "MISTY#108",
|
|
{ variant(base, lg, "g3_single") }, "launcher", lg)
|
|
joinUnion(OnlinePanel, imp, P.misty, variant(base, lg, "g3_link"), "MISTY", lg, 1)
|
|
P.erika = connectPeer(OnlinePanel, imp, "ERIKA#111",
|
|
{ variant(base, fr, "g3_single") }, "launcher", fr)
|
|
joinUnion(OnlinePanel, imp, P.erika, variant(base, fr, "g3_link"), "ERIKA", fr, 1)
|
|
P.blue = connectPeer(OnlinePanel, imp, "BLUE#109",
|
|
{ variant(base, lg, "g3_single") }, "launcher", lg)
|
|
settle(OnlinePanel, imp, 0.5)
|
|
return P
|
|
end
|
|
|
|
local function lobbyHas(OnlinePanel, imp, n)
|
|
return function()
|
|
OnlinePanel.invalidate(imp, "lobby")
|
|
OnlinePanel.refresh(imp)
|
|
local c = OnlinePanel.cache(imp)
|
|
return #(c.rooms or {}) >= n
|
|
end
|
|
end
|
|
|
|
local function rowFor(OnlinePanel, imp, name)
|
|
OnlinePanel.invalidate(imp, "lobby")
|
|
OnlinePanel.refresh(imp)
|
|
for _, e in ipairs(Main().lobby() or {}) do
|
|
if e.name == name then return e end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function playerRowFor(OnlinePanel, imp, name)
|
|
OnlinePanel.invalidate(imp, "lobby")
|
|
OnlinePanel.refresh(imp)
|
|
for _, r in ipairs(OnlinePanel.cache(imp).players or {}) do
|
|
if r.name == name then return r end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function playList(OnlinePanel, imp, base)
|
|
local P = seedLobby(OnlinePanel, imp, base)
|
|
waitUntil(OnlinePanel, imp, lobbyHas(OnlinePanel, imp, 3), "lobby rows", 8)
|
|
for _, e in ipairs(Main().lobby() or {}) do
|
|
log("entry", tostring(e.name), tostring(e.where), tostring(e.version), tostring(e.room),
|
|
tostring(e.locked), tostring(e.status), "online=" .. tostring(e.online))
|
|
end
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "play")
|
|
return P
|
|
end
|
|
|
|
local function pinTarget(OnlinePanel, imp)
|
|
local entry = rowFor(OnlinePanel, imp, "LEAF#102")
|
|
log("pin row", tostring(entry and entry.room), tostring(entry and entry.locked))
|
|
return entry and OnlinePanel.targetFor(entry, "player") or nil
|
|
end
|
|
|
|
local function submitPin(OnlinePanel, imp, pin)
|
|
local mo = OnlinePanel.pinModal(imp)
|
|
if mo then mo.pin = "" end
|
|
OnlinePanel.fieldType(imp, OnlinePanel.PIN_FIELD, pin)
|
|
OnlinePanel.pinSubmit(imp)
|
|
waitUntil(OnlinePanel, imp, function()
|
|
local m = OnlinePanel.pinModal(imp)
|
|
return m ~= nil and m.error ~= nil
|
|
end, "the PIN answer", 6)
|
|
local m = OnlinePanel.pinModal(imp)
|
|
log("pin answer", tostring(m and m.error))
|
|
end
|
|
|
|
local STATES = {}
|
|
|
|
function STATES.play(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
playList(OnlinePanel, imp, base)
|
|
end
|
|
|
|
STATES["play-gen3"] = function(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
playList(OnlinePanel, imp, base)
|
|
OnlinePanel.setFilter(imp, "gen3")
|
|
end
|
|
|
|
function STATES.trainers(OnlinePanel, imp)
|
|
local st, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
playList(OnlinePanel, imp, base)
|
|
st.list = "players"
|
|
OnlinePanel.invalidate(imp)
|
|
end
|
|
|
|
STATES["trainers-where"] = function(OnlinePanel, imp)
|
|
local st, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
local fr, lg = "firered", "leafgreen"
|
|
local misty = connectPeer(OnlinePanel, imp, "MISTY#108", { variant(base, lg, "g3_single") }, "launcher", lg)
|
|
joinUnion(OnlinePanel, imp, misty, variant(base, lg, "g3_link"), "MISTY", lg, 1)
|
|
local erika = connectPeer(OnlinePanel, imp, "ERIKA#111", { variant(base, fr, "g3_single") }, "launcher", fr)
|
|
joinUnion(OnlinePanel, imp, erika, variant(base, fr, "g3_link"), "ERIKA", fr, 1)
|
|
local brock = connectPeer(OnlinePanel, imp, "BROCK#107", { variant(base, fr, "g3_single") }, "launcher", fr)
|
|
brock.directList("battle_single", variant(base, fr, "g3_single"))
|
|
local gold = connectPeer(OnlinePanel, imp, "GOLD#103", { variant(base, lg, "g3_double") }, "launcher", lg)
|
|
directHost(OnlinePanel, imp, gold, "battle_double", variant(base, lg, "g3_double"), nil, "GOLD", lg)
|
|
connectPeer(OnlinePanel, imp, "BLUE#109", { variant(base, lg, "g3_single") }, "launcher", lg)
|
|
connectPeer(OnlinePanel, imp, "SILVER#112", { variant(base, fr, "g3_single") }, "launcher", fr)
|
|
settle(OnlinePanel, imp, 0.5)
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "play")
|
|
st.list = "players"
|
|
OnlinePanel.setFilter(imp, "gen3")
|
|
OnlinePanel.invalidate(imp)
|
|
end
|
|
|
|
STATES["invite-picker"] = function(OnlinePanel, imp)
|
|
local st, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
playList(OnlinePanel, imp, base)
|
|
st.list = "players"
|
|
local row = playerRowFor(OnlinePanel, imp, "MISTY#108")
|
|
log("picker row", tostring(row and row.name), tostring(row and row.where))
|
|
if row then OnlinePanel.invitePickerOpen(imp, row) end
|
|
end
|
|
|
|
STATES["invite-picker-direct"] = function(OnlinePanel, imp)
|
|
local st, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
playList(OnlinePanel, imp, base)
|
|
st.list = "players"
|
|
local row = playerRowFor(OnlinePanel, imp, "BROCK#107")
|
|
if row then OnlinePanel.invitePickerOpen(imp, row) end
|
|
end
|
|
|
|
STATES["invite-picker-launcher"] = function(OnlinePanel, imp)
|
|
local st, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
playList(OnlinePanel, imp, base)
|
|
st.list = "players"
|
|
local row = playerRowFor(OnlinePanel, imp, "BLUE#109")
|
|
if row then OnlinePanel.invitePickerOpen(imp, row) end
|
|
end
|
|
|
|
function STATES.toast(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
local P = playList(OnlinePanel, imp, base)
|
|
local me = Main().you() and Main().you().id
|
|
P.misty.invite(me, "battle_double", { ruleset = "g3_double" },
|
|
variant(base, "leafgreen", "g3_double"))
|
|
waitUntil(OnlinePanel, imp, function() return OnlinePanel.toast(imp) ~= nil end,
|
|
"the invite toast", 6)
|
|
settle(OnlinePanel, imp, 1.2)
|
|
log("toast", tostring(OnlinePanel.toast(imp) and OnlinePanel.inviteLine(OnlinePanel.toast(imp))))
|
|
end
|
|
|
|
function STATES.pin(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
playList(OnlinePanel, imp, base)
|
|
local target = pinTarget(OnlinePanel, imp)
|
|
if target then OnlinePanel.startJoin(imp, target) end
|
|
OnlinePanel.fieldType(imp, OnlinePanel.PIN_FIELD, "04")
|
|
end
|
|
|
|
STATES["pin-wrong"] = function(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
playList(OnlinePanel, imp, base)
|
|
local target = pinTarget(OnlinePanel, imp)
|
|
if target then OnlinePanel.startJoin(imp, target) end
|
|
submitPin(OnlinePanel, imp, "1111")
|
|
end
|
|
|
|
STATES["pin-locked"] = function(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
playList(OnlinePanel, imp, base)
|
|
local target = pinTarget(OnlinePanel, imp)
|
|
if target then OnlinePanel.startJoin(imp, target) end
|
|
for i = 1, 5 do submitPin(OnlinePanel, imp, ("%04d"):format(1110 + i)) end
|
|
end
|
|
|
|
STATES["host-private"] = function(OnlinePanel, imp)
|
|
local st = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "play")
|
|
OnlinePanel.startWizard(imp, "hostBattle")
|
|
OnlinePanel.wizardTo(imp, "visibility")
|
|
st.private = true
|
|
OnlinePanel.fieldType(imp, OnlinePanel.HOST_PIN_FIELD or "online-host-pin", "0427")
|
|
if st.pin ~= "0427" then st.pin = "0427" end
|
|
end
|
|
|
|
STATES["host-format"] = function(OnlinePanel, imp)
|
|
goOnline(OnlinePanel, imp, "firered", 3, "g3_double")
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "play")
|
|
OnlinePanel.startWizard(imp, "hostBattle")
|
|
OnlinePanel.wizardTo(imp, "format")
|
|
end
|
|
|
|
STATES["host-format-multi"] = function(OnlinePanel, imp)
|
|
goOnline(OnlinePanel, imp, "firered", 3, "g3_multi")
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "play")
|
|
OnlinePanel.startWizard(imp, "hostBattle")
|
|
OnlinePanel.wizardTo(imp, "format")
|
|
end
|
|
|
|
function STATES.room(OnlinePanel, imp)
|
|
local st, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
st.private, st.pin = true, "0427"
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "play")
|
|
OnlinePanel.hostBattle(imp)
|
|
waitUntil(OnlinePanel, imp, function() return Main().room() ~= nil end, "the panel room", 8)
|
|
local room = Main().room()
|
|
local guest = connectPeer(OnlinePanel, imp, "LEAF#102",
|
|
{ variant(base, "leafgreen", "g3_single") }, "union", "leafgreen")
|
|
local spec = connectPeer(OnlinePanel, imp, "MISTY#108",
|
|
{ variant(base, "leafgreen", "g3_single") }, "launcher", "leafgreen")
|
|
if room then
|
|
local s = spec.joinRoom(room.room, "spectator", variant(base, "leafgreen", "g3_single"), "0427")
|
|
waitUntil(OnlinePanel, imp, function() return s.done end, "the spectator", 6)
|
|
log("spectator", tostring(s.error))
|
|
end
|
|
settle(OnlinePanel, imp, 0.3)
|
|
OnlinePanel.go(imp, "room")
|
|
log("room", tostring(room and room.room), tostring(room and room.locked), tostring(guest.state()))
|
|
end
|
|
|
|
STATES["room-multi"] = function(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_multi")
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "play")
|
|
OnlinePanel.hostBattle(imp)
|
|
waitUntil(OnlinePanel, imp, function() return Main().room() ~= nil end, "the multi room", 8)
|
|
local room = Main().room()
|
|
log("multi seats", tostring(room and room.seats))
|
|
for _, who in ipairs({ { "LEAF#102", "leafgreen", "union" }, { "GOLD#103", "firered", "direct" } }) do
|
|
local C = connectPeer(OnlinePanel, imp, who[1],
|
|
{ variant(base, who[2], "g3_multi") }, who[3], who[2])
|
|
if room then
|
|
local j = C.joinRoom(room.room, "player", variant(base, who[2], "g3_multi"))
|
|
waitUntil(OnlinePanel, imp, function() return j.done end, who[1] .. " joins", 6)
|
|
end
|
|
end
|
|
waitUntil(OnlinePanel, imp, function()
|
|
local r = Main().room()
|
|
return r and #(r.players or {}) >= 3
|
|
end, "three seats taken", 6)
|
|
OnlinePanel.go(imp, "room")
|
|
end
|
|
|
|
function STATES.watch(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
local host = connectPeer(OnlinePanel, imp, "STEVEN#111",
|
|
{ variant(base, "leafgreen", "g3_multi") }, "union", "leafgreen")
|
|
local id = hostRoom(OnlinePanel, imp, host, { intent = "battle",
|
|
profile = variant(base, "leafgreen", "g3_multi"), playing = true, maxSpectators = 8,
|
|
private = false, seats = 4, auto = false })
|
|
local seatNames = { { "WALLACE#112", "firered" }, { "GLACIA#113", "leafgreen" },
|
|
{ "DRAKE#114", "firered" } }
|
|
for _, who in ipairs(seatNames) do
|
|
local C = connectPeer(OnlinePanel, imp, who[1],
|
|
{ variant(base, who[2], "g3_multi") }, "direct", who[2])
|
|
if id then
|
|
local j = C.joinRoom(id, "player", variant(base, who[2], "g3_multi"))
|
|
waitUntil(OnlinePanel, imp, function() return j.done end, who[1] .. " joins", 6)
|
|
end
|
|
end
|
|
local blaine = connectPeer(OnlinePanel, imp, "BLAINE#115",
|
|
{ variant(base, "firered", "g3_double") }, "launcher", "firered")
|
|
local id2 = hostRoom(OnlinePanel, imp, blaine, { intent = "battle",
|
|
profile = variant(base, "firered", "g3_double"), playing = true, maxSpectators = 8,
|
|
private = false, seats = 2, auto = false })
|
|
local sabrina = connectPeer(OnlinePanel, imp, "SABRINA#116",
|
|
{ variant(base, "leafgreen", "g3_double") }, "union", "leafgreen")
|
|
if id2 then
|
|
local j = sabrina.joinRoom(id2, "player", variant(base, "leafgreen", "g3_double"))
|
|
waitUntil(OnlinePanel, imp, function() return j.done end, "sabrina joins", 6)
|
|
end
|
|
waitUntil(OnlinePanel, imp, function()
|
|
OnlinePanel.invalidate(imp, "lobby")
|
|
OnlinePanel.refresh(imp)
|
|
return #(OnlinePanel.cache(imp).watch or {}) >= 2
|
|
end, "two watchable battles", 8)
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "watch")
|
|
end
|
|
|
|
local function tradePair(OnlinePanel, imp, version, peerVersion, ruleset)
|
|
local st, base = goOnline(OnlinePanel, imp, version, 1, nil)
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "trade")
|
|
local tr = OnlinePanel.tradeState(imp)
|
|
tr.mode, tr.chosen = "remote", true
|
|
OnlinePanel.hostTrade(imp)
|
|
waitUntil(OnlinePanel, imp, function() return Main().room() ~= nil end, "the trade room", 8)
|
|
local room = Main().room()
|
|
local peerProfile = variant(base, peerVersion, ruleset or (base and base.rulesetId), 3)
|
|
if room and room.profile then
|
|
peerProfile = copy(room.profile)
|
|
peerProfile.version = peerVersion
|
|
end
|
|
local partner = connectPeer(OnlinePanel, imp, "LEAF#102", { peerProfile }, "launcher", peerVersion)
|
|
local j = partner.joinRoom(room and room.room, "player", peerProfile)
|
|
waitUntil(OnlinePanel, imp, function() return j.done end, "the partner joins", 6)
|
|
log("partner join", tostring(j.error))
|
|
local Trade = require("src.online.Trade")
|
|
local handle, why = Trade.openSlot(peerVersion, "slot1", nil)
|
|
log("partner handle", tostring(handle and #handle.party), tostring(why))
|
|
local peer
|
|
if handle and require("src.core.GameVersion").generation(peerVersion) ~= 3 then
|
|
local Protocol = require("src.link.Protocol")
|
|
partner.ready(Protocol.packParty({ handle.party[1] }), "final-peer")
|
|
waitUntil(OnlinePanel, imp, function()
|
|
local r = partner.room()
|
|
return r and r.stage ~= "waiting" and r.stage ~= "ready"
|
|
end, "the gen 1 trade to start", 8)
|
|
end
|
|
waitUntil(OnlinePanel, imp, function() return partner.roomSession() ~= nil end, "partner session", 6)
|
|
if handle and partner.roomSession() then
|
|
local err
|
|
peer, err = Trade.remote(handle, partner.roomSession(), { peerName = "RED", strict = true })
|
|
log("partner remote", tostring(peer ~= nil), tostring(err))
|
|
if peer then
|
|
hooks[#hooks + 1] = function() peer:update(1 / 60) end
|
|
peer:start()
|
|
end
|
|
end
|
|
waitUntil(OnlinePanel, imp, function()
|
|
return tr.remote and tr.remote:stage() == "picking" and peer and peer:stage() == "picking"
|
|
end, "both trade menus", 10)
|
|
log("stages", tostring(tr.remote and tr.remote:stage()), tostring(peer and peer:stage()),
|
|
tostring(tr.remoteError))
|
|
return st, tr, peer
|
|
end
|
|
|
|
STATES["trade-picking"] = function(OnlinePanel, imp)
|
|
tradePair(OnlinePanel, imp, "firered", "leafgreen")
|
|
end
|
|
|
|
STATES["trade-confirm"] = function(OnlinePanel, imp)
|
|
local _, tr, peer = tradePair(OnlinePanel, imp, "firered", "leafgreen")
|
|
OnlinePanel.remotePick(imp, 4)
|
|
if peer then peer:pick(1) end
|
|
waitUntil(OnlinePanel, imp, function()
|
|
return tr.remote and tr.remote:stage() == "confirming" and peer and peer:stage() == "confirming"
|
|
end, "both confirm prompts", 8)
|
|
end
|
|
|
|
STATES["trade-done"] = function(OnlinePanel, imp)
|
|
local st, tr, peer = tradePair(OnlinePanel, imp, "firered", "leafgreen")
|
|
OnlinePanel.remotePick(imp, 4)
|
|
if peer then peer:pick(1) end
|
|
waitUntil(OnlinePanel, imp, function()
|
|
return tr.remote and tr.remote:stage() == "confirming" and peer and peer:stage() == "confirming"
|
|
end, "both confirm prompts", 8)
|
|
OnlinePanel.remoteConfirm(imp, true)
|
|
if peer then peer:confirm(true) end
|
|
waitUntil(OnlinePanel, imp, function()
|
|
return st.status == "Trade complete." or tr.remoteResult ~= nil
|
|
end, "the trade commit", 10)
|
|
log("trade", tostring(st.status), tostring(tr.remoteResult), tostring(peer and peer:stage()))
|
|
end
|
|
|
|
STATES["tour-code"] = function(OnlinePanel, imp)
|
|
local st, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
st.tourPublic = false
|
|
st.tourPlaying = true
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "play")
|
|
OnlinePanel.hostTournament(imp)
|
|
waitUntil(OnlinePanel, imp, function() return Main().tournament() ~= nil end,
|
|
"the private tournament", 8)
|
|
local tour = Main().tournament()
|
|
log("tour code", tostring(tour and tour.code))
|
|
if tour and tour.code then
|
|
for _, who in ipairs({ { "LEAF#102", "leafgreen" }, { "BROCK#107", "firered" } }) do
|
|
local C = connectPeer(OnlinePanel, imp, who[1], { variant(base, who[2], "g3_single") },
|
|
"launcher", who[2])
|
|
local j = C.joinTournament({ code = tour.code, as = "spectator",
|
|
profile = variant(base, who[2], "g3_single") })
|
|
waitUntil(OnlinePanel, imp, function() return j.done end, who[1] .. " joins", 6)
|
|
end
|
|
end
|
|
OnlinePanel.go(imp, "tournament")
|
|
end
|
|
|
|
STATES["tour-join"] = function(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "firered", 3, "g3_single")
|
|
local org = connectPeer(OnlinePanel, imp, "LEAF#102",
|
|
{ variant(base, "leafgreen", "g3_single") }, "launcher", "leafgreen")
|
|
local made = org.createTournament({ profile = variant(base, "leafgreen", "g3_single"),
|
|
rule = { partySize = 3 }, playing = false, shotClock = 6, maxSpectators = 8,
|
|
public = false })
|
|
waitUntil(OnlinePanel, imp, function() return made.done end, "the peer tournament", 8)
|
|
local code = org.tournament() and org.tournament().code
|
|
log("peer tour code", tostring(code))
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "tournament")
|
|
if code then
|
|
imp._onlineFocus = OnlinePanel.TOUR_CODE_FIELD
|
|
OnlinePanel.fieldType(imp, OnlinePanel.TOUR_CODE_FIELD, code:lower())
|
|
end
|
|
end
|
|
|
|
function STATES.upgrade(OnlinePanel, imp)
|
|
local st = setup(OnlinePanel, imp, "firered", 3)
|
|
waitUntil(OnlinePanel, imp, function() return OnlinePanel.myProfile(imp) ~= nil end,
|
|
"the panel profile", 20)
|
|
local Protocol2 = require("src.online.Protocol2")
|
|
local was = Protocol2.PROTOCOL
|
|
Protocol2.PROTOCOL = 2
|
|
OnlinePanel.connect(imp)
|
|
Protocol2.PROTOCOL = was
|
|
waitUntil(OnlinePanel, imp, function() return Main().upgradeRequired() ~= nil end,
|
|
"upgrade_required", 8)
|
|
log("upgrade", tostring(Main().state()), tostring(Main().error()), tostring(st.status))
|
|
OnlinePanel.home(imp)
|
|
end
|
|
|
|
STATES["g1-play"] = function(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "red", 1, nil)
|
|
if not base then return end
|
|
local blue = connectPeer(OnlinePanel, imp, "BLUE#221", { copy(base) }, "launcher", "red")
|
|
hostRoom(OnlinePanel, imp, blue, { intent = "battle", profile = copy(base), playing = true,
|
|
maxSpectators = 4, private = false, seats = 2, auto = false, note = "first to three" })
|
|
local green = connectPeer(OnlinePanel, imp, "GREEN#009", { copy(base) }, "launcher", "red")
|
|
hostRoom(OnlinePanel, imp, green, { intent = "trade", profile = copy(base), playing = true,
|
|
maxSpectators = 0, private = false, seats = 2, auto = false })
|
|
waitUntil(OnlinePanel, imp, lobbyHas(OnlinePanel, imp, 2), "gen 1 rows", 8)
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "play")
|
|
end
|
|
|
|
STATES["g1-join"] = function(OnlinePanel, imp)
|
|
local _, base = goOnline(OnlinePanel, imp, "red", 1, nil)
|
|
if not base then return end
|
|
local blue = connectPeer(OnlinePanel, imp, "BLUE#221", { copy(base) }, "launcher", "red")
|
|
local id = hostRoom(OnlinePanel, imp, blue, { intent = "battle", profile = copy(base),
|
|
playing = true, maxSpectators = 4, private = false, seats = 2, auto = false })
|
|
waitUntil(OnlinePanel, imp, lobbyHas(OnlinePanel, imp, 1), "gen 1 row", 8)
|
|
OnlinePanel.home(imp)
|
|
OnlinePanel.go(imp, "play")
|
|
local entry = rowFor(OnlinePanel, imp, "BLUE#221")
|
|
if entry then
|
|
OnlinePanel.startJoin(imp, OnlinePanel.targetFor(entry, "player"))
|
|
local st = OnlinePanel.state(imp)
|
|
if st.wizard then
|
|
OnlinePanel.wizardTo(imp, "summary")
|
|
OnlinePanel.wizardNext(imp)
|
|
end
|
|
end
|
|
waitUntil(OnlinePanel, imp, function()
|
|
local r = Main().room()
|
|
return r and r.room == id and #(r.players or {}) == 2
|
|
end, "the gen 1 room", 8)
|
|
log("g1 room", tostring(Main().room() and Main().room().room), tostring(id))
|
|
OnlinePanel.go(imp, "room")
|
|
end
|
|
|
|
STATES["g1-trade"] = function(OnlinePanel, imp)
|
|
local _, tr, peer = tradePair(OnlinePanel, imp, "red", "red")
|
|
OnlinePanel.remotePick(imp, 1)
|
|
if peer then peer:pick(1) end
|
|
waitUntil(OnlinePanel, imp, function()
|
|
return tr.remote and tr.remote:stage() == "confirming" and peer and peer:stage() == "confirming"
|
|
end, "both confirm prompts", 8)
|
|
end
|
|
|
|
return function(OnlinePanel, imp, want)
|
|
require("src.ui.kit.Transition").reduceMotion = true
|
|
hookUpdate(OnlinePanel)
|
|
local run = STATES[want]
|
|
if not run then
|
|
log("unknown state", tostring(want))
|
|
return
|
|
end
|
|
local ok, err = xpcall(function() run(OnlinePanel, imp) end, debug.traceback)
|
|
if not ok then log("ERROR", tostring(err)) end
|
|
settle(OnlinePanel, imp, 0.3)
|
|
log("screen", tostring(OnlinePanel.screen(imp)), "status", tostring(OnlinePanel.state(imp).status))
|
|
end
|