diff options
Diffstat (limited to 'gamemode/server/glon.lua')
| -rw-r--r-- | gamemode/server/glon.lua | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/gamemode/server/glon.lua b/gamemode/server/glon.lua new file mode 100644 index 0000000..ccc7376 --- /dev/null +++ b/gamemode/server/glon.lua @@ -0,0 +1,365 @@ +-- GLON: Garry's Mod Lua Object Notation +-- A dialect of LON: Lua Object Notation +-- Made entirely by Deco Da Man +-- Types: + -- 2: table + -- 3: array + -- 4: fasle boolean + -- 5: true boolean + -- 6: number (NOT COMPRESSED, it isn't worth it) + -- 7: string + ---- non-LON types start here! + -- 8: Vector (NOT COMPRESSED, it isn't worth it) + -- 9: Angle (NOT COMPRESSED, it isn't worth it) + -- 10: Entity (Can do players, vehicles, npcs, weapons and any other type of entity (-1 for null entity)) + -- 11: Player (By UserID) + -- 12: CEffectData + -- 13: ConVar (Not ClientConVar) + -- 15: Color + -- 255: reference (Sends the ID of the table to use (for "local t = {} t.a=t")) +local pairs = pairs +local type = type +local string = string +local math = math +local tostring = tostring +local ValidEntity = ValidEntity +local error = error +local print = print +local setmetatable = setmetatable +local Vector = Vector +local Angle = Angle +local Entity = Entity +local EffectData = EffectData +local GetConVar = GetConVar +local tonumber = tonumber +local player = player +module("glon") +local idcount = {} +local encode_types +local decode_types +local function InDataEscape(s) + return string.gsub(string.gsub(s, "([\1\2])", "\2%1"), "%z", "\2\3") +end +encode_types = { + ["nil"] = {nil, function() + return "", nil + end}, + table = {2, function(o, rtabs) + for k,v in pairs(rtabs) do + if v == o then + return tostring( k ) .. "\1", 255 + end + end + rtabs[#rtabs + 1] = o + local is_array = true + local i = 0 + for k,v in pairs(o) do + i = i + 1 + if k ~= i or type(k) ~= "number" or math.floor(k) ~= k then + is_array = false + break end + end + local s = "" + for k,v in pairs(o) do + if not is_array then + s = s .. Write(k, rtabs) + end + s = s .. Write(v, rtabs) + end + return s .. "\1", is_array and 3 + end}, + boolean = {4, function(o) + return "", o and 5 + end}, + number = {6, function(o) + o = o == 0 and "" or o + return tostring(o) .. "\1" + end}, + string = {7, function(o) + return InDataEscape(o) .. "\1" + end}, + -- non-LON types start here! + Vector = {8, function(o) + return o.x .. "\1" .. o.y .. "\1" .. o.z .. "\1" + end}, + Angle = {9, function(o) + return o.p .. "\1" .. o.y .. "\1" .. o.r .. "\1" + end}, + Entity = {10, function(o) + return (ValidEntity(o) and o:EntIndex() or -1) .. "\1" + end}, + Player = {11, function(o) + return o:EntIndex() .. "\1" + end}, + CEffectData = {12, function(o, rtabs) + local t = {} + if o:GetAngle() ~= Angle(0,0,0) then + t.a = o:GetAngle() + end + if o:GetAttachment() ~= 0 then + t.h = o:GetAttachment() + end + if o:GetEntity():IsValid() then + t.e = o:GetEntity() + end + if o:GetMagnitude() ~= 0 then + t.m = o:GetMagnitude() + end + if o:GetNormal() ~= Vector(0,0,0) then + t.n = o:GetNormal() + end + if o:GetOrigin() ~= Vector(0,0,0) then + t.o = o:GetOrigin() + end + if o:GetRadius() ~= 0 then + t.r = o:GetRadius() + end + if o:GetScale() ~= 0 then + t.c = o:GetScale() + end + if o:GetStart() ~= 0 then + t.s = o:GetStart() + end + if o:GetSurfaceProp() ~= 0 then + t.p = o:GetSurfaceProp() + end + return encode_types.table[2](t, rtabs) + end}, + ConVar = {13, function(o) + return InDataEscape(o:GetName()) .. "\1" + end}, + PhysObj = {14, function(o) + local parent, obj, id = o:GetEntity() + for i = 1, parent:GetPhysicsObjectCount() do + obj = parent:GetPhysicsObjectNum() + if obj == o then + id = i + break end + end + return parent:EntIndex() .. "\1" .. id .. "\1" + end}, + Color = {15, function(o) + return o.r .. "\1" .. o.g .. "\1" .. o.b .. "\1" .. o.a .. "\1" + end}, +} +function Write(data, rtabs) + local t = encode_types[type(data)] + if t then + local data, id_override = t[2](data, rtabs) + local char = id_override or t[1] or "" + if char ~= "" then char = string.char(char) end + return char .. (data or "") + else + error(string.format("Tried to write unwriteable type: %s", + type(data))) + end +end +local CEffectDataTranslation = { + a = "Angle", + h = "Attachment", + e = "Entity", + m = "Magnitude", + n = "Normal", + o = "Origin", + r = "Radius", + c = "Scale", + s = "Start", + p = "SurfaceProp", +} +decode_types = { + -- \2\6omg\1\6omgavalue\1\1 + [2 ] = function(reader, rtabs) -- table + local t, c, pos = {}, reader:Next() + rtabs[#rtabs + 1] = t + local stage = false + local key + while true do + c, pos = reader:Peek() + if c == "\1" then + if stage then + error(string.format("Expected value to match key at %s! (Got EO Table)", + pos)) + else + reader:Next() + return t + end + else + if stage then + t[key] = Read(reader, rtabs) + else + key = Read(reader, rtabs) + end + stage = not stage + end + end + end, + [3] = function(reader, rtabs) -- array + local t, i, c, pos = {}, 1, reader:Next() + rtabs[#rtabs + 1] = t + while true do + c, pos = reader:Peek() + if c == "\1" then + reader:Next() + return t + else + t[i] = Read(reader, rtabs) + i = i + 1 + end + end + end, + [4 ] = function(reader) -- false boolean + reader:Next() + return false + end, + [5 ] = function(reader) -- true boolean + reader:Next() + return true + end, + [6 ] = function(reader) -- number + local s, c, pos, e = "", reader:Next() + while true do + c = reader:Next() + if not c then + error(string.format("Expected \1 to end number at %s! (Got EOF!)", + pos)) + elseif c == "\1" then + break + else + s = s .. c + end + end + if s == "" then s = "0" end + local n = tonumber(s) + if not n then + error(string.format("Invalid number at %s! (%q)", + pos, s)) + end + return n + end, + [7 ] = function(reader) -- string + local s, c, pos, e = "", reader:Next() + while true do + c = reader:Next() + if not c then + error(string.format("Expected unescaped \1 to end string at position %s! (Got EOF)", + pos)) + elseif e then + if c == "\3" then + s = s .. "\0" + else + s = s .. c + end + e = false + elseif c == "\2" then + e = true + elseif c == "\1" then + return s + else + s = s .. c + end + end + end, + [8 ] = function(reader) -- Vector + local x = decode_types[6](reader) + reader:StepBack() + local y = decode_types[6](reader) + reader:StepBack() + local z = decode_types[6](reader) + return Vector(x, y, z) + end, + [9 ] = function(reader) -- Angle + local p = decode_types[6](reader) + reader:StepBack() + local y = decode_types[6](reader) + reader:StepBack() + local r = decode_types[6](reader) + return Angle(p, y, r) + end, + [10 ] = function(reader) -- Entity + return Entity(decode_types[6](reader)) + end, + [11 ] = function(reader) -- Player + local num = decode_types[6](reader) + return player.GetByID(num) + end, + [12 ] = function(reader, rtabs) -- CEffectData + local t = decode_types[2](reader, rtabs) + local d = EffectData() + for k,v in pairs(t) do + d["Set" .. CEffectDataTranslation[k]](d, v) + end + return d + end, + [13 ] = function(reader) -- ConVar + return GetConVar(decode_types[7](reader)) + end, + [15 ] = function(reader) -- Color + local r = decode_types[6](reader) + reader:StepBack() + local g = decode_types[6](reader) + reader:StepBack() + local b = decode_types[6](reader) + reader:StepBack() + local a = decode_types[6](reader) + return Color(r, g, b, a) + end, + [255] = function(reader, rtabs) -- Reference + return rtabs[decode_types[6](reader) - 1] + end +} +function Read(reader, rtabs) + local t, pos = reader:Peek() + if not t then + error(string.format("Expected type ID at %s! (Got EOF)", + pos)) + else + local dt = decode_types[string.byte(t)] + if not dt then + error(string.format("Unknown type ID, %s!", + string.byte(t))) + else + return dt(reader, rtabs or {0}) + end + end +end +local reader_meta = {} +reader_meta.__index = reader_meta +function reader_meta:Next() + self.i = self.i + 1 + self.c = string.sub(self.s, self.i, self.i) + if self.c == "" then self.c = nil end + self.p = string.sub(self.s, self.i + 1, self.i + 1) + if self.p == "" then self.p = nil end + return self.c, self.i +end +function reader_meta:StepBack() + self.i = self.i-1 + self.c = string.sub(self.s, self.i, self.i) + if self.c == "" then self.c = nil end + self.p = string.sub(self.s, self.i + 1, self.i + 1) + if self.p == "" then self.p = nil end + return self.c, self.i +end +function reader_meta:Peek() + return self.p, self.i + 1 +end +function decode(data) + if type(data) == "nil" then + return nil + elseif type(data) ~= "string" then + error(string.format("Expected string to decode! (Got type %s)", + type(data) + )) + elseif data:len() == 0 then + return nil + end + return Read(setmetatable({ + s = data, + i = 0, + c = string.sub(data, 0, 0), + p = string.sub(data, 1, 1), + }, reader_meta), {}) +end +function encode(data) + return Write(data, {0}) -- to use the first key, to prevent it from interfereing with \1s. You can have up to 254 unique tables (including arrays) +end |
