-
-
Save h-4-t/1b580f0b3b77ed987fe2c6c6168a1c79 to your computer and use it in GitHub Desktop.
BOI's Memento v1.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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