wallLamps = {}
lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids
[3947] = 3948,
[2039] = 2040
}, {}
for k, v in pairs(lampTransformIds) do
reverseLampTransformIds[v] = k
end
function table.size(t)
local size = 0
for k, v in pairs(t) do
size = size + 1
end
return size
end
function serialize(s)
local...
Your question is very confusing, try to clarify further.
Always have a way to do rsWhen you use a wall lamp inside house and turn on the lamp for example, after server save, lamp back to turn off
Always have a way to do rs
You can try:
When server start, the map is loaded with lamp state in .otbm file. You can do a script to execute before server close and search all map for itens with itemID equal to lamp in On/Off state and store the info(position and state) to when server start, get lamp in positions and transform to stored state.
Give a try
Try this:Good idea, but idk how to do this script :/
wall_lamps.lua
and put this inside:local startPos = {x = 0, y = 0, z = 7} --X, Y and Z values where will start searching for Lamps
local finalPos = {x = 50, y = 50, z = 7} --X, Y and Z values where will finish searching for Lamps
local idLampOn = 2051 --ItemId of Lamp in ON state
local idLampOff = 2050 --ItemId of Lamp in OFF state
local filePath = "lampsInMap.txt" --Full Path where .txt file will be saved with lamp states info
--Check all lamps in area and save in file the state
function saveWallLamps()
local lampsInMap = {} --Initialize a empty table that will recive the info of lamps in map
for _posZ = startPos.z, finalPos.z do --For startPosition Z to finalPosition Z
for _posY = startPos.y, finalPos.y do --For startPosition Y to finalPosition Y
for _posX = startPos.x, finalPos.x do--For startPosition X to finalPosition X
local currentPos = Position({x = _posX, y = _posY, z = _posZ})
local currentTile = Tile(currentPos) --Get tile on searched position X Y Z
if currentTile then --If find a tile in position
local lampOn = currentTile:getItemById(idLampOn) --try get item with ID of LampOn in currentTile
local lampOff = currentTile:getItemById(idLampOff) --try get item with ID of LampOff in currentTile
if lampOn ~= nil then --If have item with id of LampOn in tile
table.insert(lampsInMap, {lampPos = currentTile:getPosition(), lampId = idLampOn}) --insert the position and state in table
elseif lampOff ~= nil then --Else If have item with id of LampOff in tile
table.insert(lampsInMap, {lampPos = currentTile:getPosition(), lampId = idLampOff})--insert the position and state in table
end
end
end
end
end
if #lampsInMap > 0 then --If count of lamp infos in Table is more than 1
local tableInStringFormat = dumpTable(lampsInMap) --turn table to string (don't sure if needed)
local file = io.open(filePath, "w") --Open the file in FilePath with "w"(write) mode
file:write(tableInStringFormat) --Write all table to file
file:close() --Close the file
end
return true
end
--read file with lamps data and transform to stored state
function loadWallLamps()
local file = io.open(filePath, "r") --Open the file in FilePath with "r"(read) mode
if not file then --If file don't exist
print("[ERRO] loadWallLamps FILE not found.") --Print erro in console
return false --exit
end
local wallLampsData = file:read("*all")--Get all data from file and save in a variable
file:close() --close the file
local wallLampsTable = loadstring("return "..wallLampsData)() --transform the string variable in table
if #wallLampsTable > 0 then --if have 1 or more index in table
for i = 1, #wallLampsTable do -- for 1 index to all index in table
local targetTile = Tile(wallLampsTable[i].lampPos) --get tile with position stored in table
local targetLampOn = targetTile:getItemById(idLampOn) --try get a lamp on ON state in targetTile
local targetLampOff = targetTile:getItemById(idLampOff) --try get a lamp on OFF state in targetTile
local lampId = wallLampsTable[i].lampId --get the id of lamp stored in table(when server got closed)
if targetLampOn ~= nil and targetLampOn.itemId ~= lampId then --if exist lamp with ON state in tile and the ID is ~= from stored in table
targetLampOn:transform(lampId) --transform the item to stored lampId
elseif targetLampOff ~= nil and targetLampOff.itemId ~= lampId then --if exist lamp with OFF state in tile and the ID is ~= from stored in table
targetLampOff:transform(lampId)--transform the item to stored lampId
end
end
end
return true
end
--transform a table in string
function dumpTable(targetTable)
if type(targetTable) == 'table' then
local s = '{ '
for k,v in pairs(targetTable) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dumpTable(v) .. ','
end
return s .. '} '
else
return tostring(targetTable)
end
end
serverSave function
to:local function serverSave()
if shutdownAtServerSave then
Game.setGameState(GAME_STATE_SHUTDOWN)
saveWallLamps()
else
Game.setGameState(GAME_STATE_CLOSED)
saveWallLamps()
if cleanMapAtServerSave then
cleanMap()
end
Game.setGameState(GAME_STATE_NORMAL)
end
end
loadWallLamps()
wall_lamps.lua
on lib folder.wallLamps = {}
lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids
[1111] = 2222
}, {}
for k, v in pairs(lampTransformIds) do
reverseLampTransformIds[v] = k
end
function table.size(t)
local size = 0
for k, v in pairs(t) do
size = size + 1
end
return size
end
function serialize(s)
local isTable = type(s) == 'table'
local ret = {(isTable and "{" or nil)}
local function doSerialize(s)
if isTable then
local size = table.size(s)
local index = 0
for k, v in pairs(s) do
index = index + 1
local key = (type(k) == 'string') and '"'..k..'"' or k
local val = (type(v) == 'string') and '"'..v..'"' or v
local comma = ((index < size) and ', ' or '')
if type(v) == 'table' then
ret[#ret+1] = ('[%s] = {'):format(key)
doSerialize(v)
ret[#ret+1] = ('}%s'):format(comma)
else
ret[#ret+1] = ('[%s] = %s%s'):format(key, val, comma)
end
end
else
ret[#ret+1] = s
end
end
doSerialize(s)
return (table.concat(ret) .. (isTable and "}" or ""))
end
function unserialize(str)
local f = loadstring("return ".. str)
return f and f() or nil
end
function serializePos(pos)
return string.format('Position(%d, %d, %d)', pos.x, pos.y, pos.z)
end
function unserializePos(s)
return Position(s:match("Position%((%d+), (%d+), (%d+)%)"))
end
function dumpLampStates()
local file = io.open('lamp_states.lua', 'w')
if file then
file:write(serialize(wallLamps))
end
end
function loadLampStates()
local file = io.open('lamp_states.lua')
wallLamps = unserialize(file:read('*a'))
for serializedPos, state in pairs(wallLamps) do
local flippedState = lampTransformIds[state] or reverseLampTransformIds[state]
Tile(unserializePos(serializedPos)):getItemById(state):transform(flippedState)
end
end
loadLampStates()
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
local transformId = lampTransformIds[item:getId()] or reverseLampTransformIds[item:getId()]
item:transform(transformId)
wallLamps[serializePos(toPosition)] = transformId -- update lamp state
dumpLampStates()
return true
end
This would have much better performance using an action script rather than iterating the entire map looking for the lamps.
In a lib file:
Lua:wallLamps = {} lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids [1111] = 2222 }, {} for k, v in pairs(lampTransformIds) do reverseLampTransformIds[v] = k end function table.size(t) local size = 0 for k, v in pairs(t) do size = size + 1 end return size end function serialize(s) local isTable = type(s) == 'table' local ret = {(isTable and "{" or nil)} local function doSerialize(s) if isTable then local size = table.size(s) local index = 0 for k, v in pairs(s) do index = index + 1 local key = (type(k) == 'string') and '"'..k..'"' or k local val = (type(v) == 'string') and '"'..v..'"' or v local comma = ((index < size) and ', ' or '') if type(v) == 'table' then ret[#ret+1] = ('[%s] = {'):format(key) doSerialize(v) ret[#ret+1] = ('}%s'):format(comma) else ret[#ret+1] = ('[%s] = %s%s'):format(key, val, comma) end end else ret[#ret+1] = s end end doSerialize(s) return (table.concat(ret) .. (isTable and "}" or "")) end function unserialize(str) local f = loadstring("return ".. str) return f and f() or nil end function serializePos(pos) return string.format('Position(%d, %d, %d)', pos.x, pos.y, pos.z) end function unserializePos(s) return Position(s:match("Position%((%d+), (%d+), (%d+)%)")) end function dumpLampStates() local file = io.open('lamp_states.lua', 'w') if file then file:write(serialize(wallLamps)) end end function loadLampStates() local file = io.open('lamp_states.lua') wallLamps = unserialize(file:read('*a')) for serializedPos, state in pairs(wallLamps) do local flippedState = lampTransformIds[state] or reverseLampTransformIds[state] Tile(unserializePos(serializedPos)):getItemById(state):transform(flippedState) end end loadLampStates()
Action script (register each wall id to actions.xml, and add it to the lampTransformIds table in the lib file)
Lua:function onUse(player, item, fromPosition, target, toPosition, isHotkey) local transformId = lampTransformIds[item:getId()] or reverseLampTransformIds[item:getId()] item:transform(transformId) wallLamps[serializePos(toPosition)] = transformId -- update lamp state dumpLampStates() return true end
<action itemid="5907" script="others/lamp_states.lua" />
<action itemid="5908" script="others/lamp_states.lua" />
Lua Script Error: [Main Interface]
data/global.lua
cannot open data/lib/lamp_states.lua: No such file or directory
stack traceback:
[C]: at 0x7ff792cb9200
[C]: in function 'dofile'
data/lib/lib.lua:3: in main chunk
[C]: in function 'dofile'
data/global.lua:1: in main chunk
[Warning - ScriptingManager::loadScriptSystems] Can not load data/global.lua
dofile
checks data/lib, not data/lib/core.loadLampStates
with this instead:function loadLampStates()
local file = io.open('lamp_states.lua')
if file then
wallLamps = unserialize(file:read('*a'))
for serializedPos, state in pairs(wallLamps) do
local flippedState = lampTransformIds[state] or reverseLampTransformIds[state]
Tile(unserializePos(serializedPos)):getItemById(state):transform(flippedState)
end
else
io.open('lamp_states.lua', 'w'):close() -- create file if it doesn't exist
end
end
{["Position(32354, 32198, 7)"] = 5908} ["Position(32358, 32198, 7)"] = 5907} ["Position(32358, 32198, 7)"] = 5907}
i did, tested but unfortunately it didn't workChange this (inside dumpLampStates)
ToLua:local file = io.open('lamp_states.lua', 'w')
Lua:local file = io.open('lamp_states.lua', 'w+')
function loadLampStates()
local file = io.open('lamp_states.lua')
print('Loading lamp states')
if file then
wallLamps = unserialize(file:read('*a'))
print('Previous data stored, size: '.. #wallLamps)
for serializedPos, state in pairs(wallLamps) do
local flippedState = lampTransformIds[state] or reverseLampTransformIds[state]
local position = unserializePos(serializedPos)
print(string.format('Restoring previous state of lamp at %s to id %d', position, flippedState))
Tile(position):getItemById(state):transform(flippedState)
end
else
print('Previous data not found, creating an empty file (no data will be loaded).')
io.open('lamp_states.lua', 'w'):close() -- create file if it doesn't exist
end
end
Yeah, this is much better! Would never think of using it that way, thanks!This would have much better performance using an action script rather than iterating the entire map looking for the lamps.
In a lib file:
Lua:wallLamps = {} lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids [1111] = 2222 }, {} for k, v in pairs(lampTransformIds) do reverseLampTransformIds[v] = k end function table.size(t) local size = 0 for k, v in pairs(t) do size = size + 1 end return size end function serialize(s) local isTable = type(s) == 'table' local ret = {(isTable and "{" or nil)} local function doSerialize(s) if isTable then local size = table.size(s) local index = 0 for k, v in pairs(s) do index = index + 1 local key = (type(k) == 'string') and '"'..k..'"' or k local val = (type(v) == 'string') and '"'..v..'"' or v local comma = ((index < size) and ', ' or '') if type(v) == 'table' then ret[#ret+1] = ('[%s] = {'):format(key) doSerialize(v) ret[#ret+1] = ('}%s'):format(comma) else ret[#ret+1] = ('[%s] = %s%s'):format(key, val, comma) end end else ret[#ret+1] = s end end doSerialize(s) return (table.concat(ret) .. (isTable and "}" or "")) end function unserialize(str) local f = loadstring("return ".. str) return f and f() or nil end function serializePos(pos) return string.format('Position(%d, %d, %d)', pos.x, pos.y, pos.z) end function unserializePos(s) return Position(s:match("Position%((%d+), (%d+), (%d+)%)")) end function dumpLampStates() local file = io.open('lamp_states.lua', 'w') if file then file:write(serialize(wallLamps)) end end function loadLampStates() local file = io.open('lamp_states.lua') wallLamps = unserialize(file:read('*a')) for serializedPos, state in pairs(wallLamps) do local flippedState = lampTransformIds[state] or reverseLampTransformIds[state] Tile(unserializePos(serializedPos)):getItemById(state):transform(flippedState) end end loadLampStates()
Action script (register each wall id to actions.xml, and add it to the lampTransformIds table in the lib file)
Lua:function onUse(player, item, fromPosition, target, toPosition, isHotkey) local transformId = lampTransformIds[item:getId()] or reverseLampTransformIds[item:getId()] item:transform(transformId) wallLamps[serializePos(toPosition)] = transformId -- update lamp state dumpLampStates() return true end
now nothing appear on output file.Replace this function, restart server, and show me the output:
]Lua:function loadLampStates() local file = io.open('lamp_states.lua') print('Loading lamp states') if file then wallLamps = unserialize(file:read('*a')) print('Previous data stored, size: '.. #wallLamps) for serializedPos, state in pairs(wallLamps) do local flippedState = lampTransformIds[state] or reverseLampTransformIds[state] local position = unserializePos(serializedPos) print(string.format('Restoring previous state of lamp at %s to id %d', position, flippedState)) Tile(position):getItemById(state):transform(flippedState) end else print('Previous data not found, creating an empty file (no data will be loaded).') io.open('lamp_states.lua', 'w'):close() -- create file if it doesn't exist end end
There should be prints to your console, not output file.now nothing appear on output file.
wallLamps = {}
lampTransformIds, reverseLampTransformIds = { -- used for direct access to flip ids
[5907] = 5908
}, {}
for k, v in pairs(lampTransformIds) do
reverseLampTransformIds[v] = k
end
function table.size(t)
local size = 0
for k, v in pairs(t) do
size = size + 1
end
return size
end
function serialize(s)
local isTable = type(s) == 'table'
local ret = {(isTable and "{" or nil)}
local function doSerialize(s)
if isTable then
local size = table.size(s)
local index = 0
for k, v in pairs(s) do
index = index + 1
local key = (type(k) == 'string') and '"'..k..'"' or k
local val = (type(v) == 'string') and '"'..v..'"' or v
local comma = ((index < size) and ', ' or '')
if type(v) == 'table' then
ret[#ret+1] = ('[%s] = {'):format(key)
doSerialize(v)
ret[#ret+1] = ('}%s'):format(comma)
else
ret[#ret+1] = ('[%s] = %s%s'):format(key, val, comma)
end
end
else
ret[#ret+1] = s
end
end
doSerialize(s)
return (table.concat(ret) .. (isTable and "}" or ""))
end
function unserialize(str)
local f = loadstring("return ".. str)
return f and f() or nil
end
function serializePos(pos)
return string.format('Position(%d, %d, %d)', pos.x, pos.y, pos.z)
end
function unserializePos(s)
return Position(s:match("Position%((%d+), (%d+), (%d+)%)"))
end
function dumpLampStates()
local file = io.open('lamp_states.lua', 'w+')
if file then
file:write(serialize(wallLamps))
end
end
function loadLampStates()
local file = io.open('lamp_states.lua')
print('Loading lamp states')
if file then
wallLamps = unserialize(file:read('*a'))
print('Previous data stored, size: '.. #wallLamps)
for serializedPos, state in pairs(wallLamps) do
local flippedState = lampTransformIds[state] or reverseLampTransformIds[state]
local position = unserializePos(serializedPos)
print(string.format('Restoring previous state of lamp at %s to id %d', position, flippedState))
Tile(position):getItemById(state):transform(flippedState)
end
else
print('Previous data not found, creating an empty file (no data will be loaded).')
io.open('lamp_states.lua', 'w'):close() -- create file if it doesn't exist
end
end