mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 05:32:07 -04:00
171 lines
6.5 KiB
Lua
171 lines
6.5 KiB
Lua
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.harness")
|
|
if not _G.love then _G.love = require("tests.love_stub") end
|
|
|
|
local Cache = require("tests.game3_cache")
|
|
if not Cache.mount("meta.json") then
|
|
print("[skip] online_trade_relay3: " .. tostring(Cache.reason))
|
|
os.exit(0)
|
|
end
|
|
|
|
local okR, FakeRelay = pcall(require, "tests.support.fake_relay")
|
|
if not okR then
|
|
print("[skip] online_trade_relay3: no tests/support/fake_relay.lua: " .. tostring(FakeRelay))
|
|
os.exit(0)
|
|
end
|
|
|
|
local GameVersion = require("src.core.GameVersion")
|
|
GameVersion.set("firered")
|
|
local SaveData = require("src.core.SaveData")
|
|
local Trade = require("src.online.Trade")
|
|
local Fingerprint = require("src.link.Fingerprint")
|
|
local Pokemon = require("src.core.game3.pokemon")
|
|
local Party = require("src.core.game3.party")
|
|
local Schema = require("src.core.game3.save_schema_firered")
|
|
local RelayTransport = require("src.core.game3.link.relay_transport")
|
|
local Version = require("src.core.Version")
|
|
Pokemon.install(nil)
|
|
|
|
local files = {}
|
|
SaveData.portableFs = function()
|
|
return {
|
|
getInfo = function(name) return files[name] and { type = "file" } or nil end,
|
|
read = function(name) return files[name] end,
|
|
write = function(name, body) files[name] = body return true end,
|
|
remove = function(name) files[name] = nil return true end,
|
|
createDirectory = function() return true end,
|
|
}
|
|
end
|
|
|
|
local cache = require("src.core.game3.dataset").cache()
|
|
local fingerprint = Fingerprint.compute({ generation = 3,
|
|
gen3Inputs = Fingerprint.gen3Inputs(function(rel) return cache:read(rel) end) }, {}, 3)
|
|
local PROFILE = { engine = 3, version = "firered", engineVersion = Version.engine,
|
|
apiVersion = Version.modApi, fingerprint = fingerprint, rulesetId = "g3_link",
|
|
kind = "vanilla", rule = {} }
|
|
|
|
local function newClient(relay, seat)
|
|
package.loaded["src.online.Client"] = nil
|
|
local Client = require("src.online.Client")
|
|
Client.reset()
|
|
Client.configure({ relayAddress = "fake:1", connect = function() return seat.transport end })
|
|
return Client
|
|
end
|
|
|
|
local function makeSave(version, name, trainerId, mons)
|
|
local session = Schema.newGame({ version = version, name = name, rngSeed = trainerId })
|
|
session.trainerId = trainerId
|
|
session.dex.nationalUnlocked = true
|
|
session.party = {}
|
|
for _, row in ipairs(mons) do
|
|
assert(Party.giveMon(session, row.species, row.level))
|
|
local mon = session.party[#session.party]
|
|
for k, v in pairs(row.extra or {}) do mon[k] = v end
|
|
end
|
|
return SaveData.decode(SaveData.encode(Schema.toSaveTable(session)))
|
|
end
|
|
|
|
local DATA = { generation = 3, Pokemon = Pokemon, pokemon = Pokemon }
|
|
|
|
local function handle(version, slotId, save)
|
|
local path = Trade.slotPath(version, slotId)
|
|
files[path] = SaveData.encode(save)
|
|
return { version = version, generation = 3, slotId = slotId, save = save,
|
|
path = path, party = save.party, data = DATA }
|
|
end
|
|
|
|
local function setup(slot)
|
|
local relay = FakeRelay.new()
|
|
local seatA = relay:seat("a0000001", "RED")
|
|
local seatB = relay:seat("b0000002", "LEAF")
|
|
local B = newClient(relay, seatB)
|
|
local A = newClient(relay, seatA)
|
|
local function step(n)
|
|
for _ = 1, n or 1 do
|
|
relay:pump()
|
|
A.update(0)
|
|
B.update(0)
|
|
end
|
|
end
|
|
A.connect({ name = "RED", profiles = { PROFILE } })
|
|
B.connect({ name = "LEAF", profiles = { PROFILE } })
|
|
step(3)
|
|
A.queueDirect({ activity = "trade", ruleset = "g3_link", auto = true, profile = PROFILE,
|
|
avatar = { name = "RED", trainerId = 1, gender = 0, version = "firered" }, preview = { 64 } })
|
|
step(2)
|
|
B.queueDirect({ activity = "trade", ruleset = "g3_link", auto = true, profile = PROFILE,
|
|
avatar = { name = "LEAF", trainerId = 2, gender = 1, version = "leafgreen" }, preview = { 95 } })
|
|
step(3)
|
|
local hA = handle("firered", slot, makeSave("firered", "RED", 11111, {
|
|
{ species = 64, level = 30 }, { species = 25, level = 12 } }))
|
|
local hB = handle("leafgreen", slot, makeSave("leafgreen", "LEAF", 22222, {
|
|
{ species = 95, level = 25, extra = { item = 199, heldItem = 199 } }, { species = 1, level = 8 } }))
|
|
local rsA, rsB = A.roomSession(), B.roomSession()
|
|
local remoteA = Trade.remote(hA, rsA, { transport = RelayTransport.new(rsA, { client = A }) })
|
|
local remoteB = Trade.remote(hB, rsB, { transport = RelayTransport.new(rsB, { client = B }) })
|
|
return { relay = relay, A = A, B = B, step = step, rA = remoteA, rB = remoteB,
|
|
hA = hA, hB = hB, diskA = files[hA.path], diskB = files[hB.path] }
|
|
end
|
|
|
|
local function run(s, n, until_)
|
|
for _ = 1, n do
|
|
s.step(1)
|
|
s.rA:update()
|
|
s.rB:update()
|
|
if until_ and until_() then return true end
|
|
end
|
|
return until_ == nil or until_()
|
|
end
|
|
|
|
do
|
|
local s = setup("slot1")
|
|
T.eq(s.A.seat(), 0, "the AUTO pair seats FireRed first")
|
|
T.check(s.rA ~= nil and s.rB ~= nil, "both launchers open a Gen 3 remote trade")
|
|
s.rA:start()
|
|
s.rB:start()
|
|
T.check(run(s, 12, function()
|
|
return s.rA:stage() == "picking" and s.rB:stage() == "picking"
|
|
end), "both reach the trade menu over the real Client rooms")
|
|
s.rA:pick(1)
|
|
s.rB:pick(1)
|
|
T.check(run(s, 8, function()
|
|
return s.rA:stage() == "confirming" and s.rB:stage() == "confirming"
|
|
end), "the leader sets the mons to trade")
|
|
s.rA:confirm(true)
|
|
s.rB:confirm(true)
|
|
T.check(run(s, 12, function()
|
|
return s.rA:stage() == "committed" and s.rB:stage() == "committed"
|
|
end), "the relay barrier commits both sides: " .. tostring(s.rA:stage()) .. "/"
|
|
.. tostring(s.rB:stage()))
|
|
T.eq(SaveData.decode(files[s.hA.path]).party[1].species, 208, "FireRed holds Steelix")
|
|
T.eq(SaveData.decode(files[s.hB.path]).party[1].species, 65, "LeafGreen holds Alakazam")
|
|
s.rA:close()
|
|
s.rB:close()
|
|
s.step(3)
|
|
T.eq(s.A.room(), nil, "closing leaves the room")
|
|
end
|
|
|
|
do
|
|
local s = setup("slot2")
|
|
s.rA:start()
|
|
s.rB:start()
|
|
run(s, 12, function() return s.rA:stage() == "picking" and s.rB:stage() == "picking" end)
|
|
s.rA:pick(1)
|
|
s.rB:pick(1)
|
|
run(s, 8, function() return s.rA:stage() == "confirming" and s.rB:stage() == "confirming" end)
|
|
s.rB:confirm(true)
|
|
s.rA:confirm(true)
|
|
run(s, 12, function() return s.rB:stage() == "commit_wait" end)
|
|
T.eq(s.rB:stage(), "commit_wait", "seat 1 has confirmed its digest")
|
|
T.eq(s.rA:stage(), "exchange", "seat 0 has not sent its digest yet")
|
|
s.A.leaveRoom()
|
|
run(s, 10, function() return s.rB:stage() == "cancelled" end)
|
|
T.eq(s.rB:stage(), "cancelled", "seat 0 leaving before its digest aborts the trade")
|
|
T.eq(s.rA:stage(), "cancelled", "and seat 0's own trade is off")
|
|
T.eq(files[s.hA.path], s.diskA, "nothing written on seat 0")
|
|
T.eq(files[s.hB.path], s.diskB, "nothing written on seat 1")
|
|
end
|
|
|
|
T.finish()
|