Skip to content

Instantly share code, notes, and snippets.

@h-4-t

h-4-t/main.lua Secret

Created September 23, 2021 12:20
Show Gist options
  • Save h-4-t/1b580f0b3b77ed987fe2c6c6168a1c79 to your computer and use it in GitHub Desktop.
Save h-4-t/1b580f0b3b77ed987fe2c6c6168a1c79 to your computer and use it in GitHub Desktop.
BOI's Memento v1.0
local mod = RegisterMod("isaac-memento", 2)
local socket = require "socket"
local json = require "json"
local os = require "os"
local url = "++BOI_CONFIG_URL++"
local port = "++BOI_CONFIG_PORT++"
local token = "++BOI_CONFIG_TOKEN++"
local version = "1.0"
local client
local initialInit = false
local text2print = Game():GetSeeds():GetStartSeedString()
local isItContinue = false
local function sendMessage(msg)
if client then
if type(msg) ~= "table" then
msg = {
seed = Game():GetSeeds():GetStartSeedString(),
token = token,
type = "msg",
msg = tostring(msg),
epoch = os.time()
}
end
client:send(json.encode(msg) .. "\n")
end
end
local function tryConnect(initial)
if initial then
client = socket.tcp()
success = client:connect(url, port)
if success then
client:settimeout(0.01)
Isaac.DebugString("Done: " .. tostring(client))
_G["print"] = function(...)
local t = table.pack(...)
if #t > 0 then
local msg = tostring(t[1])
for i = 2, #t do
msg = msg .. "\t" .. tostring(t[i])
end
sendMessage(msg)
end
end
initialInit = true
else
client = nil
end
end
if client then
return
end
end
function mod:init(player)
Isaac.DebugString("Initialize networking...")
tryConnect(true)
end
function mod:render()
local cR = 1.0
local cG = 0.0
if client then
cR = 0.0
cG = 1.0
end
local p = Game():GetPlayer(0)
local pos = Isaac.WorldToRenderPosition(p.Position, true) + Game():GetRoom():GetRenderScrollOffset()
Isaac.RenderText(text2print, pos.X - 3 * #text2print, pos.Y + 3, cR, cG, 0.0, 1.0)
end
local function sendHealthStatus()
local function cntBits(num)
local r = 0
for i = 0, 11 do
if (num >> i) % 2 ~= 0 then
r = r + 1
end
end
return r
end
local p = Game():GetPlayer(0)
local msg = {
type = "health-status",
seed = Game():GetSeeds():GetStartSeedString(),
token = token,
epoch = os.time(),
red = p:GetHearts(),
max = p:GetMaxHearts(),
soul = p:GetSoulHearts(),
black = 2 * cntBits(p:GetBlackHearts()),
blackmask = p:GetBlackHearts(),
gold = p:GetGoldenHearts(),
eternal = p:GetEternalHearts(),
life = p:GetExtraLives(),
has_fullred = p:HasFullHearts(),
has_fullredsoul = p:HasFullHeartsAndSoulHearts(),
broken = p:GetBrokenHearts(),
rotten = p:GetRottenHearts(),
soul_charge = p:GetSoulCharge(),
blood_charge = p:GetBloodCharge(),
ingame_time = (Game().TimeCounter) / 30
}
sendMessage(msg)
end
local function sendPlayerStatus()
local p = Game():GetPlayer(0)
local msg = {
type = "player-status",
token = token,
seed = Game():GetSeeds():GetStartSeedString(),
epoch = os.time(),
canfly = p.CanFly,
damage = p.Damage,
luck = p.Luck,
maxfiredelay = p.MaxFireDelay,
movespeed = p.MoveSpeed,
shotspeed = p.ShotSpeed,
firedelay = p.FireDelay,
tearflags = p.TearFlags,
tearheight = p.TearHeight,
tearfallingspeed = p.TearFallingSpeed,
ingame_time = (Game().TimeCounter) / 30,
name = p:GetName()
}
sendMessage(msg)
end
local function sendSeedStatus()
local s = Game():GetSeeds()
local l = Game():GetLevel()
local msg = {
type = "seed-status",
seed = Game():GetSeeds():GetStartSeedString(),
epoch = os.time(),
count_effect = s:CountSeedEffects(),
token = token,
version = version,
player_init = s:GetPlayerInitSeed(),
start_seed = s:GetStartSeed(),
start_string = s:GetStartSeedString(),
ingame_time = (Game().TimeCounter) / 30,
custom_run = s:IsCustomRun(),
difficulty = Game().Difficulty
}
sendMessage(msg)
end
local function sendLootStatus()
local p = Game():GetPlayer(0)
local msg = {
type = "loot-status",
seed = Game():GetSeeds():GetStartSeedString(),
epoch = os.time(),
token = token,
count_bombs = p:GetNumBombs(),
count_coins = p:GetNumCoins(),
count_keys = p:GetNumKeys(),
has_gold_key = p:HasGoldenKey(),
has_gold_bomb = p:HasGoldenBomb(),
ingame_time = (Game().TimeCounter) / 30,
is_holdingitem = p:IsHoldingItem(),
count_collectible = p:GetCollectibleCount()
}
sendMessage(msg)
end
local function ItemList()
local itemz = {}
for i = 0, 730, 1 do
if (Game():GetPlayer(0):GetCollectibleNum(i) == 1) then
table.insert(itemz, i)
end
end
return itemz
end
local function PillEffects()
local pillz = {}
for i = 0, 15, 1 do
data = {}
data.color = i
data.effect = Game():GetItemPool():GetPillEffect(i, Game():GetPlayer(0))
table.insert(pillz, data)
end
return pillz
end
local function sendItems()
local p = Game():GetPlayer(0)
local l = Game():GetLevel()
local msg = {
type = "item-status",
token = token,
seed = Game():GetSeeds():GetStartSeedString(),
epoch = os.time(),
ingame_time = (Game().TimeCounter) / 30,
items = ItemList(),
cards = {slot0 = p:GetCard(0), slot1 = p:GetCard(1)},
trinkets = {slot0 = p:GetTrinket(0), slot1 = p:GetTrinket(1)},
pills = {slot0 = p:GetPill(0), slot1 = p:GetPill(1)},
effects = PillEffects(),
count_item = p:GetCollectibleCount(),
level = l:GetAbsoluteStage(),
room = l:GetCurrentRoomIndex()
}
sendMessage(msg)
end
local function sendChargeStatus()
local p = Game():GetPlayer(0)
local msg = {
type = "charge-status",
seed = Game():GetSeeds():GetStartSeedString(),
epoch = os.time(),
hasActiveItem = (p:GetActiveItem() ~= -1),
token = token,
ingame_time = (Game().TimeCounter) / 30,
needsCharge = p:NeedsCharge(),
slots = {p:GetActiveItem(0), p:GetActiveItem(1), p:GetActiveItem(2), p:GetActiveItem(3)}
}
sendMessage(msg)
end
local function sendRoomStatus()
local l = Game():GetLevel()
local r = l:GetCurrentRoom()
local d = l:GetCurrentRoomDesc()
local msg = {
type = "room-status",
token = token,
seed = Game():GetSeeds():GetStartSeedString(),
epoch = os.time(),
level = l:GetAbsoluteStage(),
room_idx = l:GetCurrentRoomIndex(),
room_visited = d.VisitedCount,
room_idx_list = d.ListIndex,
room_idx_grid = d.GridIndex,
room_idx_safegrid = d.SafeGridIndex,
room_awardseed = d.AwardSeed,
room_cleared = d.Clear,
room_challengedone = d.ChallengeDone,
room_display = d.DisplayFlags,
room_haswater = d.HasWater,
room_noreward = d.NoReward,
room_pits = d.PitsCount,
room_poop = d.PoopCount,
room_plates = d.PressurePlatesTriggered,
room_sacrificedone = d.SacrificeDone,
room_shopdiscountidx = d.ShopItemDiscountIdx,
room_shopitemidx = d.ShopItemIdx,
room_miniboss = d.SurpriseMiniboss,
room_count_boss = r:GetAliveBossesCount(),
room_count_enem = r:GetAliveEnemiesCount(),
room_devil = r:GetDevilRoomChance(),
room_delirium = r:GetDeliriumDistance(),
room_dungeonrock = r:GetDungeonRockIdx(),
room_redheart_damage = r:GetRedHeartDamage(),
room_shape = r:GetRoomShape(),
room_shoplevel = r:GetShopLevel(),
room_spawnseed = r:GetSpawnSeed(),
room_taintedrock = r:GetTintedRockIdx(),
room_type = r:GetType(),
room_firstblood = r:IsFirstEnemyDead(),
ingame_time = (Game().TimeCounter) / 30
}
sendMessage(msg)
end
local function sendLevelStatus()
local l = Game():GetLevel()
local function hasRoom(t)
local rng = RNG()
local idx1 = Game():GetLevel():QueryRoomTypeIndex(t, false, rng)
rng:Next()
local idx2 = Game():GetLevel():QueryRoomTypeIndex(t, false, rng)
rng:Next()
local idx3 = Game():GetLevel():QueryRoomTypeIndex(t, false, rng)
return (idx1 ~= -1) and (idx1 == idx2) and (idx1 == idx3)
end
local data = {
type = "level-status",
epoch = os.time(),
seed = Game():GetSeeds():GetStartSeedString(),
token = token,
ingame_time = (Game().TimeCounter) / 30,
level_stage = (l:GetAbsoluteStage()),
level_angel = (l:GetAngelRoomChance()),
level_cursename = (l:GetCurseName()),
level_curses = (l:GetCurses()),
level_dungeon_seed = (l:GetDungeonPlacementSeed()),
level_name = (l:GetName()),
level_room_count = (l:GetRoomCount()),
level_startroom_idx = (l:GetStartingRoomIndex()),
level_has_bosschal = (l:HasBossChallenge()),
level_is_alt = (l:IsAltStage()),
level_nextstage = (l:IsNextStageAvailable()),
level_dungeon_returnidx = (l.DungeonReturnRoomIndex),
level_has_shop = hasRoom(RoomType.ROOM_SHOP),
level_has_treasure = hasRoom(RoomType.ROOM_TREASURE),
level_has_secret = hasRoom(RoomType.ROOM_SECRET),
level_has_angel = hasRoom(RoomType.ROOM_ANGEL),
level_has_devil = hasRoom(RoomType.ROOM_DEVIL),
level_has_supersecret = hasRoom(RoomType.ROOM_SUPERSECRET),
level_has_arcade = hasRoom(RoomType.ROOM_ARCADE),
level_has_sacrifice = hasRoom(RoomType.ROOM_SACRIFICE),
level_has_curse = hasRoom(RoomType.ROOM_CURSE),
level_has_challenge = hasRoom(RoomType.ROOM_CHALLENGE),
level_has_library = hasRoom(RoomType.ROOM_LIBRARY),
level_has_dungeon = hasRoom(RoomType.ROOM_DUNGEON),
level_has_isaacs = hasRoom(RoomType.ROOM_ISAACS),
level_has_barren = hasRoom(RoomType.ROOM_BARREN),
level_has_dice = hasRoom(RoomType.ROOM_DICE),
level_has_error = hasRoom(RoomType.ROOM_ERROR),
level_has_blackmarket = hasRoom(RoomType.ROOM_BLACK_MARKET),
level_has_bossrush = hasRoom(RoomType.ROOM_BOSSRUSH),
level_has_miniboss = hasRoom(RoomType.ROOM_MINIBOSS),
level_has_chest = hasRoom(RoomType.ROOM_CHEST),
level_has_greedexit = hasRoom(RoomType.ROOM_GREED_EXIT),
level_has_planetarium = hasRoom(RoomType.ROOM_PLANETARIUM),
level_has_teleporter = hasRoom(RoomType.ROOM_TELEPORTER),
level_has_teleporterexit = hasRoom(RoomType.ROOM_TELEPORTER_EXIT),
level_has_ultrasecret = hasRoom(RoomType.ROOM_ULTRASECRET)
}
sendMessage(data)
end
local lastCharge = {}
local lastHealth = {}
local lastStats = {}
local lastLoot = {}
local lastRoom = {}
local lastSeed = {}
local lastItems = {}
lastItems.items = {0}
lastItems.cards = {slot0 = 0, slot1 = 0}
lastItems.trinkets = {slot0 = 0, slot1 = 0}
lastItems.pills = {slot0 = 0, slot1 = 0}
lastCharge.cooldown = (Game().TimeCounter) / 30
lastHealth.cooldown = (Game().TimeCounter) / 30
lastStats.cooldown = (Game().TimeCounter) / 30
lastLoot.cooldown = (Game().TimeCounter) / 30
local gamepaused = false
function mod:update()
if client then
local cmd, err = client:receive("*line")
if err and err ~= "timeout" then
Isaac.DebugString("CLI: " .. err)
client = nil
return
end
if cmd then
Isaac.DebugString("Received command: " .. tostring(cmd))
_G["mod"] = mod
local ok, err =
pcall(
function()
local command, err = load("return " .. cmd)
if command then
local data = command()
if data.type == "run" then
local script, err = load(data.code)
if script then
sendMessage {
type = "rce-status",
token = token,
msg = tostring(data.code),
epoch = os.time(),
token = token,
seed = Game():GetSeeds():GetStartSeedString(),
ingame_time = (Game().TimeCounter) / 30
}
script()
else
sendMessage {
type = "err-status",
token = token,
msg = ("Failed to compile code: " .. tostring(err)),
epoch = os.time(),
token = token,
seed = Game():GetSeeds():GetStartSeedString(),
ingame_time = (Game().TimeCounter) / 30
}
end
elseif data.type == "text2print" then
text2print = tostring(data.code)
end
else
sendMessage {
type = "err-status",
token = token,
msg = ("Failed to unpack data: " .. tostring(err)),
epoch = os.time(),
ingame_time = (Game().TimeCounter) / 30
}
end
end
)
if not ok then
sendMessage {
type = "err-status",
token = token,
msg = err or "Unknown error!",
epoch = os.time(),
ingame_time = (Game().TimeCounter) / 30
}
end
_G["mod"] = nil
end
else
if Isaac.GetFrameCount() % 60 == 0 then
tryConnect(false)
end
end
if Isaac.GetFrameCount() < 10 then
return
end
local currentCharge = Game():GetPlayer(0):GetActiveCharge()
local currentActiveItem = Game():GetPlayer(0):GetActiveItem()
if ((Game().TimeCounter) / 30 - lastCharge.cooldown > 0.5) then
if (lastCharge.lastActiveItem ~= currentActiveItem) or (lastCharge.lastItemCharge ~= currentCharge) then
sendChargeStatus()
lastCharge.lastItemCharge = currentCharge
lastCharge.lastActiveItem = currentActiveItem
lastCharge.cooldown = (Game().TimeCounter) / 30
end
end
local p = Game():GetPlayer(0)
local l = Game():GetLevel()
local r = l:GetCurrentRoomDesc()
local s = Game():GetSeeds()
if ((Game().TimeCounter) / 30 - lastHealth.cooldown > 0.5) then
if
((p:GetMaxHearts() ~= lastHealth.max) or (p:GetHearts() ~= lastHealth.red) or
(p:GetSoulHearts() ~= lastHealth.soul) or
(p:GetBlackHearts() ~= lastHealth.black) or
(p:GetGoldenHearts() ~= lastHealth.gold) or
(p:GetEternalHearts() ~= lastHealth.eternal) or
(p:GetExtraLives() ~= lastHealth.life))
then
sendHealthStatus()
lastHealth.red = p:GetHearts()
lastHealth.max = p:GetMaxHearts()
lastHealth.soul = p:GetSoulHearts()
lastHealth.black = p:GetBlackHearts()
lastHealth.gold = p:GetGoldenHearts()
lastHealth.eternal = p:GetEternalHearts()
lastHealth.life = p:GetExtraLives()
lastHealth.has_fullred = p:HasFullHearts()
lastHealth.has_fullredsoul = p:HasFullHeartsAndSoulHearts()
lastHealth.cooldown = (Game().TimeCounter) / 30
end
end
if ((Game().TimeCounter) / 30 - lastStats.cooldown > 0.5) then
if
(p.CanFly ~= lastStats.canfly or p.Damage ~= lastStats.damage or p.Luck ~= lastStats.luck or
p.MaxFireDelay ~= lastStats.maxfiredelay or
p.MoveSpeed ~= lastStats.movespeed or
p.ShotSpeed ~= lastStats.shotspeed or
p.TearFallingSpeed ~= lastStats.tearfallingspeed or
p.TearFlags ~= lastStats.tearflags or
p.TearHeight ~= lastStats.tearheight or
p:GetName() ~= lastStats.name)
then
sendPlayerStatus()
lastStats.canfly = p.CanFly
lastStats.damage = p.Damage
lastStats.luck = p.Luck
lastStats.maxfiredelay = p.MaxFireDelay
lastStats.movespeed = p.MoveSpeed
lastStats.shotspeed = p.ShotSpeed
lastStats.tearfallingspeed = p.TearFallingSpeed
lastStats.tearflags = p.TearFlags
lastStats.tearheight = p.TearHeight
lastStats.name = p:GetName()
lastStats.cooldown = (Game().TimeCounter) / 30
end
end
local has_changed = false
if p:GetCard(0) ~= lastItems.cards.slot0 then
lastItems.cards.slot0 = p:GetCard(0)
has_changed = true
end
if p:GetCard(1) ~= lastItems.cards.slot1 then
lastItems.cards.slot1 = p:GetCard(1)
has_changed = true
end
if p:GetTrinket(0) ~= lastItems.trinkets.slot0 then
lastItems.trinkets.slot0 = p:GetTrinket(0)
has_changed = true
end
if p:GetTrinket(1) ~= lastItems.trinkets.slot1 then
lastItems.trinkets.slot1 = p:GetTrinket(1)
has_changed = true
end
if p:GetPill(0) ~= lastItems.pills.slot0 then
lastItems.pills.slot0 = p:GetPill(0)
has_changed = true
end
if p:GetPill(1) ~= lastItems.pills.slot1 then
lastItems.pills.slot1 = p:GetPill(1)
has_changed = true
end
if p:GetCollectibleCount() ~= lastItems.count_item then
lastItems.items = ItemList()
lastItems.count_item = p:GetCollectibleCount()
has_changed = true
end
if has_changed then
sendItems()
has_changed = false
end
if ((Game().TimeCounter) / 30 - lastLoot.cooldown > 0.5) then
if
(p:GetNumBombs() ~= lastLoot.count_bombs or p:GetNumCoins() ~= lastLoot.count_coins or
p:GetNumKeys() ~= lastLoot.count_keys or
p:HasGoldenKey() ~= lastLoot.has_gold_key or
p:HasGoldenBomb() ~= lastLoot.has_gold_bomb or
p:IsHoldingItem() ~= lastLoot.is_holdingitem)
then
sendLootStatus()
lastLoot.count_bombs = p:GetNumBombs()
lastLoot.count_coins = p:GetNumCoins()
lastLoot.count_keys = p:GetNumKeys()
lastLoot.has_gold_key = p:HasGoldenKey()
lastLoot.has_gold_bomb = p:HasGoldenBomb()
lastLoot.is_holdingitem = p:IsHoldingItem()
lastLoot.cooldown = (Game().TimeCounter) / 30
end
end
if l:GetAbsoluteStage() ~= lastRoom.level or initialInit then
sendLevelStatus()
end
if
l:GetAbsoluteStage() ~= lastRoom.level or l:GetCurseName() ~= lastRoom.level_curse or
l:GetAngelRoomChance() ~= lastRoom.level_angel or
l:GetCurrentRoomIndex() ~= lastRoom.room_idx or
r.VisitedCount ~= lastRoom.room_visited or
r.ListIndex ~= lastRoom.room_idx_list or
r.GridIndex ~= lastRoom.room_idx_grid or
r.SafeGridIndex ~= lastRoom.room_idx_safegrid or
r.AwardSeed ~= lastRoom.room_awardseed or
r.Clear ~= lastRoom.room_cleared or
r.ChallengeDone ~= lastRoom.room_challengedone or
r.DeliriumDistance ~= lastRoom.room_delirium or
r.DisplayFlags ~= lastRoom.room_display or
r.HasWater ~= lastRoom.room_haswater or
r.NoReward ~= lastRoom.room_noreward or
r.PitsCount ~= lastRoom.room_pits or
r.PoopCount ~= lastRoom.room_poop or
r.PressurePlatesTriggered ~= lastRoom.room_plates or
r.SacrificeDone ~= lastRoom.room_sacrificedone or
r.ShopItemDiscountIdx ~= lastRoom.room_shopdiscountidx or
r.ShopItemIdx ~= lastRoom.room_shopitemidx or
r.SpawnSeed ~= lastRoom.room_spawnseed or
r.SurpriseMiniboss ~= lastRoom.room_miniboss
then
sendRoomStatus()
lastRoom.level = l:GetAbsoluteStage()
lastRoom.level_curse = l:GetCurseName()
lastRoom.level_angel = l:GetAngelRoomChance()
lastRoom.room_idx = l:GetCurrentRoomIndex()
lastRoom.room_visited = r.VisitedCount
lastRoom.room_idx_list = r.ListIndex
lastRoom.room_idx_grid = r.GridIndex
lastRoom.room_idx_safegrid = r.SafeGridIndex
lastRoom.room_awardseed = r.AwardSeed
lastRoom.room_cleared = r.Clear
lastRoom.room_challengedone = r.ChallengeDone
lastRoom.room_delirium = r.DeliriumDistance
lastRoom.room_display = r.DisplayFlags
lastRoom.room_haswater = r.HasWater
lastRoom.room_noreward = r.NoReward
lastRoom.room_pits = r.PitsCount
lastRoom.room_poop = r.PoopCount
lastRoom.room_plates = r.PressurePlatesTriggered
lastRoom.room_sacrificedone = r.SacrificeDone
lastRoom.room_shopdiscountidx = r.ShopItemDiscountIdx
lastRoom.room_shopitemidx = r.ShopItemIdx
lastRoom.room_spawnseed = r.SpawnSeed
lastRoom.room_miniboss = r.SurpriseMiniboss
end
if s:IsInitialized() == true then
if
s:CountSeedEffects() ~= lastSeed.count_effect or s:GetPlayerInitSeed() ~= lastSeed.player_init or
s:GetStartSeed() ~= lastSeed.start_seed or
s:GetStartSeedString() ~= lastSeed.start_string or
s:IsCustomRun() ~= lastSeed.custom_run
then
sendSeedStatus()
lastSeed.count_effect = s:CountSeedEffects()
lastSeed.player_init = s:GetPlayerInitSeed()
lastSeed.start_seed = s:GetStartSeed()
lastSeed.start_string = s:GetStartSeedString()
lastSeed.custom_run = s:IsCustomRun()
end
end
if initialInit then
local msg = {
type = "game-status",
status = "initialized",
token = token,
version = version,
epoch = os.time(),
ingame_time = (Game().TimeCounter) / 30,
seed = Game():GetSeeds():GetStartSeedString(),
difficulty = Game().Difficulty,
continue = isItContinue
}
tryConnect(true)
sendMessage(msg)
text2print = Game():GetSeeds():GetStartSeedString()
initialInit = false
sendSeedStatus()
sendLevelStatus()
sendPlayerStatus()
sendHealthStatus()
sendLootStatus()
sendItems()
sendChargeStatus()
end
if Game():GetLevel():GetAbsoluteStage() ~= lastStage then
sendSeedStatus()
sendLevelStatus()
sendPlayerStatus()
sendHealthStatus()
sendLootStatus()
sendItems()
sendChargeStatus()
text2print = Game():GetSeeds():GetStartSeedString()
lastStage = Game():GetLevel():GetAbsoluteStage()
end
end
mod:AddCallback(ModCallbacks.MC_POST_PLAYER_INIT, mod.init)
mod:AddCallback(ModCallbacks.MC_POST_UPDATE, mod.update)
mod:AddCallback(ModCallbacks.MC_POST_RENDER, mod.render)
local function onStart(_, bool)
local msg = {
type = "game-status",
status = "started",
token = token,
version = version,
epoch = os.time(),
ingame_time = (Game().TimeCounter) / 30,
continue = bool
}
isItContinue = bool
sendMessage(msg)
end
local function onEnd(_, bool)
local msg = {
type = "game-status",
status = "ended",
seed = Game():GetSeeds():GetStartSeedString(),
epoch = os.time(),
ingame_time = (Game().TimeCounter) / 30,
token = token,
died = bool,
continue = false
}
sendMessage(msg)
initialInit = false
end
local function onExit(_, bool)
local msg = {
type = "game-status",
status = "exited",
epoch = os.time(),
seed = Game():GetSeeds():GetStartSeedString(),
ingame_time = (Game().TimeCounter) / 30,
token = token,
continue = bool
}
sendMessage(msg)
initialInit = false
end
local function onNewLevel()
sendLevelStatus()
end
mod:AddCallback(ModCallbacks.MC_POST_GAME_STARTED, onStart)
mod:AddCallback(ModCallbacks.MC_POST_GAME_END, onEnd)
mod:AddCallback(ModCallbacks.MC_PRE_GAME_EXIT, onExit)
mod:AddCallback(ModCallbacks.MC_POST_NEW_LEVEL, onNewLevel)
for i, v in pairs(ModCallbacks) do
mod:AddCallback(
v,
function(...)
if mod[i] then
local args = table.pack(...)
local ok, result =
pcall(
function()
mod[i](table.unpack(args))
end
)
if not ok and client then
sendMessage {
type = "err",
token = token,
msg = "Failed to execute " .. v .. ": " .. tostring(result)
}
end
end
end
)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment