From 9aca1644e69053fc8aba42e5477ec7e2a29fd5db Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Sun, 27 Jan 2013 07:44:15 -0200 Subject: [PATCH] Implement rule violations, closes #218 --- init.lua | 5 +- modules/client/client.lua | 7 +- modules/game_console/console.lua | 207 +++++++++++++++++++---- modules/game_console/console.otui | 2 + modules/game_interface/interface.otmod | 2 +- modules/game_minimap/minimap.lua | 5 + modules/game_npctrade/npctrade.lua | 6 +- modules/game_playermount/playermount.lua | 23 ++- src/client/game.cpp | 21 +++ src/client/game.h | 5 + src/client/luafunctions.cpp | 3 + src/client/protocolcodes.h | 3 + src/client/protocolgame.h | 3 + src/client/protocolgameparse.cpp | 2 + src/client/protocolgamesend.cpp | 26 +++ 15 files changed, 282 insertions(+), 38 deletions(-) diff --git a/init.lua b/init.lua index 30e37bb6..76251382 100644 --- a/init.lua +++ b/init.lua @@ -47,7 +47,8 @@ g_modules.ensureModuleLoaded("game_interface") -- mods 1000-9999 g_modules.autoLoadModules(9999) -if g_resources.fileExists("/otclientrc") then - dofile("/otclientrc") +local script = '/' .. g_app.getCompactName() .. 'rc' +if g_resources.fileExists(script) then + dofile(script) end diff --git a/modules/client/client.lua b/modules/client/client.lua index 02e345fe..75dbfc06 100644 --- a/modules/client/client.lua +++ b/modules/client/client.lua @@ -13,7 +13,12 @@ end function reloadScripts() g_textures.clearTexturesCache() g_modules.reloadModules() - dofile('/' .. g_app.getCompactName() .. 'rc') + + local script = '/' .. g_app.getCompactName() .. 'rc' + if g_resources.fileExists(script) then + dofile(script) + end + local message = tr('All modules and scripts were reloaded.') modules.game_textmessage.displayGameMessage(message) diff --git a/modules/game_console/console.lua b/modules/game_console/console.lua index 735f0a5c..abef97b1 100644 --- a/modules/game_console/console.lua +++ b/modules/game_console/console.lua @@ -15,6 +15,9 @@ SpeakTypesSettings = { channelOrange = { speakType = MessageModes.ChannelHighlight, color = '#FE6500' }, monsterSay = { speakType = MessageModes.MonsterSay, color = '#FE6500', hideInConsole = true}, monsterYell = { speakType = MessageModes.MonsterYell, color = '#FE6500', hideInConsole = true}, + rvrAnswerFrom = { speakType = MessageModes.RVRAnswer, color = '#FE6500' }, + rvrAnswerTo = { speakType = MessageModes.RVRAnswer, color = '#FE6500' }, + rvrContinue = { speakType = MessageModes.RVRContinue, color = '#FFFF00' }, } SpeakTypes = { @@ -32,6 +35,9 @@ SpeakTypes = { [MessageModes.ChannelHighlight] = SpeakTypesSettings.channelOrange, [MessageModes.MonsterSay] = SpeakTypesSettings.monsterSay, [MessageModes.MonsterYell] = SpeakTypesSettings.monsterYell, + [MessageModes.RVRChannel] = SpeakTypesSettings.channelWhite, + [MessageModes.RVRContinue] = SpeakTypesSettings.rvrContinue, + [MessageModes.RVRAnswer] = SpeakTypesSettings.rvrAnswerFrom, -- ignored types [MessageModes.Spell] = SpeakTypesSettings.none, @@ -62,6 +68,9 @@ currentMessageIndex = 0 ignoreNpcMessages = false defaultTab = nil serverTab = nil +violationsChannelId = nil +violationWindow = nil +violationReportTab = nil local ignoreSettings = { privateMessages = false, @@ -76,8 +85,12 @@ function init() onOpenPrivateChannel = onOpenPrivateChannel, onOpenOwnPrivateChannel = onOpenOwnPrivateChannel, onCloseChannel = onCloseChannel, - onGameStart = onGameStart, - onGameEnd = clear }) + onRuleViolationChannel = onRuleViolationChannel, + onRuleViolationRemove = onRuleViolationRemove, + onRuleViolationCancel = onRuleViolationCancel, + onRuleViolationLock = onRuleViolationLock, + onGameStart = online, + onGameEnd = offline }) consolePanel = g_ui.loadUI('console', modules.game_interface.getBottomPanel()) consoleTextEdit = consolePanel:getChildById('consoleTextEdit') @@ -134,8 +147,12 @@ function terminate() onOpenPrivateChannel = onOpenPrivateChannel, onOpenOwnPrivateChannel = onOpenPrivateChannel, onCloseChannel = onCloseChannel, - onGameStart = onGameStart, - onGameEnd = clear }) + onRuleViolationChannel = onRuleViolationChannel, + onRuleViolationRemove = onRuleViolationRemove, + onRuleViolationCancel = onRuleViolationCancel, + onRuleViolationLock = onRuleViolationLock, + onGameStart = online, + onGameEnd = offline }) if g_game.isOnline() then clear() end @@ -155,6 +172,11 @@ function terminate() ignoreWindow = nil end + if violationWindow then + violationWindow:destroy() + violationWindow = nil + end + consolePanel:destroy() consolePanel = nil consoleTextEdit = nil @@ -208,8 +230,18 @@ function clear() consoleTabBar:removeTab(npcTab) end + if violationReportTab then + consoleTabBar:removeTab(violationReportTab) + violationReportTab = nil + end + consoleTextEdit:clearText() + if violationWindow then + violationWindow:destroy() + violationWindow = nil + end + if channelsWindow then channelsWindow:destroy() channelsWindow = nil @@ -234,6 +266,24 @@ function openHelp() g_game.joinChannel(helpChannel) end +function openPlayerReportRuleViolationWindow() + if violationWindow or violationReportTab then return end + violationWindow = g_ui.loadUI('violationwindow', rootWidget) + violationWindow.onEscape = function() + violationWindow:destroy() + violationWindow = nil + end + violationWindow.onEnter = function() + local text = violationWindow:getChildById('text'):getText() + g_game.talkChannel(MessageModes.RVRChannel, 0, text) + violationReportTab = addTab(tr('Report Rule') .. '...', true) + addTabText(tr('Please wait patiently for a gamemaster to reply') .. '.', SpeakTypesSettings.privateRed, violationReportTab) + violationReportTab.locked = true + violationWindow:destroy() + violationWindow = nil + end +end + function addTab(name, focus) local tab = getTab(name) if tab then -- is channel already open @@ -249,12 +299,20 @@ function addTab(name, focus) return tab end -function removeTab(name) - local tab = consoleTabBar:getTab(name) +function removeTab(tab) + if type(tab) == 'string' then + tab = consoleTabBar:getTab(name) + end + if tab == defaultTab or tab == serverTab then return end + if tab == violationReportTab then + g_game.cancelRuleViolation() + violationReportTab = nil + elseif tab.violationChatName then + g_game.closeRuleViolation(tab.violationChatName) -- notificate the server that we are leaving the channel - if tab.channelId then + elseif tab.channelId then for k, v in pairs(channels) do if (k == tab.channelId) then channels[k] = nil end end @@ -268,25 +326,28 @@ end function removeCurrentTab() local tab = consoleTabBar:getCurrentTab() - if tab == defaultTab or tab == serverTab then return end - - -- notificate the server that we are leaving the channel - if tab.channelId then - for k, v in pairs(channels) do - if (k == tab.channelId) then channels[k] = nil end - end - g_game.leaveChannel(tab.channelId) - elseif tab:getText() == "NPCs" then - g_game.closeNpcChannel() - end - - consoleTabBar:removeTab(tab) + removeTab(tab) end function getTab(name) return consoleTabBar:getTab(name) end +function getChannelTab(channelId) + local channel = channels[channelId] + if channel then + return getTab(channel) + end + return nil +end + +function getRuleViolationsTab() + if violationsChannelId then + return getChannelTab(violationsChannelId) + end + return nil +end + function getCurrentTab() return consoleTabBar:getCurrentTab() end @@ -365,6 +426,8 @@ function getHighlightedText(text) end function addTabText(text, speaktype, tab, creatureName) + if not tab or tab.locked or not text or #text == 0 then return end + if modules.client_options.getOption('showTimestampsInConsole') then text = os.date('%H:%M') .. ' ' .. text end @@ -432,8 +495,11 @@ function addTabText(text, speaktype, tab, creatureName) labelHighlight:setText("") end - label.onMouseRelease = function (self, mousePos, mouseButton) - processMessageMenu(mousePos, mouseButton, creatureName, text, self) + label.name = creatureName + if creatureName and #creatureName > 0 then + label.onMouseRelease = function (self, mousePos, mouseButton) + processMessageMenu(mousePos, mouseButton, creatureName, text, self, tab) + end end if consoleBuffer:getChildCount() > MAX_LINES then @@ -445,6 +511,16 @@ function addTabText(text, speaktype, tab, creatureName) end end +function removeTabLabelByName(tab, name) + local panel = consoleTabBar:getTabPanel(tab) + local consoleBuffer = panel:getChildById('consoleBuffer') + for _,label in pairs(consoleBuffer:getChildren()) do + if label.name == name then + label:destroy() + end + end +end + function processChannelTabMenu(tab, mousePos, mouseButton) local menu = g_ui.createWidget('PopupMenu') @@ -460,7 +536,7 @@ function processChannelTabMenu(tab, mousePos, mouseButton) menu:display(mousePos) end -function processMessageMenu(mousePos, mouseButton, creatureName, text, label) +function processMessageMenu(mousePos, mouseButton, creatureName, text, label, tab) if mouseButton == MouseRightButton then local menu = g_ui.createWidget('PopupMenu') if creatureName then @@ -493,6 +569,11 @@ function processMessageMenu(mousePos, mouseButton, creatureName, text, label) end menu:addOption(tr('Copy message'), function() g_window.setClipboardText(text) end) menu:addOption(tr('Select all'), function() label:selectAll() end) + if tab.violations then + menu:addSeparator() + menu:addOption(tr('Process') .. ' ' .. creatureName, function() processViolation(creatureName, text) end) + menu:addOption(tr('Remove') .. ' ' .. creatureName, function() g_game.closeRuleViolation(creatureName) end) + end menu:display(mousePos) end end @@ -509,6 +590,8 @@ end function sendMessage(message, tab) local tab = tab or getCurrentTab() + if tab == getRuleViolationsTab() then return end + -- handling chat commands local originalMessage = message local chatCommandSayMode @@ -567,12 +650,21 @@ function sendMessage(message, tab) return else local isPrivateCommand = false + local priv = true + local tabname = name if chatCommandPrivateReady then speaktypedesc = 'privatePlayerToPlayer' name = chatCommandPrivate isPrivateCommand = true elseif tab.npcChat then speaktypedesc = 'privatePlayerToNpc' + elseif tab == violationReportTab then + speaktypedesc = 'rvrContinue' + tabname = tr('Report Rule') .. '...' + elseif tab.violationChatName then + speaktypedesc = 'rvrAnswerTo' + name = tab.violationChatName + tabname = tab.violationChatName .. '\'...' else speaktypedesc = 'privatePlayerToPlayer' end @@ -583,7 +675,7 @@ function sendMessage(message, tab) g_game.talkPrivate(speaktype.speakType, name, message) message = applyMessagePrefixies(player:getName(), player:getLevel(), message) - addPrivateText(message, speaktype, name, isPrivateCommand, g_game.getCharacterName()) + addPrivateText(message, speaktype, tabname, isPrivateCommand, g_game.getCharacterName()) end end @@ -641,6 +733,12 @@ function onTalk(name, level, mode, message, channelId, creaturePos) if ignoreNpcMessages and mode == MessageModes.NpcFrom then return end speaktype = SpeakTypes[mode] + + if not speaktype then + perror('unhandled onTalk message mode ' .. mode .. ': ' .. message) + return + end + if name ~= g_game.getLocalPlayer():getName() then if mode == MessageModes.Yell and isIgnoringYelling() then return @@ -651,6 +749,10 @@ function onTalk(name, level, mode, message, channelId, creaturePos) end end + if mode == MessageModes.RVRChannel then + channelId = violationsChannelId + end + if (mode == MessageModes.Say or mode == MessageModes.Whisper or mode == MessageModes.Yell or mode == MessageModes.Spell or mode == MessageModes.MonsterSay or mode == MessageModes.MonsterYell or mode == MessageModes.NpcFrom or mode == MessageModes.BarkLow or mode == MessageModes.BarkLoud) and @@ -674,18 +776,18 @@ function onTalk(name, level, mode, message, channelId, creaturePos) local defaultMessage = mode <= 3 and true or false - if not speaktype then - perror('unhandled onTalk message mode ' .. mode .. ': ' .. message) - return - end - if speaktype == SpeakTypesSettings.none then return end if speaktype.hideInConsole then return end local composedMessage = applyMessagePrefixies(name, level, message) - if speaktype.private then + if mode == MessageModes.RVRAnswer then + violationReportTab.locked = false + addTabText(composedMessage, speaktype, violationReportTab, name) + elseif mode == MessageModes.RVRContinue then + addText(composedMessage, speaktype, name .. '\'...', name) + elseif speaktype.private then addPrivateText(composedMessage, speaktype, name, false, name) if modules.client_options.getOption('showPrivateMessagesOnScreen') and speaktype ~= SpeakTypesSettings.privateNpcToPlayer then modules.game_textmessage.displayPrivateMessage(name .. ':\n' .. message) @@ -734,6 +836,40 @@ function onCloseChannel(channelId) end end +function processViolation(name, text) + local tabname = name .. '\'...' + local tab = addTab(tabname, true) + channels[tabname] = tabname + tab.violationChatName = name + g_game.openRuleViolation(name) + addTabText(text, SpeakTypesSettings.say, tab) +end + +function onRuleViolationChannel(channelId) + violationsChannelId = channelId + local tab = addChannel(tr('Rule Violations'), channelId) + tab.violations = true +end + +function onRuleViolationRemove(name) + local tab = getRuleViolationsTab() + if not tab then return end + removeTabLabelByName(tab, name) +end + +function onRuleViolationCancel(name) + local tab = getTab(name .. '\'...') + if not tab then return end + addTabText(tr('%s has finished the request', name) .. '.', SpeakTypesSettings.privateRed, tab) + tab.locked = true +end + +function onRuleViolationLock() + if not violationReportTab then return end + addTabText(tr('Your request has been closed') .. '.', SpeakTypesSettings.privateRed, violationReportTab) + violationReportTab.locked = true +end + function doChannelListSubmit() local channelListPanel = channelsWindow:getChildById('channelList') local openPrivateChannelWith = channelsWindow:getChildById('openPrivateChannelWith'):getText() @@ -884,7 +1020,10 @@ function onClickIgnoreButton() end end -function onGameStart() +function online() + if g_game.getProtocolVersion() < 862 then + g_keyboard.bindKeyDown('Ctrl+R', openPlayerReportRuleViolationWindow) + end -- open last channels local lastChannelsOpen = g_settings.getNode('lastChannelsOpen') if lastChannelsOpen then @@ -913,3 +1052,9 @@ function onGameStart() end end +function offline() + if g_game.getProtocolVersion() < 862 then + g_keyboard.unbindKeyDown('Ctrl+R') + end + clear() +end diff --git a/modules/game_console/console.otui b/modules/game_console/console.otui index 3e722603..e00e98a3 100644 --- a/modules/game_console/console.otui +++ b/modules/game_console/console.otui @@ -8,6 +8,8 @@ ConsoleLabel < UITextEdit selection-color: #111416 selection-background-color: #999999 change-cursor-image: false + cursor-visible: false + editable: false ConsolePhantomLabel < UILabel font: verdana-11px-antialised diff --git a/modules/game_interface/interface.otmod b/modules/game_interface/interface.otmod index 51c99eb5..91f0973c 100644 --- a/modules/game_interface/interface.otmod +++ b/modules/game_interface/interface.otmod @@ -22,10 +22,10 @@ Module - game_npctrade - game_textwindow - game_playertrade - - game_ruleviolation - game_bugreport - game_playerdeath - game_playermount + - game_ruleviolation - game_market - game_spelllist - game_cooldown diff --git a/modules/game_minimap/minimap.lua b/modules/game_minimap/minimap.lua index 57a6b9e2..4b81e54d 100644 --- a/modules/game_minimap/minimap.lua +++ b/modules/game_minimap/minimap.lua @@ -56,6 +56,11 @@ function init() end function terminate() + g_keyboard.unbindKeyPress('Alt+Left') + g_keyboard.unbindKeyPress('Alt+Right') + g_keyboard.unbindKeyPress('Alt+Up') + g_keyboard.unbindKeyPress('Alt+Down') + disconnect(g_game, { onGameStart = online, onGameEnd = offline, diff --git a/modules/game_npctrade/npctrade.lua b/modules/game_npctrade/npctrade.lua index 8b44780a..a1bfe161 100644 --- a/modules/game_npctrade/npctrade.lua +++ b/modules/game_npctrade/npctrade.lua @@ -22,6 +22,7 @@ capacityLabel = nil tradeButton = nil buyTab = nil sellTab = nil +initialized = false showWeight = true buyWithBackpack = nil @@ -82,9 +83,12 @@ function init() connect(LocalPlayer, { onFreeCapacityChange = onFreeCapacityChange, onInventoryChange = onInventoryChange } ) + + initialized = true end function terminate() + initialized = false npcWindow:destroy() disconnect(g_game, { onGameEnd = hide, @@ -352,7 +356,7 @@ function refreshTradeItems() end function refreshPlayerGoods() - if not g_game.isOnline() then return end + if not initialized then return end moneyLabel:setText(playerMoney .. ' ' .. CURRENCY) capacityLabel:setText(string.format('%.2f', playerFreeCapacity) .. ' ' .. WEIGHT_UNIT) diff --git a/modules/game_playermount/playermount.lua b/modules/game_playermount/playermount.lua index 1bd65c4c..660f852c 100644 --- a/modules/game_playermount/playermount.lua +++ b/modules/game_playermount/playermount.lua @@ -1,9 +1,28 @@ function init() - g_keyboard.bindKeyDown('Ctrl+R', toggleMount, gameRootPanel) + connect(g_game, { + onGameStart = online, + onGameEnd = offline + }) + if g_game.isOnline() then online() end end function terminate() - g_keyboard.unbindKeyDown('Ctrl+R', gameRootPanel) + disconnect(g_game, { + onGameStart = online, + onGameEnd = offline + }) +end + +function online() + if g_game.getFeature(GamePlayerMounts) then + g_keyboard.bindKeyDown('Ctrl+R', toggleMount) + end +end + +function offline() + if g_game.getFeature(GamePlayerMounts) then + g_keyboard.unbindKeyDown('Ctrl+R') + end end function toggleMount() diff --git a/src/client/game.cpp b/src/client/game.cpp index 68966b45..d075de1c 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1156,6 +1156,27 @@ void Game::editList(uint id, int doorId, const std::string& text) m_protocolGame->sendEditList(id, doorId, text); } +void Game::openRuleViolation(const std::string& reporter) +{ + if(!canPerformGameAction()) + return; + m_protocolGame->sendOpenRuleViolation(reporter); +} + +void Game::closeRuleViolation(const std::string& reporter) +{ + if(!canPerformGameAction()) + return; + m_protocolGame->sendCloseRuleViolation(reporter); +} + +void Game::cancelRuleViolation() +{ + if(!canPerformGameAction()) + return; + m_protocolGame->sendCancelRuleViolation(); +} + void Game::reportBug(const std::string& comment) { if(!canPerformGameAction()) diff --git a/src/client/game.h b/src/client/game.h index 27f22675..e90afd85 100644 --- a/src/client/game.h +++ b/src/client/game.h @@ -225,6 +225,11 @@ public: void editText(uint id, const std::string& text); void editList(uint id, int doorId, const std::string& text); + // rule violations (only gms) + void openRuleViolation(const std::string& reporter); + void closeRuleViolation(const std::string& reporter); + void cancelRuleViolation(); + // reports void reportBug(const std::string& comment); void reportRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment); diff --git a/src/client/luafunctions.cpp b/src/client/luafunctions.cpp index 3d4f8d34..d98bb3fe 100644 --- a/src/client/luafunctions.cpp +++ b/src/client/luafunctions.cpp @@ -196,6 +196,9 @@ void Client::registerLuaFunctions() g_lua.bindSingletonFunction("g_game", "inspectTrade", &Game::inspectTrade, &g_game); g_lua.bindSingletonFunction("g_game", "acceptTrade", &Game::acceptTrade, &g_game); g_lua.bindSingletonFunction("g_game", "rejectTrade", &Game::rejectTrade, &g_game); + g_lua.bindSingletonFunction("g_game", "openRuleViolation", &Game::openRuleViolation, &g_game); + g_lua.bindSingletonFunction("g_game", "closeRuleViolation", &Game::closeRuleViolation, &g_game); + g_lua.bindSingletonFunction("g_game", "cancelRuleViolation", &Game::cancelRuleViolation, &g_game); g_lua.bindSingletonFunction("g_game", "reportBug", &Game::reportBug, &g_game); g_lua.bindSingletonFunction("g_game", "reportRuleViolation", &Game::reportRuleViolation, &g_game); g_lua.bindSingletonFunction("g_game", "debugReport", &Game::debugReport, &g_game); diff --git a/src/client/protocolcodes.h b/src/client/protocolcodes.h index 43c8e9b3..4a2e4adc 100644 --- a/src/client/protocolcodes.h +++ b/src/client/protocolcodes.h @@ -204,6 +204,9 @@ namespace Proto { ClientJoinChannel = 152, ClientLeaveChannel = 153, ClientOpenPrivateChannel = 154, + ClientOpenRuleViolation = 155, + ClientCloseRuleViolation = 156, + ClientCancelRuleViolation = 157, ClientCloseNpcChannel = 158, ClientChangeFightModes = 160, ClientAttack = 161, diff --git a/src/client/protocolgame.h b/src/client/protocolgame.h index 0c15ad76..cdd849c4 100644 --- a/src/client/protocolgame.h +++ b/src/client/protocolgame.h @@ -79,6 +79,9 @@ public: void sendJoinChannel(int channelId); void sendLeaveChannel(int channelId); void sendOpenPrivateChannel(const std::string& receiver); + void sendOpenRuleViolation(const std::string& reporter); + void sendCloseRuleViolation(const std::string& reporter); + void sendCancelRuleViolation(); void sendCloseNpcChannel(); void sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeFight); void sendAttack(uint creatureId, uint seq); diff --git a/src/client/protocolgameparse.cpp b/src/client/protocolgameparse.cpp index 98d0daa9..e4f4f9d9 100644 --- a/src/client/protocolgameparse.cpp +++ b/src/client/protocolgameparse.cpp @@ -1123,6 +1123,8 @@ void ProtocolGame::parseTalk(const InputMessagePtr& msg) case Otc::MessagePrivateFrom: case Otc::MessageGamemasterBroadcast: case Otc::MessageGamemasterPrivateFrom: + case Otc::MessageRVRAnswer: + case Otc::MessageRVRContinue: break; case Otc::MessageRVRChannel: msg->getU32(); diff --git a/src/client/protocolgamesend.cpp b/src/client/protocolgamesend.cpp index f388a7e3..391f6745 100644 --- a/src/client/protocolgamesend.cpp +++ b/src/client/protocolgamesend.cpp @@ -502,6 +502,7 @@ void ProtocolGame::sendTalk(Otc::MessageMode mode, int channelId, const std::str switch(mode) { case Otc::MessagePrivateTo: case Otc::MessageGamemasterPrivateTo: + case Otc::MessageRVRAnswer: msg->addString(receiver); break; case Otc::MessageChannel: @@ -549,6 +550,31 @@ void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver) send(msg); } +void ProtocolGame::sendOpenRuleViolation(const std::string& reporter) +{ + OutputMessagePtr msg(new OutputMessage); + msg->addU8(Proto::ClientOpenRuleViolation); + msg->addString(reporter); + send(msg); +} + +void ProtocolGame::sendCloseRuleViolation(const std::string& reporter) +{ + OutputMessagePtr msg(new OutputMessage); + msg->addU8(Proto::ClientCloseRuleViolation); + msg->addString(reporter); + dump << "ProtocolGame::sendCloseRuleViolation" << reporter; + send(msg); +} + +void ProtocolGame::sendCancelRuleViolation() +{ + OutputMessagePtr msg(new OutputMessage); + msg->addU8(Proto::ClientCancelRuleViolation); + dump << "ProtocolGame::sendCancelRuleViolation"; + send(msg); +} + void ProtocolGame::sendCloseNpcChannel() { OutputMessagePtr msg(new OutputMessage);