Skip to content

Commit 6dd8045

Browse files
committed
test(events): MC integration tests for @on(PlayerJoin) and @on(PlayerDeath)
1 parent 1a508e6 commit 6dd8045

1 file changed

Lines changed: 178 additions & 0 deletions

File tree

src/__tests__/mc-integration.test.ts

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,3 +1612,181 @@ describe('MC Integration - entity tag methods (@s.tag/untag/has_tag)', () => {
16121612
console.log(` has_after_untag=${hasAfterUntag} (expect 0) ✓`)
16131613
}, 20000)
16141614
})
1615+
1616+
// ===========================================================================
1617+
// fft.mcrs — MC integration test for dft_real array param dynamic indexing
1618+
// ===========================================================================
1619+
describe('MC Integration - fft.mcrs dft_real', () => {
1620+
const NS = 'fft_mc_test'
1621+
1622+
beforeAll(async () => {
1623+
if (!serverOnline) return
1624+
1625+
const MATH_SRC = fs.readFileSync(path.join(__dirname, '../stdlib/math.mcrs'), 'utf-8')
1626+
const FFT_SRC = fs.readFileSync(path.join(__dirname, '../stdlib/fft.mcrs'), 'utf-8')
1627+
1628+
const fftSrc = `
1629+
namespace fft_mc_test
1630+
1631+
@load fn __load() {
1632+
raw("scoreboard objectives add fft_obj dummy");
1633+
_math_init()
1634+
}
1635+
1636+
@keep fn test_dft_re0(): int {
1637+
let input: int[] = [10000, 10000, 10000, 10000]
1638+
let re: int[] = [0, 0, 0, 0]
1639+
let im: int[] = [0, 0, 0, 0]
1640+
dft_real(input, 4, re, im)
1641+
let v: int = re[0]
1642+
scoreboard_set("#dft_re0", "fft_obj", v)
1643+
return v
1644+
}
1645+
1646+
@keep fn test_dft_mag1(): int {
1647+
let input: int[] = [10000, 0, -10000, 0]
1648+
let re: int[] = [0, 0, 0, 0]
1649+
let im: int[] = [0, 0, 0, 0]
1650+
dft_real(input, 4, re, im)
1651+
let mag: int = dft_magnitude(re, im, 1)
1652+
scoreboard_set("#dft_mag1", "fft_obj", mag)
1653+
return mag
1654+
}
1655+
`
1656+
1657+
// Use compile directly with librarySources (writeFixture doesn't support libs)
1658+
fs.mkdirSync(DATAPACK_DIR, { recursive: true })
1659+
if (!fs.existsSync(path.join(DATAPACK_DIR, 'pack.mcmeta'))) {
1660+
fs.writeFileSync(path.join(DATAPACK_DIR, 'pack.mcmeta'), JSON.stringify({
1661+
pack: { pack_format: 48, description: 'RedScript integration tests' }
1662+
}))
1663+
}
1664+
const fftResult = compile(fftSrc, { namespace: NS, librarySources: [MATH_SRC, FFT_SRC] })
1665+
for (const file of fftResult.files) {
1666+
if (file.path === 'pack.mcmeta') continue
1667+
const filePath = path.join(DATAPACK_DIR, file.path)
1668+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
1669+
if (file.path.includes('data/minecraft/tags/') && fs.existsSync(filePath)) {
1670+
const existing = JSON.parse(fs.readFileSync(filePath, 'utf-8'))
1671+
const incoming = JSON.parse(file.content)
1672+
const merged = { values: [...new Set([...(existing.values ?? []), ...(incoming.values ?? [])])] }
1673+
fs.writeFileSync(filePath, JSON.stringify(merged, null, 2))
1674+
} else {
1675+
fs.writeFileSync(filePath, file.content)
1676+
}
1677+
}
1678+
1679+
await mc.reload()
1680+
await mc.ticks(10)
1681+
await mc.command(`/function ${NS}:__load`).catch(() => {})
1682+
await mc.ticks(5)
1683+
})
1684+
1685+
test('dft_real DC input: re[0] == 40000', async () => {
1686+
if (!serverOnline) return
1687+
await mc.command(`/function ${NS}:test_dft_re0`)
1688+
await mc.ticks(3)
1689+
const val = await mc.scoreboard('#dft_re0', 'fft_obj')
1690+
expect(val).toBe(40000)
1691+
}, 20000)
1692+
1693+
test('dft_real quarter-wave: X[1] magnitude ≈ 20000', async () => {
1694+
if (!serverOnline) return
1695+
await mc.command(`/function ${NS}:test_dft_mag1`)
1696+
await mc.ticks(3)
1697+
const val = await mc.scoreboard('#dft_mag1', 'fft_obj')
1698+
expect(val).toBeGreaterThanOrEqual(19500)
1699+
expect(val).toBeLessThanOrEqual(20500)
1700+
}, 20000)
1701+
})
1702+
1703+
// ===========================================================================
1704+
// events.mcrs — MC integration test for @on(EventType) event handler system
1705+
// ===========================================================================
1706+
describe('MC Integration - @on(EventType) event system', () => {
1707+
const NS = 'ev_mc_test'
1708+
let botOnline = false
1709+
1710+
beforeAll(async () => {
1711+
if (!serverOnline) return
1712+
1713+
const EVENTS_SRC = fs.readFileSync(path.join(__dirname, '../stdlib/events.mcrs'), 'utf-8')
1714+
1715+
const evSrc = `
1716+
namespace ev_mc_test
1717+
1718+
@on(PlayerJoin) fn on_join(p: Player) {
1719+
raw("scoreboard objectives add ev_obj dummy");
1720+
scoreboard_add(p, "ev_obj", 1)
1721+
}
1722+
1723+
@on(PlayerDeath) fn on_death(p: Player) {
1724+
raw("scoreboard objectives add ev_obj dummy");
1725+
scoreboard_add(p, "ev_obj", 100)
1726+
}
1727+
`
1728+
1729+
// Compile with events.mcrs as library source
1730+
fs.mkdirSync(DATAPACK_DIR, { recursive: true })
1731+
if (!fs.existsSync(path.join(DATAPACK_DIR, 'pack.mcmeta'))) {
1732+
fs.writeFileSync(path.join(DATAPACK_DIR, 'pack.mcmeta'), JSON.stringify({
1733+
pack: { pack_format: 48, description: 'RedScript integration tests' }
1734+
}))
1735+
}
1736+
const evResult = compile(evSrc, { namespace: NS, librarySources: [EVENTS_SRC] })
1737+
for (const file of evResult.files) {
1738+
if (file.path === 'pack.mcmeta') continue
1739+
const filePath = path.join(DATAPACK_DIR, file.path)
1740+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
1741+
if (file.path.includes('data/minecraft/tags/') && fs.existsSync(filePath)) {
1742+
const existing = JSON.parse(fs.readFileSync(filePath, 'utf-8'))
1743+
const incoming = JSON.parse(file.content)
1744+
const merged = { values: [...new Set([...(existing.values ?? []), ...(incoming.values ?? [])])] }
1745+
fs.writeFileSync(filePath, JSON.stringify(merged, null, 2))
1746+
} else {
1747+
fs.writeFileSync(filePath, file.content)
1748+
}
1749+
}
1750+
1751+
await mc.reload()
1752+
await mc.ticks(20)
1753+
1754+
// Check if TestBot is online
1755+
const status = await mc.status()
1756+
botOnline = status.playerNames?.includes('TestBot') ?? false
1757+
})
1758+
1759+
test('events.mcrs dispatcher loads without error', async () => {
1760+
if (!serverOnline) return
1761+
// If we got here, reload succeeded
1762+
expect(serverOnline).toBe(true)
1763+
}, 10000)
1764+
1765+
test('PlayerJoin: removing rs.joined tag fires @on(PlayerJoin) handlers', async () => {
1766+
if (!serverOnline || !botOnline) return
1767+
1768+
// Reset score
1769+
await mc.command(`scoreboard objectives add ev_obj dummy`).catch(() => {})
1770+
await mc.command(`scoreboard players set TestBot ev_obj 0`)
1771+
1772+
// Simulate "join" by removing the rs.joined tag
1773+
await mc.command(`tag TestBot remove rs.joined`)
1774+
await mc.ticks(3) // wait for @tick to fire
1775+
1776+
const score = await mc.scoreboard('TestBot', 'ev_obj')
1777+
expect(score).toBeGreaterThanOrEqual(1)
1778+
console.log(` PlayerJoin handler fired: ev_obj = ${score} (expect >= 1) ✓`)
1779+
}, 20000)
1780+
1781+
test('PlayerDeath: killing TestBot fires @on(PlayerDeath) handlers', async () => {
1782+
if (!serverOnline || !botOnline) return
1783+
1784+
await mc.command(`scoreboard players set TestBot ev_obj 0`)
1785+
await mc.command(`kill TestBot`)
1786+
await mc.ticks(5)
1787+
1788+
const score = await mc.scoreboard('TestBot', 'ev_obj')
1789+
expect(score).toBeGreaterThanOrEqual(100)
1790+
console.log(` PlayerDeath handler fired: ev_obj = ${score} (expect >= 100) ✓`)
1791+
}, 20000)
1792+
})

0 commit comments

Comments
 (0)