1local opcodeCallbacks = {}
2local extendedCallbacks = {}
3local extendedJSONCallbacks = {}
4local extendedJSONData = {}
5local maxPacketSize = 65000
6
7-- Utility function to check if an item id is valid
8local function isValidItemId(itemId)
9 -- g_things is usually the global accessor for items
10 return g_things and g_things:isValidItemId(itemId)
11end
12
13function ProtocolGame:onOpcode(opcode, msg)
14 for i, callback in pairs(opcodeCallbacks) do
15 if i == opcode then
16 callback(self, msg)
17 return true
18 end
19 end
20 return false
21end
22
23function ProtocolGame:onExtendedOpcode(opcode, buffer)
24 local callback = extendedCallbacks[opcode]
25 if callback then
26 callback(self, opcode, buffer)
27 end
28
29 callback = extendedJSONCallbacks[opcode]
30 if callback then
31 local status = buffer:sub(1,1) -- O - just one message, S - start, P - part, E - end
32 local data = buffer:sub(2)
33 if status ~= "E" and status ~= "P" then
34 extendedJSONData[opcode] = ""
35 end
36 if status ~= "S" and status ~= "P" and status ~= "E" then
37 extendedJSONData[opcode] = buffer
38 else
39 extendedJSONData[opcode] = extendedJSONData[opcode] .. data
40 end
41 if status ~= "S" and status ~= "P" then
42 local json_status, json_data = pcall(function() return json.decode(extendedJSONData[opcode]) end)
43 extendedJSONData[opcode] = nil
44 if not json_status then
45 error("Invalid data in extended JSON opcode (" .. json_status .. "): " .. json_data)
46 return
47 end
48 callback(self, opcode, json_data)
49 end
50 end
51end
52
53function ProtocolGame.registerOpcode(opcode, callback)
54 if opcodeCallbacks[opcode] then
55 error('opcode ' .. opcode .. ' already registered will be overriden')
56 end
57
58 opcodeCallbacks[opcode] = callback
59end
60
61function ProtocolGame.unregisterOpcode(opcode)
62 opcodeCallbacks[opcode] = nil
63end
64
65function ProtocolGame.registerExtendedOpcode(opcode, callback)
66 if not callback or type(callback) ~= 'function' then
67 error('Invalid callback.')
68 end
69
70 if opcode < 0 or opcode > 255 then
71 error('Invalid opcode. Range: 0-255')
72 end
73
74 if extendedCallbacks[opcode] then
75 error('Opcode is already taken.')
76 end
77
78 extendedCallbacks[opcode] = callback
79end
80
81function ProtocolGame.unregisterExtendedOpcode(opcode)
82 if opcode < 0 or opcode > 255 then
83 error('Invalid opcode. Range: 0-255')
84 end
85
86 if not extendedCallbacks[opcode] then
87 error('Opcode is not registered.')
88 end
89
90 extendedCallbacks[opcode] = nil
91end
92
93function ProtocolGame.registerExtendedJSONOpcode(opcode, callback)
94 if not callback or type(callback) ~= 'function' then
95 error('Invalid callback.')
96 end
97
98 if opcode < 0 or opcode > 255 then
99 error('Invalid opcode. Range: 0-255')
100 end
101
102 if extendedJSONCallbacks[opcode] then
103 error('Opcode is already taken.')
104 end
105
106 extendedJSONCallbacks[opcode] = callback
107end
108
109function ProtocolGame.unregisterExtendedJSONOpcode(opcode)
110 if opcode < 0 or opcode > 255 then
111 error('Invalid opcode. Range: 0-255')
112 end
113
114 if not extendedJSONCallbacks[opcode] then
115 error('Opcode is not registered.')
116 end
117
118 extendedJSONCallbacks[opcode] = nil
119end
120
121function ProtocolGame:sendExtendedJSONOpcode(opcode, data)
122 if opcode < 0 or opcode > 255 then
123 error('Invalid opcode. Range: 0-255')
124 end
125
126 if type(data) ~= "table" then
127 error('Invalid data type, should be table')
128 end
129
130 local buffer = json.encode(data)
131 local s = {}
132 for i=1, #buffer, maxPacketSize do
133 s[#s+1] = buffer:sub(i,i+maxPacketSize - 1)
134 end
135 if #s == 1 then
136 self:sendExtendedOpcode(opcode, s[1])
137 return
138 end
139 self:sendExtendedOpcode(opcode, "S" .. s[1])
140 for i=2,#s - 1 do
141 self:sendExtendedOpcode(opcode, "P" .. s[i])
142 end
143 self:sendExtendedOpcode(opcode, "E" .. s[#s])
144end
145