Skip to content

Commit

Permalink
Compagnon module
Browse files Browse the repository at this point in the history
  • Loading branch information
Sylvain "Telkostrasz" Cossement committed Aug 17, 2014
1 parent aa60af1 commit 6677a91
Show file tree
Hide file tree
Showing 87 changed files with 36,463 additions and 0 deletions.
959 changes: 959 additions & 0 deletions totalRP3/tags/0.2.0/UI.xsd

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions totalRP3/tags/0.2.0/core/core.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\UI.xsd">

<!-- Please note that the loading order matters a lot -->
<GameTooltip name="TRP3_MainTooltip" frameStrata="TOOLTIP" hidden="false" parent="UIParent" inherits="GameTooltipTemplate"/>
<GameTooltip name="TRP3_Toast" frameStrata="TOOLTIP" hidden="false" parent="UIParent" inherits="GameTooltipTemplate">
<Scripts>
<OnHide>
self.isFading = nil;
</OnHide>
</Scripts>
</GameTooltip>

<Script file="impl\globals.lua"/>
<Script file="impl\events.lua"/>
<Include file="impl\locale\locale.xml"/>
<Script file="impl\utils.lua"/>
<Script file="impl\ui_tools.lua"/>

<Include file="ui\widgets.xml"/>

<Include file="ui\main.xml"/>
<Script file="impl\main_structure.lua"/>

<Include file="ui\configuration.xml"/>
<Script file="impl\configuration.lua"/>

<Script file="impl\communication_protocol.lua"/>
<Script file="impl\communication_protocol_broadcast.lua"/>

<Script file="impl\ui_main.lua"/>

<Include file="ui\browsers\icons.xml"/>
<Include file="ui\browsers\musics.xml"/>
<Include file="ui\browsers\colors.xml"/>
<Include file="ui\browsers\images.xml"/>
<Script file="impl\popup.lua"/>

<Include file="ui\toolbar.xml"/>
<Script file="impl\toolbar.lua"/>

<Include file="ui\profiles.xml"/>
<Script file="impl\profiles.lua"/>

<Include file="ui\target_frame.xml"/>
<Script file="impl\target_frame.lua"/>

<Script file="impl\script\script_generation.lua"/>
<Script file="impl\script\script_operands.lua"/>
<Script file="impl\script\script_effects.lua"/>

</Ui>
249 changes: 249 additions & 0 deletions totalRP3/tags/0.2.0/core/impl/communication_protocol.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-- Total RP 3 Addon Communication protocol
-- This is a regular protocol based on layers 1 & 3 & 4 & 5 from the ISO-OSI model.
--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

-- Public accessor
TRP3_API.communication = {};

-- imports
local RegisterAddonMessagePrefix = RegisterAddonMessagePrefix;
local tostring, pairs, assert, string, wipe, tinsert, type, math = tostring, pairs, assert, string, wipe, tinsert, type, math;
local tconcat = table.concat;
local ChatThrottleLib = ChatThrottleLib;
local Globals = TRP3_API.globals;
local Utils = TRP3_API.utils;
local Log = Utils.log;
local Comm, isIDIgnored = TRP3_API.communication;
local libSerializer = LibStub:GetLibrary("AceSerializer-3.0");

-- function definition
local handlePacketsIn;
local handleStructureIn;
local receiveObject;
local onAddonMessageReceived;

--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-- LAYER 0 : CONNECTION LAYER
-- Makes connection with Wow communication functions, or debug functions
--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

local wowCom_prefix = "TRP3";
local interface_id = {
WOW = 1,
DIRECT_RELAY = 2,
DIRECT_PRINT = 3
};
Comm.interface_id = interface_id;
local selected_interface_id = interface_id.WOW;

function Comm.init()
isIDIgnored = TRP3_API.register.isIDIgnored;
Utils.event.registerHandler("CHAT_MSG_ADDON", onAddonMessageReceived);
Utils.event.registerHandler("PLAYER_ENTERING_WORLD", function()
RegisterAddonMessagePrefix(wowCom_prefix);
end);
end

-- This is the main communication interface, using ChatThrottleLib to
-- avoid being kicked by the server when sending a lot of data.
local function wowCommunicationInterface(packet, target, priority)
ChatThrottleLib:SendAddonMessage(priority or "BULK", wowCom_prefix, packet, "WHISPER", target);
end

function onAddonMessageReceived(...)
local prefix, packet , distributionType, sender = ...;
if prefix == wowCom_prefix then
-- TODO: check here ignore
handlePacketsIn(packet, sender);
end
end

-- This communication interface print all sent message to the chat frame.
-- Note that the messages are not really sent.
local function directPrint(packet, target, priority)
Log.log("Message to: "..tostring(target).." - Priority: "..tostring(priority)..(" - Message(%s):"):format(packet:len()));
Log.log(packet:sub(4));
end

-- A "direct relay" (like localhost) communication interface, used for development purpose.
-- Any message sent to this communication interface is directly rerouted to the user itself.
-- Note that the messages are not really sent.
local function directRelayInterface(packet, target, priority)
directPrint(packet, target, priority)
handlePacketsIn(packet, target);
end

-- Returns the function reference to be used as communication interface.
local function getCommunicationInterface()
if selected_interface_id == interface_id.WOW then return wowCommunicationInterface end
if selected_interface_id == interface_id.DIRECT_RELAY then return directRelayInterface end
if selected_interface_id == interface_id.DIRECT_PRINT then return directPrint end
end

-- Changes the communication interface to use
function Comm.setInterfaceID(id)
selected_interface_id = id;
end

--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-- LAYER 1 : PACKET LAYER
-- Packet sending and receiving
-- Handles packet sequences
--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

-- 254 - TRP3(4) - MESSAGE_ID(2) - control character(1)
local AVAILABLE_CHARACTERS = 246;
local NEXT_PACKET_PREFIX = 1;
local LAST_PACKET_PREFIX = 2;
local PACKETS_RECEPTOR = {};

-- Send each packet to the current communication interface.
local function handlePacketsOut(messageID, packets, target, priority)
if #packets ~= 0 then
for index, packet in pairs(packets) do
assert(packet:len() <= AVAILABLE_CHARACTERS, "Too long packet: " .. packet:len());
local control = string.char(NEXT_PACKET_PREFIX);
if index == #packets then
control = string.char(LAST_PACKET_PREFIX);
end
getCommunicationInterface()(messageID..control..packet, target, priority);
end
end
end

local function savePacket(sender, messageID, packet)
if not PACKETS_RECEPTOR[sender] then
PACKETS_RECEPTOR[sender] = {};
end
if not PACKETS_RECEPTOR[sender][messageID] then
PACKETS_RECEPTOR[sender][messageID] = {};
end
tinsert(PACKETS_RECEPTOR[sender][messageID], packet);
end

local function getPackets(sender, messageID)
assert(PACKETS_RECEPTOR[sender] and PACKETS_RECEPTOR[sender][messageID], "No stored packets from "..sender.." for structure "..messageID);
return PACKETS_RECEPTOR[sender][messageID];
end

local function endPacket(sender, messageID)
assert(PACKETS_RECEPTOR[sender] and PACKETS_RECEPTOR[sender][messageID], "No stored packets from "..sender.." for structure "..messageID);
wipe(PACKETS_RECEPTOR[sender][messageID]);
PACKETS_RECEPTOR[sender][messageID] = nil;
end

function handlePacketsIn(packet, sender)
if not isIDIgnored(sender) then
local messageID = packet:sub(1, 2);
local control = packet:sub(3, 3);
savePacket(sender, messageID, packet:sub(4));
if control:byte(1) == LAST_PACKET_PREFIX then
handleStructureIn(getPackets(sender, messageID), sender);
endPacket(sender, messageID);
end
end
end

--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-- LAYER 2 : MESSAGE LAYER
-- Structure-to-Message serialization / deserialization
-- Message cutting in packets / Message reconstitution
--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

local MESSAGE_ID_1 = 1;
local MESSAGE_ID_2 = 1;
local MESSAGE_ID = string.char(MESSAGE_ID_1, MESSAGE_ID_2);
local COMPRESS_MESSAGE = true;

-- Message IDs are 256 base number encoded on 2 chars (256*256 = 65536 available Message IDs)
local function getMessageIDAndIncrement()
local toReturn = MESSAGE_ID;
MESSAGE_ID_2 = MESSAGE_ID_2 + 1;
if MESSAGE_ID_2 > 255 then
MESSAGE_ID_2 = 1;
MESSAGE_ID_1 = MESSAGE_ID_1 + 1;
if MESSAGE_ID_1 > 255 then
MESSAGE_ID_1 = 1;
end
end
MESSAGE_ID = string.char(MESSAGE_ID_1, MESSAGE_ID_2);
return toReturn;
end

-- Convert structure to message, cut message in packets.
local function handleStructureOut(structure, target, priority)
local message = libSerializer:Serialize(structure);
local messageID = getMessageIDAndIncrement();
local messageSize = message:len();
local packetTab = {};
local index = 0;
while index < messageSize do
tinsert(packetTab, message:sub(index, index + (AVAILABLE_CHARACTERS - 1)));
index = index + AVAILABLE_CHARACTERS;
end
handlePacketsOut(messageID, packetTab, target, priority);
end

-- Reassemble the message based on the packets, and deserialize it.
function handleStructureIn(packets, sender)
local message = tconcat(packets);
local status, structure = libSerializer:Deserialize(message);
if status then
receiveObject(structure, sender);
else
Log.log(("Deserialization error. Message:\n%s"):format(message), Log.level.SEVERE);
end
end

--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-- LAYER 3 : STRUCTURE LAYER
-- "What to do with the structure received / to send ?"
--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

local PREFIX_REGISTRATION = {};

-- Register a function to callback when receiving a object attached to the given prefix
function Comm.registerProtocolPrefix(prefix, callback)
assert(prefix and callback and type(callback) == "function", "Usage: prefix, callback");
if PREFIX_REGISTRATION[prefix] == nil then
PREFIX_REGISTRATION[prefix] = {};
end
tinsert(PREFIX_REGISTRATION[prefix], callback);
end

-- Send a object to a player
-- Prefix must have been registered before use this function
-- The object can be any lua type (numbers, strings, tables, but NOT functions or userdatas)
-- Priority is optional ("Bulk" by default)
function Comm.sendObject(prefix, object, target, priority)
assert(PREFIX_REGISTRATION[prefix] ~= nil, "Unregistered prefix: "..prefix);
if not isIDIgnored(target) then
local structure = {prefix, object};
handleStructureOut(structure, target, priority);
end
end

-- Receive a structure from a player (sender)
-- Call any callback registered for this prefix.
-- Structure[1] contains the prefix, structure[2] contains the object
function receiveObject(structure, sender)
if type(structure) == "table" and #structure == 2 then
local prefix = structure[1];
if PREFIX_REGISTRATION[prefix] then
for _, callback in pairs(PREFIX_REGISTRATION[prefix]) do
callback(structure[2], sender);
end
else
Log.log("No registration for prefix: " .. prefix, Log.level.INFO);
end
else
Log.log("Bad structure composition.", Log.level.SEVERE);
end
end

-- Estimate the number of packet needed to send a object.
function Comm.estimateStructureLoad(object)
assert(object, "Object nil");
return math.ceil((#(libSerializer:Serialize({"MOCK", object}))) / AVAILABLE_CHARACTERS);
end
Loading

0 comments on commit 6677a91

Please sign in to comment.