Last active
April 14, 2023 18:17
-
-
Save aduermael/f916172fbd18a3c2413f1f1d5274ae9a to your computer and use it in GitHub Desktop.
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
Config = { | |
Map = "aduermael.hills", | |
Items = { "jacksbertox.easel" } | |
} | |
------------------- | |
--== Constants ==-- | |
------------------- | |
local EVENT_TYPE = { | |
LOAD = -3, | |
SAVE = -2, | |
SENDCLIENTDATA = -1, | |
SENDDATA = 0, | |
MOVE = 1, | |
CHAT = 2, | |
DRAW = 3, | |
UNDOREDO = 4, | |
PLACEEASEL = 5, | |
CANVASINTERACT = 6, | |
WIPLOADED = 100 | |
} | |
local DATA_TYPE = { | |
USER = 0, | |
WIP = 1, | |
PAINTING = 2, | |
} | |
painting_keys = { | |
"data1", | |
"data2", | |
"data3", | |
"artist", | |
"name" | |
} | |
maxWIPs = 5 | |
local encode_string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ=+" | |
------------------- | |
--== Variables ==-- | |
------------------- | |
default_color = 190 | |
cameraSetPos = false | |
cameraTargetPos = nil | |
cameraTargetRot = nil | |
cameraPrevRot = nil | |
observe = false | |
canMove = true | |
candraw = false | |
chatting = true | |
saveBTN = nil | |
loadShown = false | |
loadQueue = {} | |
easels = {} | |
usrTags = {} | |
myWIPs = {} | |
myWIPsData = {} | |
--color costants | |
colorWhite = DefaultColors[229] | |
btnDisabled = Color(214, 214, 214, 20) | |
btnEnabled = Color(216, 216, 216) | |
btnToggleON = Color(0, 0, 0) | |
--a number converter | |
function toBase64(int) | |
local fin = "" | |
local i = 0 | |
local n = int | |
while (n ~= 0) do | |
i = n % 64 | |
n = math.floor(n / 64) | |
if i < 10 then | |
fin = i .. fin | |
else | |
fin = encode_string:sub(i - 9, i - 9) .. fin | |
end | |
end | |
return fin | |
end | |
function fromBase64(str) | |
local fin = 0 | |
for i = 1, #str do | |
local c = str:sub(i, i) | |
local d, _ = string.find(encode_string, c) | |
if d then d = d + 9 end | |
local a = d or c | |
fin = 64 * fin + a | |
end | |
return math.floor(fin) | |
end | |
function canvasToString(c) | |
local fin = "" | |
for x = 0, c.Width - 1 do | |
for y = 0, c.Height - 1 do | |
local n = c:GetBlock(x, y, 0).PaletteIndex | |
local col = getIndexInArray(DefaultColors, c.Palette[n].Color) | |
local a = toBase64(col) | |
if #a < 2 then a = "0" .. a end | |
fin = fin .. a | |
end | |
end | |
return fin | |
end | |
function stringToCanvas(s, c) | |
local i = 0 | |
for x = 0, c.Width - 1 do | |
for y = 0, c.Height - 1 do | |
local a = fromBase64(s:sub(i + 1, i + 2)) | |
i = i + 2 | |
c:GetBlock(x, y, 0):Replace(DefaultColors[a]) | |
end | |
end | |
end | |
function createID() | |
local template = "xxxxxx" | |
return string.gsub(template, "[xy]", function(c) | |
local v = (c == "x") and math.random(0, 0xf) or math.random(8, 0xb) | |
return string.format("%x", v) | |
end) | |
end | |
function canvasData(canva) | |
local data = canvasToString(canva) | |
return { data1 = data:sub(1, 250), | |
data2 = data:sub(251, 500), | |
data3 = data:sub(501, 512), | |
name = canva.name or "???", | |
artist = canva.owner.Username | |
} | |
end | |
function tablelength(T) | |
local count = 0 | |
for _ in pairs(T) do count = count + 1 end | |
return count | |
end | |
function getIndexInArray(array, item) | |
for i = 1, #array do | |
if array[i] == item then return i end | |
end | |
return nil | |
end | |
function saveData(key, args) | |
local e = Event() | |
e.action = EVENT_TYPE.SAVE | |
e.key = key | |
e.data = JSON:Encode(args) | |
e:SendTo(Server) | |
end | |
function loadData(key, keys, type) | |
local e = Event() | |
e.action = EVENT_TYPE.LOAD | |
e.key = key | |
e.keys = JSON:Encode(keys) | |
local k = e.keys | |
table.insert(loadQueue, { type = type, key = key }) | |
e:SendTo(Server) | |
end | |
local Private = { | |
ItemEditorClearUndoRedoAndGrid = function (self) | |
end, | |
ItemEditorCreateUndoRedoAndGrid = function (self) | |
local ui = require "uikit" | |
local undo = ui:createButton("Undo", 13) | |
undo.Text = "Undo" | |
local redo = ui:createButton("Redo", 13) | |
redo.Text = "Undo" | |
local save = ui:createButton("Save", 13) | |
return undo, redo, save | |
end | |
} | |
Client.OnStart = function() | |
function playerSpawn(player) | |
player.Position = Map.Scale * { Map.Width * 0.5, Map.Height + 25, Map.Depth * 0.5 } | |
player.Velocity = { 0, 0, 0 } | |
player.Motion = { 0, 0, 0 } | |
end | |
require("multi").teleportTriggerDistance = 100 | |
World:AddChild(Player) | |
playerSpawn(Player) | |
sun = Light() | |
sun:SetParent(World) | |
sun.Type = LightType.Directional | |
sun.CastsShadows = true | |
sun.Color = Color(99,75,0) | |
sun.Rotation = { 0.7, 0.5, 0.0 } | |
canvasShape = MutableShape() | |
for x = 0, 15 do | |
for y = 0, 15 do | |
canvasShape:AddBlock(colorWhite, x, y, 0) | |
end | |
end | |
loadData(Player.UserID, { "WIPs" }, DATA_TYPE.USER) | |
Camera.playerPOV = function(self) | |
self:SetModeFirstPerson() | |
Player.Head.IsHidden = true | |
Player.Body.IsHidden = true | |
Player.LeftLeg.IsHidden = true | |
Player.RightLeg.IsHidden = true | |
Player.RightArm.IsHidden = true | |
Player.LeftLeg.IsHidden = true | |
end | |
uiKit = require("uikit") | |
uiKit.margin = 8 | |
uiKit:init() | |
local picker = ColorPicker() | |
picker.SelectedIndex = default_color | |
picker.OnColorSelect = function(index) | |
default_color = index | |
end | |
ui = { | |
start = { | |
start = Label("Place Down your easel to start drawing", Anchor.HCenter, Anchor.Top) | |
}, | |
walk = {}, | |
draw = { | |
picker = picker, | |
back = Button("Back", Anchor.Left, Anchor.Top), | |
load = Button("⬅ 💾"), | |
save = Button("➡ 💾"), | |
--[[backBt = back, | |
undo = undoBtn, | |
redo = redoBtn,]] | |
}, | |
load = {}, | |
} | |
for i = 1, maxWIPs do | |
local b = Button("") | |
b.id = i | |
b.OnPress = function() | |
local data = myWIPsData[myWIPs[b.id]] | |
if data then | |
stringToCanvas(data.data1 .. data.data2 .. data.data3, curCanvas) | |
curCanvas.id = myWIPs[b.id] | |
local e = Event() | |
e.action = EVENT_TYPE.SENDCLIENTDATA | |
e.easelDown = easelPlaced | |
e.easelPos = myEasel.Position | |
e.easelRot = myEasel.Rotation | |
e.paint = canvasToString(curCanvas) | |
e:SendTo(OtherPlayers) | |
end | |
end | |
ui.load["loadBTN" .. i] = b | |
b:Remove() | |
end | |
ui.draw.save.OnPress = function() | |
if #myWIPs < maxWIPs then | |
print("✏ painting ID: " .. curCanvas.id .. " Please name your drawing") | |
chatting = false | |
Client.OpenChatInput() | |
end | |
end | |
ui.draw.save.callBack = function(self, msg) | |
if msg ~= nil and msg ~= "" then | |
if myWIPsData[curCanvas.id] == nil then | |
table.insert(myWIPs, curCanvas.id) | |
end | |
saveData(Player.UserID, { WIPs = myWIPs }) | |
curCanvas.name = msg | |
local data = canvasData(curCanvas) | |
myWIPsData[curCanvas.id] = data | |
saveData(curCanvas.id, data) | |
print(#myWIPs) | |
else | |
print("❌ That is not a valid name!") | |
end | |
end | |
ui.draw.back.OnPress = function() | |
cameraSetPos = true | |
cameraTargetPos = Player.Position + { 0, 7.55, 0 } | |
cameraTargetRot = cameraPrevRot | |
--print(canvasToString(curCanvas)) | |
exitDrawMode() | |
end | |
ui.draw.load.OnPress = function() | |
loadShown = not loadShown | |
if loadShown then | |
ui.draw.load.Color = btnToggleON | |
ui:showScene("load") | |
for i = 1, maxWIPs do | |
local data = myWIPsData[myWIPs[i]] | |
local name = "" | |
local b = ui.load["loadBTN" .. i] | |
if not data then b:Remove() else name = "[ " .. data.name .. " ]" or "[ ??? ]" end | |
b.Text = name | |
end | |
else | |
ui.draw.load.Color = btnEnabled | |
ui:hideScene("load") | |
end | |
end | |
ui.curScene = "walk" | |
ui.draw.picker.Visible = false | |
function ui:showScene(scene) | |
for _, v in pairs(ui[scene]) do | |
if type(v) == "ColorPicker" then | |
v.Visible = true | |
else | |
v:Add() | |
end | |
end | |
end | |
function ui:hideScene(scene) | |
for _, v in pairs(ui[scene]) do | |
if type(v) == "ColorPicker" then | |
v.Visible = false | |
else | |
v:Remove() | |
end | |
end | |
end | |
function ui:switchScene(scene) | |
ui:hideScene(ui.curScene) | |
ui:showScene(scene) | |
ui.curScene = scene | |
end | |
function refreshUndoRedo() | |
--[[if not curCanvas.CanUndo then | |
undo:setColor(btnDisabled) | |
else | |
undo:setColor(btnEnabled) | |
end | |
if not curCanvas.CanRedo then | |
redo:setColor(btnDisabled) | |
else | |
redo:setColor(btnEnabled) | |
end]] | |
end | |
enterDrawMode = function() | |
UI.Crosshair = false | |
-- stop all ongoing motion | |
Player.Velocity = { 0, 0, 0 } | |
Player.Motion = { 0, 0, 0 } | |
dpadX = 0 | |
dpadY = 0 | |
observe = true | |
canMove = false | |
ui:switchScene("draw") | |
Pointer:Show() | |
Client.DirectionalPad = nil | |
Client.Action1 = nil | |
--for some reason :Remove() deletes them unlike other buttons | |
--undo, redo, save = Private:ItemEditorCreateUndoRedoAndGrid() | |
--save.Text = "➡ 💾" | |
--saveBTN = save | |
refreshUndoRedo() | |
ui.draw.load.Color = btnEnabled | |
--[[save.OnPress = function() | |
if #myWIPs < maxWIPs then | |
print("✏ painting ID: " .. curCanvas.id .. " Please name your drawing") | |
chatting = false | |
Client.OpenChatInput() | |
end | |
end | |
save.callBack = function(self, msg) | |
if msg ~= nil and msg ~= "" then | |
if myWIPsData[curCanvas.id] == nil then | |
table.insert(myWIPs, curCanvas.id) | |
end | |
saveData(Player.UserID, { WIPs = myWIPs }) | |
curCanvas.name = msg | |
local data = canvasData(curCanvas) | |
myWIPsData[curCanvas.id] = data | |
saveData(curCanvas.id, data) | |
else | |
print("❌ That is not a valid name!") | |
end | |
end | |
undo.OnPress = function() | |
curCanvas:Undo() | |
refreshUndoRedo() | |
local e = Event() | |
e.action = EVENT_TYPE.UNDOREDO | |
e.undo = true | |
e:SendTo(OtherPlayers) | |
end | |
redo.OnPress = function() | |
curCanvas:Redo() | |
refreshUndoRedo() | |
local e = Event() | |
e.action = EVENT_TYPE.UNDOREDO | |
e.undo = false | |
e:SendTo(OtherPlayers) | |
end]] | |
end | |
exitDrawMode = function() | |
canDraw = false | |
UI.Crosshair = true | |
if loadShown then | |
loadShown = false | |
ui:hideScene("load") | |
end | |
observe = false | |
ui:switchScene("walk") | |
Pointer:Hide() | |
Client.DirectionalPad = padDirFunc | |
Client.Action1 = jumpFunc | |
--Private:ItemEditorClearUndoRedoAndGrid() | |
end | |
exitDrawMode() | |
ui:hideScene("draw") | |
ui:switchScene("start") | |
TimeCycle.On = false | |
Time.Current = Time.Noon | |
function spawnEasel(owner, pos) | |
local easel = Shape(Items.jacksbertox.easel) | |
easel.canva = canvasShape:Copy() | |
easel.canva.Pivot = canvasShape.Center | |
easel.LocalScale = 0.5 | |
easel.owner = owner | |
easel.canva.owner = owner | |
easel:AddChild(easel.canva) | |
easel.canva.LocalPosition = Number3(0, 4.5, 2) | |
easels[owner.ID] = easel | |
easel.Position = pos | |
local p = Object() | |
p:SetParent(easel.canva) | |
p.LocalPosition = { 0, 0, 20 } | |
easel.cameraPoint = p | |
if owner.IsLocal then | |
curCanvas = easel.canva | |
myEasel = easel | |
easel.canva.id = createID() | |
end | |
easel.canva.History = true --item edit history | |
World:AddChild(easel) | |
easel.OnCollision = function(self, other) | |
self.collidesWithMap = type(other) == "Map" | |
end | |
return easel | |
end | |
spawnEasel(Player, Number3(0, 12, 16)) | |
myEasel.PrivateDrawMode = 1 | |
curCanvas.PrivateDrawMode = 1 | |
myEasel:SetParent(Player) | |
myEasel.IsHidden = false | |
myEasel.LocalPosition = { 0, 12, 16 } | |
myEasel.LocalRotation = { 0, 3.14, 0 } | |
function Camera:smoothSetPos(tPos, tRot, minSpeed, dt) | |
Camera:SetModeFree() | |
local distance = Camera.Position - tPos | |
local distance2 = Camera.Forward - tRot | |
if distance.Length > 0.1 then | |
local speed = ((Camera.Position - tPos) * 2.0).Length | |
if speed < minSpeed then | |
speed = minSpeed | |
end | |
if speed * dt > distance.Length then | |
speed = distance.Length / dt | |
end | |
distance:Normalize() | |
Camera.Position = Camera.Position - distance * speed * dt | |
else | |
cameraSetPos = false | |
end | |
if distance2.Length > 0.1 then | |
local speed2 = ((Camera.Forward - tRot) * 0.5).Length | |
if speed2 < minSpeed * 0.1 then | |
speed2 = minSpeed * 0.1 | |
end | |
if speed2 * dt > distance2.Length then | |
speed2 = distance2.Length / dt | |
end | |
distance2:Normalize() | |
Camera.Forward = Camera.Forward - distance2 * speed2 * dt | |
end | |
end | |
end | |
Client.OnPlayerJoin = function(p) | |
require("multi"):initPlayer(p) | |
if not p.IsLocal then | |
spawnEasel(p, Number3(0, 0, 0)) | |
print("😬 " .. p.Username .. " Joined") | |
local o = Object() | |
o.name = p.Username | |
usrTags[p.ID] = o | |
o:TextBubble(o.name, -1, Number3(0, 35, 0), Color(1.0, 1.0, 1.0, 135), Color(0, 0, 0, 0)) | |
o:SetParent(p) | |
local e = Event() | |
e.action = EVENT_TYPE.SENDCLIENTDATA | |
e.easelDown = easelPlaced | |
e.easelPos = myEasel.Position | |
e.easelRot = myEasel.Rotation | |
e.paint = canvasToString(curCanvas) | |
e:SendTo(p) | |
end | |
playerSpawn(p) | |
end | |
Client.AnalogPad = function(dx, dy) | |
Player.LocalRotation.Y = Player.LocalRotation.Y + dx * 0.01 | |
Player.LocalRotation.X = Player.LocalRotation.X + -dy * 0.01 | |
if dpadX ~= nil and dpadY ~= nil and canMove then | |
Player.Motion = (Player.Forward * dpadY + Player.Right * dpadX) * 50 | |
end | |
end | |
padDirFunc = function(x, y) | |
-- storing globals here for AnalogPad to update Player.Motion | |
dpadX = x | |
dpadY = y | |
if canMove then Player.Motion = (Player.Forward * y + Player.Right * x) * 50 end | |
Player.moving = x ~= 0 or y ~= 0 | |
end | |
Client.OnPlayerLeave = function(p) | |
require("multi"):removePlayer(p) | |
usrTags[p.ID]:ClearTextBubble() | |
usrTags[p.ID] = nil | |
print("🤨 " .. p.Username .. " Left") | |
easels[p.ID]:SetParent(nil) | |
easels[p.ID] = nil | |
end | |
Client.Tick = function(dt) | |
require("multi"):tick(dt) | |
if Player.Position.Y < -500 then | |
playerSpawn(Player) | |
end | |
if cameraSetPos then | |
Camera:smoothSetPos(cameraTargetPos, cameraTargetRot, 12, dt) | |
else | |
if not observe then | |
Camera:playerPOV() | |
canMove = true | |
else | |
canDraw = true | |
end | |
end | |
local Pos = Player.Forward + Player.Position | |
local Coords = Number3( | |
math.floor(Pos.X / Map.Scale.X), | |
math.floor(Pos.Y / Map.Scale.Y), | |
math.floor(Pos.Z / Map.Scale.Z) | |
) | |
if Map:GetBlock(Coords.X, Coords.Y, Coords.Z + 1) ~= nil and Map:GetBlock(Coords.X, Coords.Y + 1, Coords.Z + 1) == | |
nil and Player.moving then | |
Player.Velocity.Y = 40 | |
end | |
if Map:GetBlock(Coords.X, Coords.Y, Coords.Z - 1) ~= nil and Map:GetBlock(Coords.X, Coords.Y + 1, Coords.Z - 1) == | |
nil and Player.moving then | |
Player.Velocity.Y = 40 | |
end | |
if Map:GetBlock(Coords.X + 1, Coords.Y, Coords.Z) ~= nil and Map:GetBlock(Coords.X + 1, Coords.Y + 1, Coords.Z) == | |
nil and Player.moving then | |
Player.Velocity.Y = 40 | |
end | |
if Map:GetBlock(Coords.X - 1, Coords.Y, Coords.Z) ~= nil and Map:GetBlock(Coords.X - 1, Coords.Y + 1, Coords.Z) == | |
nil and Player.moving then | |
Player.Velocity.Y = 40 | |
end | |
end | |
-- jump function | |
jumpFunc = function() | |
if Player.IsOnGround then | |
Player.Velocity.Y = 100 | |
end | |
end | |
Client.Action2 = function() | |
if easelPlaced then | |
-- Note from Cubzh: this is because Action2 is wrongfully triggered, to be fixed on our end | |
if not canMove then return end | |
local i = Player:CastRay(curCanvas) | |
if i.Object ~= nil and i.FaceTouched == Face.Front then | |
if i.Distance < 35 then | |
--Smooth transition to canvas | |
cameraPrevRot = Camera.Forward:Copy() | |
cameraSetPos = true | |
cameraTargetPos = myEasel.cameraPoint.Position | |
cameraTargetRot = curCanvas.Backward | |
enterDrawMode() | |
else | |
print("⚠ Too Far!") | |
end | |
end | |
else | |
if not myEasel.collidesWithMap and Player.IsOnGround then | |
ui:hideScene("start") | |
local pos1 = myEasel.Position:Copy() | |
World:AddChild(myEasel, true) | |
local pos2 = myEasel.Position:Copy() | |
easelPlaced = true | |
myEasel.PrivateDrawMode = 0 | |
curCanvas.PrivateDrawMode = 0 | |
local e = Event() | |
e.action = EVENT_TYPE.PLACEEASEL | |
e:SendTo(OtherPlayers) | |
end | |
end | |
end | |
Client.OnChat = function(message) | |
if chatting then | |
-- display bubble over local Player | |
-- when a message is posted | |
print("[" .. Player.Username .. "]: " .. message) | |
Player:TextBubble(message, 8, true) | |
-- send message to other players | |
local e = Event() | |
e.action = EVENT_TYPE.CHAT | |
e.msg = message | |
e:SendTo(OtherPlayers) | |
else | |
chatting = true | |
ui.draw.save:callBack(message) | |
end | |
end | |
Client.DidReceiveEvent = function(e) | |
require("multi"):receive(e) | |
if e.action == EVENT_TYPE.MOVE then | |
local sender = e.Sender | |
sender.Position = e.p | |
sender.Motion = e.m | |
sender.Velocity = e.v | |
sender.Rotation = e.r | |
elseif e.action == EVENT_TYPE.CHAT then | |
-- display messages from other players | |
print("[" .. e.Sender.Username .. "]: " .. e.msg) | |
e.Sender:TextBubble(e.msg, 8, true) | |
elseif e.action == EVENT_TYPE.SENDCLIENTDATA then | |
local ea = easels[e.Sender.ID] or spawnEasel(e.Sender, Number3(0, 0, 0)) | |
if e.easelDown then | |
ea:SetParent(World) | |
ea.Position = e.easelPos | |
ea.Rotation = e.easelRot | |
stringToCanvas(e.paint, ea.canva) | |
else | |
ea:SetParent(e.Sender) | |
ea.PrivateDrawMode = 1 | |
ea.canva.PrivateDrawMode = 1 | |
ea.LocalPosition = { 0, 12, 16 } | |
ea.LocalRotation = { 0, 3.14, 0 } | |
end | |
elseif e.action == EVENT_TYPE.PLACEEASEL then | |
local ea = easels[e.Sender.ID] | |
ea.PrivateDrawMode = 0 | |
ea.canva.PrivateDrawMode = 0 | |
local p = ea.Position:Copy() | |
World:AddChild(ea, true) | |
local p = ea.Position:Copy() | |
elseif e.action == EVENT_TYPE.DRAW then | |
local ea = easels[e.Sender.ID] | |
ea.canva:GetBlock(e.pos.X, e.pos.Y, e.pos.Z):Replace(DefaultColors[e.color]) | |
elseif e.action == EVENT_TYPE.UNDOREDO then | |
if e.undo then | |
easels[e.Sender.ID].canva:Undo() | |
else | |
easels[e.Sender.ID].canva:Redo() | |
end | |
elseif e.action == EVENT_TYPE.SENDDATA then | |
local data = JSON:Decode(e.data) | |
local queueElement = table.remove(loadQueue, 1) | |
if queueElement.type == DATA_TYPE.WIP then | |
myWIPsData[queueElement.key] = data | |
elseif queueElement.type == DATA_TYPE.USER then | |
myWIPs = data.WIPs or {} | |
for i = 1, #myWIPs do | |
loadData(myWIPs[i], painting_keys, DATA_TYPE.WIP) | |
end | |
elseif queueElement.type == DATA_TYPE.PAINTING then | |
end | |
end | |
end | |
placePixel = function(e) | |
if canDraw then | |
refreshUndoRedo() | |
local i = e:CastRay(curCanvas) | |
local pos | |
if i.Block then | |
i.Block:Replace(DefaultColors[default_color]) | |
pos = i.Block.Coords | |
local e = Event() | |
e.action = EVENT_TYPE.DRAW | |
e.color = default_color | |
e.pos = pos | |
e:SendTo(OtherPlayers) | |
end | |
end | |
end | |
Pointer.Down = function(e) | |
placePixel(e) | |
end | |
Pointer.Drag = function(e) | |
placePixel(e) | |
end | |
Server.OnStart = function() | |
end | |
Server.DidReceiveEvent = function(e) | |
if e.action == EVENT_TYPE.SAVE then | |
print("💾 Saving Data...") | |
local store = KeyValueStore(e.key) | |
local data = JSON:Decode(e.data) | |
local i = 0 | |
local count = 0 | |
local progress = 0 | |
for _ in pairs(data) do count = count + 1 end | |
for k, v in pairs(data) do | |
local value | |
if type(v) == "table" then value = JSON:Encode(v) else value = v end | |
store:Set(k, value, function(success) | |
if success then | |
i = i + 1 | |
progress = math.floor(100 / count * i) | |
print(progress) | |
else | |
print("❌ Something went wrong!") | |
end | |
end) | |
end | |
else | |
local ev = Event() | |
ev.action = EVENT_TYPE.SENDDATA | |
ev.data = "" | |
local store = KeyValueStore(e.key) | |
local keys = JSON:Decode(e.keys) | |
local p = 0 | |
local r = {} | |
for i = 1, #keys do | |
store:Get(keys[i], function(success, result) | |
if success then | |
local item = result[keys[i]] | |
if type(item) == "string" then | |
if item:sub(1, 1) == "[" and item:sub(#item, #item) == "]" then | |
item = JSON:Decode(item) | |
end | |
end | |
r[keys[i]] = item | |
else | |
print("❌ Something went wrong!") | |
end | |
p = i | |
if p == #keys then | |
ev.data = JSON:Encode(r) | |
ev:SendTo(e.Sender) | |
end | |
end) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment