mirror of
https://github.com/edubart/otclient.git
synced 2025-06-05 18:44:28 +02:00
Merge with 'master'
This commit is contained in:
commit
2d65a0a3ed
@ -1,4 +1,4 @@
|
||||
[](http://travis-ci.org/edubart/otclient)
|
||||
[](http://travis-ci.org/edubart/otclient) [](https://gitter.im/edubart/otclient?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
### What is otclient?
|
||||
|
||||
Otclient is an alternative Tibia client for usage with otserv. It aims to be complete and flexible,
|
||||
|
@ -78,7 +78,7 @@ local function onCharacterList(protocol, characters, account, otui)
|
||||
if motdEnabled then
|
||||
local lastMotdNumber = g_settings.getNumber("motd")
|
||||
if G.motdNumber and G.motdNumber ~= lastMotdNumber then
|
||||
g_settings.set("motd", motdNumber)
|
||||
g_settings.set("motd", G.motdNumber)
|
||||
motdWindow = displayInfoBox(tr('Message of the day'), G.motdMessage)
|
||||
connect(motdWindow, { onOk = function() CharacterList.show() motdWindow = nil end })
|
||||
CharacterList.hide()
|
||||
|
@ -10,6 +10,7 @@ Module
|
||||
dofile 'string'
|
||||
dofile 'table'
|
||||
dofile 'bitwise'
|
||||
dofile 'struct'
|
||||
|
||||
dofile 'const'
|
||||
dofile 'util'
|
||||
|
173
modules/corelib/struct.lua
Normal file
173
modules/corelib/struct.lua
Normal file
@ -0,0 +1,173 @@
|
||||
Struct = {}
|
||||
|
||||
function Struct.pack(format, ...)
|
||||
local stream = {}
|
||||
local vars = {...}
|
||||
local endianness = true
|
||||
|
||||
for i = 1, format:len() do
|
||||
local opt = format:sub(i, i)
|
||||
|
||||
if opt == '>' then
|
||||
endianness = false
|
||||
elseif opt:find('[bBhHiIlL]') then
|
||||
local n = opt:find('[hH]') and 2 or opt:find('[iI]') and 4 or opt:find('[lL]') and 8 or 1
|
||||
local val = tonumber(table.remove(vars, 1))
|
||||
|
||||
if val < 0 then
|
||||
val = val + 2 ^ (n * 8 - 1)
|
||||
end
|
||||
|
||||
local bytes = {}
|
||||
for j = 1, n do
|
||||
table.insert(bytes, string.char(val % (2 ^ 8)))
|
||||
val = math.floor(val / (2 ^ 8))
|
||||
end
|
||||
|
||||
if not endianness then
|
||||
table.insert(stream, string.reverse(table.concat(bytes)))
|
||||
else
|
||||
table.insert(stream, table.concat(bytes))
|
||||
end
|
||||
elseif opt:find('[fd]') then
|
||||
local val = tonumber(table.remove(vars, 1))
|
||||
local sign = 0
|
||||
|
||||
if val < 0 then
|
||||
sign = 1
|
||||
val = -val
|
||||
end
|
||||
|
||||
local mantissa, exponent = math.frexp(val)
|
||||
if val == 0 then
|
||||
mantissa = 0
|
||||
exponent = 0
|
||||
else
|
||||
mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, (opt == 'd') and 53 or 24)
|
||||
exponent = exponent + ((opt == 'd') and 1022 or 126)
|
||||
end
|
||||
|
||||
local bytes = {}
|
||||
if opt == 'd' then
|
||||
val = mantissa
|
||||
for i = 1, 6 do
|
||||
table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
|
||||
val = math.floor(val / (2 ^ 8))
|
||||
end
|
||||
else
|
||||
table.insert(bytes, string.char(math.floor(mantissa) % (2 ^ 8)))
|
||||
val = math.floor(mantissa / (2 ^ 8))
|
||||
table.insert(bytes, string.char(math.floor(val) % (2 ^ 8)))
|
||||
val = math.floor(val / (2 ^ 8))
|
||||
end
|
||||
|
||||
table.insert(bytes, string.char(math.floor(exponent * ((opt == 'd') and 16 or 128) + val) % (2 ^ 8)))
|
||||
val = math.floor((exponent * ((opt == 'd') and 16 or 128) + val) / (2 ^ 8))
|
||||
table.insert(bytes, string.char(math.floor(sign * 128 + val) % (2 ^ 8)))
|
||||
val = math.floor((sign * 128 + val) / (2 ^ 8))
|
||||
|
||||
if not endianness then
|
||||
table.insert(stream, string.reverse(table.concat(bytes)))
|
||||
else
|
||||
table.insert(stream, table.concat(bytes))
|
||||
end
|
||||
elseif opt == 's' then
|
||||
table.insert(stream, tostring(table.remove(vars, 1)))
|
||||
table.insert(stream, string.char(0))
|
||||
elseif opt == 'c' then
|
||||
local n = format:sub(i + 1):match('%d+')
|
||||
local length = tonumber(n)
|
||||
|
||||
if length > 0 then
|
||||
local str = tostring(table.remove(vars, 1))
|
||||
if length - str:len() > 0 then
|
||||
str = str .. string.rep(' ', length - str:len())
|
||||
end
|
||||
table.insert(stream, str:sub(1, length))
|
||||
end
|
||||
i = i + n:len()
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(stream)
|
||||
end
|
||||
|
||||
function Struct.unpack(format, stream)
|
||||
local vars = {}
|
||||
local iterator = 1
|
||||
local endianness = true
|
||||
|
||||
for i = 1, format:len() do
|
||||
local opt = format:sub(i, i)
|
||||
|
||||
if opt == '>' then
|
||||
endianness = false
|
||||
elseif opt:find('[bBhHiIlL]') then
|
||||
local n = opt:find('[hH]') and 2 or opt:find('[iI]') and 4 or opt:find('[lL]') and 8 or 1
|
||||
local signed = opt:lower() == opt
|
||||
|
||||
local val = 0
|
||||
for j = 1, n do
|
||||
local byte = string.byte(stream:sub(iterator, iterator))
|
||||
if endianness then
|
||||
val = val + byte * (2 ^ ((j - 1) * 8))
|
||||
else
|
||||
val = val + byte * (2 ^ ((n - j) * 8))
|
||||
end
|
||||
iterator = iterator + 1
|
||||
end
|
||||
|
||||
if signed then
|
||||
val = val - 2 ^ (n * 8 - 1)
|
||||
end
|
||||
|
||||
table.insert(vars, val)
|
||||
elseif opt:find('[fd]') then
|
||||
local n = (opt == 'd') and 8 or 4
|
||||
local x = stream:sub(iterator, iterator + n - 1)
|
||||
iterator = iterator + n
|
||||
|
||||
if not endianness then
|
||||
x = string.reverse(x)
|
||||
end
|
||||
|
||||
local sign = 1
|
||||
local mantissa = string.byte(x, (opt == 'd') and 7 or 3) % ((opt == 'd') and 16 or 128)
|
||||
for i = n - 2, 1, -1 do
|
||||
mantissa = mantissa * (2 ^ 8) + string.byte(x, i)
|
||||
end
|
||||
|
||||
if string.byte(x, n) > 127 then
|
||||
sign = -1
|
||||
end
|
||||
|
||||
local exponent = (string.byte(x, n) % 128) * ((opt == 'd') and 16 or 2) + math.floor(string.byte(x, n - 1) / ((opt == 'd') and 16 or 128))
|
||||
if exponent == 0 then
|
||||
table.insert(vars, 0.0)
|
||||
else
|
||||
mantissa = (math.ldexp(mantissa, (opt == 'd') and -52 or -23) + 1) * sign
|
||||
table.insert(vars, math.ldexp(mantissa, exponent - ((opt == 'd') and 1023 or 127)))
|
||||
end
|
||||
elseif opt == 's' then
|
||||
local bytes = {}
|
||||
for j = iterator, stream:len() do
|
||||
if stream:sub(j, j) == string.char(0) then
|
||||
break
|
||||
end
|
||||
|
||||
table.insert(bytes, stream:sub(j, j))
|
||||
end
|
||||
|
||||
local str = table.concat(bytes)
|
||||
iterator = iterator + str:len() + 1
|
||||
table.insert(vars, str)
|
||||
elseif opt == 'c' then
|
||||
local n = format:sub(i + 1):match('%d+')
|
||||
table.insert(vars, stream:sub(iterator, iterator + tonumber(n)))
|
||||
iterator = iterator + tonumber(n)
|
||||
i = i + n:len()
|
||||
end
|
||||
end
|
||||
|
||||
return unpack(vars)
|
||||
end
|
@ -296,6 +296,16 @@ function numbertoboolean(number)
|
||||
end
|
||||
end
|
||||
|
||||
function protectedcall(func, ...)
|
||||
local status, ret = pcall(func, ...)
|
||||
if status then
|
||||
return ret
|
||||
end
|
||||
|
||||
perror(ret)
|
||||
return false
|
||||
end
|
||||
|
||||
function signalcall(param, ...)
|
||||
if type(param) == 'function' then
|
||||
local status, ret = pcall(param, ...)
|
||||
|
@ -113,13 +113,10 @@ function init()
|
||||
local tab = consoleTabBar:getCurrentTab()
|
||||
if not tab then return false end
|
||||
|
||||
local consoleBuffer = tab.tabPanel:getChildById('consoleBuffer')
|
||||
if not consoleBuffer then return false end
|
||||
local selection = tab.tabPanel:getChildById('consoleBuffer').selectionText
|
||||
if not selection then return false end
|
||||
|
||||
local consoleLabel = consoleBuffer:getFocusedChild()
|
||||
if not consoleLabel or not consoleLabel:hasSelection() then return false end
|
||||
|
||||
g_window.setClipboardText(consoleLabel:getSelection())
|
||||
g_window.setClipboardText(selection)
|
||||
return true
|
||||
end
|
||||
|
||||
@ -147,6 +144,27 @@ function init()
|
||||
end
|
||||
end
|
||||
|
||||
function clearSelection(consoleBuffer)
|
||||
for _,label in pairs(consoleBuffer:getChildren()) do
|
||||
label:clearSelection()
|
||||
end
|
||||
consoleBuffer.selectionText = nil
|
||||
consoleBuffer.selection = nil
|
||||
end
|
||||
|
||||
function selectAll(consoleBuffer)
|
||||
clearSelection(consoleBuffer)
|
||||
if consoleBuffer:getChildCount() > 0 then
|
||||
local text = {}
|
||||
for _,label in pairs(consoleBuffer:getChildren()) do
|
||||
label:selectAll()
|
||||
table.insert(text, label:getSelection())
|
||||
end
|
||||
consoleBuffer.selectionText = table.concat(text, '\n')
|
||||
consoleBuffer.selection = { first = consoleBuffer:getChildIndex(consoleBuffer:getFirstChild()), last = consoleBuffer:getChildIndex(consoleBuffer:getLastChild()) }
|
||||
end
|
||||
end
|
||||
|
||||
function toggleChat()
|
||||
if consoleToggleChat:isChecked() then
|
||||
disableChat()
|
||||
@ -577,12 +595,102 @@ function addTabText(text, speaktype, tab, creatureName)
|
||||
end
|
||||
|
||||
label.name = creatureName
|
||||
label.onMouseRelease = function (self, mousePos, mouseButton)
|
||||
consoleBuffer.onMouseRelease = function(self, mousePos, mouseButton)
|
||||
processMessageMenu(mousePos, mouseButton, nil, nil, nil, tab)
|
||||
end
|
||||
label.onMouseRelease = function(self, mousePos, mouseButton)
|
||||
processMessageMenu(mousePos, mouseButton, creatureName, text, self, tab)
|
||||
end
|
||||
label.onMousePress = function(self, mousePos, button)
|
||||
if button == MouseLeftButton then clearSelection(consoleBuffer) end
|
||||
end
|
||||
label.onDragEnter = function(self, mousePos)
|
||||
clearSelection(consoleBuffer)
|
||||
return true
|
||||
end
|
||||
label.onDragLeave = function(self, droppedWidget, mousePos)
|
||||
local text = {}
|
||||
for selectionChild = consoleBuffer.selection.first, consoleBuffer.selection.last do
|
||||
local label = self:getParent():getChildByIndex(selectionChild)
|
||||
table.insert(text, label:getSelection())
|
||||
end
|
||||
consoleBuffer.selectionText = table.concat(text, '\n')
|
||||
return true
|
||||
end
|
||||
label.onDragMove = function(self, mousePos, mouseMoved)
|
||||
local parent = self:getParent()
|
||||
local parentRect = parent:getPaddingRect()
|
||||
local selfIndex = parent:getChildIndex(self)
|
||||
local child = parent:getChildByPos(mousePos)
|
||||
|
||||
-- find bonding children
|
||||
if not child then
|
||||
if mousePos.y < self:getY() then
|
||||
for index = selfIndex - 1, 1, -1 do
|
||||
local label = parent:getChildByIndex(index)
|
||||
if label:getY() + label:getHeight() > parentRect.y then
|
||||
if (mousePos.y >= label:getY() and mousePos.y <= label:getY() + label:getHeight()) or index == 1 then
|
||||
child = label
|
||||
break
|
||||
end
|
||||
else
|
||||
child = parent:getChildByIndex(index + 1)
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif mousePos.y > self:getY() + self:getHeight() then
|
||||
for index = selfIndex + 1, parent:getChildCount(), 1 do
|
||||
local label = parent:getChildByIndex(index)
|
||||
if label:getY() < parentRect.y + parentRect.height then
|
||||
if (mousePos.y >= label:getY() and mousePos.y <= label:getY() + label:getHeight()) or index == parent:getChildCount() then
|
||||
child = label
|
||||
break
|
||||
end
|
||||
else
|
||||
child = parent:getChildByIndex(index - 1)
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
child = self
|
||||
end
|
||||
end
|
||||
|
||||
if not child then return false end
|
||||
|
||||
local childIndex = parent:getChildIndex(child)
|
||||
|
||||
-- remove old selection
|
||||
clearSelection(consoleBuffer)
|
||||
|
||||
-- update self selection
|
||||
local textBegin = self:getTextPos(self:getLastClickPosition())
|
||||
local textPos = self:getTextPos(mousePos)
|
||||
self:setSelection(textBegin, textPos)
|
||||
|
||||
consoleBuffer.selection = { first = math.min(selfIndex, childIndex), last = math.max(selfIndex, childIndex) }
|
||||
|
||||
-- update siblings selection
|
||||
if child ~= self then
|
||||
for selectionChild = consoleBuffer.selection.first + 1, consoleBuffer.selection.last - 1 do
|
||||
parent:getChildByIndex(selectionChild):selectAll()
|
||||
end
|
||||
|
||||
local textPos = child:getTextPos(mousePos)
|
||||
if childIndex > selfIndex then
|
||||
child:setSelection(0, textPos)
|
||||
else
|
||||
child:setSelection(string.len(child:getText()), textPos)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
if consoleBuffer:getChildCount() > MAX_LINES then
|
||||
consoleBuffer:getFirstChild():destroy()
|
||||
local child = consoleBuffer:getFirstChild()
|
||||
clearSelection(consoleBuffer)
|
||||
child:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
@ -609,8 +717,28 @@ function processChannelTabMenu(tab, mousePos, mouseButton)
|
||||
|
||||
if consoleTabBar:getCurrentTab() == tab then
|
||||
menu:addOption(tr('Clear Messages'), function() clearChannel(consoleTabBar) end)
|
||||
menu:addOption(tr('Save Messages'), function()
|
||||
local panel = consoleTabBar:getTabPanel(tab)
|
||||
local consoleBuffer = panel:getChildById('consoleBuffer')
|
||||
local lines = {}
|
||||
for _,label in pairs(consoleBuffer:getChildren()) do
|
||||
table.insert(lines, label:getText())
|
||||
end
|
||||
|
||||
local filename = channelName .. '.txt'
|
||||
local filepath = '/' .. filename
|
||||
|
||||
-- extra information at the beginning
|
||||
table.insert(lines, 1, os.date('\nChannel saved at %a %b %d %H:%M:%S %Y'))
|
||||
|
||||
if g_resources.fileExists(filepath) then
|
||||
table.insert(lines, 1, protectedcall(g_resources.readFileContents, filepath) or '')
|
||||
end
|
||||
|
||||
g_resources.writeFileContents(filepath, table.concat(lines, '\n'))
|
||||
modules.game_textmessage.displayStatusMessage(tr('Channel appended to %s', filename))
|
||||
end)
|
||||
end
|
||||
--menu:addOption(tr('Save Messages'), function() --[[TODO]] end)
|
||||
|
||||
menu:display(mousePos)
|
||||
end
|
||||
@ -644,12 +772,15 @@ function processMessageMenu(mousePos, mouseButton, creatureName, text, label, ta
|
||||
|
||||
menu:addOption(tr('Copy name'), function () g_window.setClipboardText(creatureName) end)
|
||||
end
|
||||
if label:hasSelection() then
|
||||
menu:addOption(tr('Copy'), function() g_window.setClipboardText(label:getSelection()) end, '(Ctrl+C)')
|
||||
local selection = tab.tabPanel:getChildById('consoleBuffer').selectionText
|
||||
if selection and #selection > 0 then
|
||||
menu:addOption(tr('Copy'), function() g_window.setClipboardText(selection) end, '(Ctrl+C)')
|
||||
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
|
||||
if text then
|
||||
menu:addOption(tr('Copy message'), function() g_window.setClipboardText(text) end)
|
||||
end
|
||||
menu:addOption(tr('Select all'), function() selectAll(tab.tabPanel:getChildById('consoleBuffer')) end)
|
||||
if tab.violations and creatureName then
|
||||
menu:addSeparator()
|
||||
menu:addOption(tr('Process') .. ' ' .. creatureName, function() processViolation(creatureName, text) end)
|
||||
menu:addOption(tr('Remove') .. ' ' .. creatureName, function() g_game.closeRuleViolation(creatureName) end)
|
||||
|
@ -10,6 +10,9 @@ ConsoleLabel < UITextEdit
|
||||
change-cursor-image: false
|
||||
cursor-visible: false
|
||||
editable: false
|
||||
draggable: true
|
||||
selectable: false
|
||||
focusable: false
|
||||
|
||||
ConsolePhantomLabel < UILabel
|
||||
font: verdana-11px-antialised
|
||||
|
@ -200,29 +200,24 @@ void Creature::drawOutfit(const Rect& destRect, bool resize)
|
||||
else
|
||||
exactSize = g_things.rawGetThingType(m_outfit.getAuxId(), m_outfit.getCategory())->getExactSize();
|
||||
|
||||
int frameSize;
|
||||
if(!resize)
|
||||
frameSize = std::max<int>(exactSize * 0.75f, 2 * Otc::TILE_PIXELS * 0.75f);
|
||||
else if(!(frameSize = exactSize))
|
||||
return;
|
||||
|
||||
if(g_graphics.canUseFBO()) {
|
||||
const FrameBufferPtr& outfitBuffer = g_framebuffers.getTemporaryFrameBuffer();
|
||||
outfitBuffer->resize(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS));
|
||||
outfitBuffer->resize(Size(frameSize, frameSize));
|
||||
outfitBuffer->bind();
|
||||
g_painter->setAlphaWriting(true);
|
||||
g_painter->clear(Color::alpha);
|
||||
internalDrawOutfit(Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South);
|
||||
internalDrawOutfit(Point(frameSize - Otc::TILE_PIXELS, frameSize - Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South);
|
||||
outfitBuffer->release();
|
||||
|
||||
Rect srcRect;
|
||||
if(resize)
|
||||
srcRect.resize(exactSize, exactSize);
|
||||
else
|
||||
srcRect.resize(2*Otc::TILE_PIXELS*0.75f, 2*Otc::TILE_PIXELS*0.75f);
|
||||
srcRect.moveBottomRight(Point(2*Otc::TILE_PIXELS - 1, 2*Otc::TILE_PIXELS - 1));
|
||||
outfitBuffer->draw(destRect, srcRect);
|
||||
outfitBuffer->draw(destRect, Rect(0,0,frameSize,frameSize));
|
||||
} else {
|
||||
float scaleFactor;
|
||||
if(resize)
|
||||
scaleFactor = destRect.width() / (float)exactSize;
|
||||
else
|
||||
scaleFactor = destRect.width() / (float)(2*Otc::TILE_PIXELS*0.75f);
|
||||
Point dest = destRect.bottomRight() - (Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) - getDisplacement())*scaleFactor;
|
||||
float scaleFactor = destRect.width() / (float)frameSize;
|
||||
Point dest = destRect.bottomRight() - (Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) - getDisplacement()) * scaleFactor;
|
||||
internalDrawOutfit(dest, scaleFactor, false, true, Otc::South);
|
||||
}
|
||||
}
|
||||
|
@ -394,6 +394,14 @@ void Map::setZoneColor(tileflags_t zone, const Color& color)
|
||||
m_zoneColors[zone] = color;
|
||||
}
|
||||
|
||||
Color Map::getZoneColor(tileflags_t flag)
|
||||
{
|
||||
auto it = m_zoneColors.find(flag);
|
||||
if(it == m_zoneColors.end())
|
||||
return Color::alpha;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void Map::setForceShowAnimations(bool force)
|
||||
{
|
||||
if(force) {
|
||||
|
@ -196,7 +196,7 @@ public:
|
||||
void setZoneOpacity(float opacity) { m_zoneOpacity = opacity; }
|
||||
|
||||
float getZoneOpacity() { return m_zoneOpacity; }
|
||||
Color getZoneColor(tileflags_t flag) { return m_zoneColors[flag]; }
|
||||
Color getZoneColor(tileflags_t flag);
|
||||
tileflags_t getZoneFlags() { return (tileflags_t)m_zoneFlags; }
|
||||
bool showZones() { return m_zoneFlags != 0; }
|
||||
bool showZone(tileflags_t zone) { return (m_zoneFlags & zone) == zone; }
|
||||
@ -257,7 +257,7 @@ private:
|
||||
|
||||
uint8 m_animationFlags;
|
||||
uint32 m_zoneFlags;
|
||||
std::array<Color, TILESTATE_LAST> m_zoneColors;
|
||||
std::map<uint32, Color> m_zoneColors;
|
||||
float m_zoneOpacity;
|
||||
|
||||
Light m_light;
|
||||
@ -272,5 +272,3 @@ private:
|
||||
extern Map g_map;
|
||||
|
||||
#endif
|
||||
|
||||
/* vim: set ts=4 sw=4 et: */
|
||||
|
@ -333,6 +333,7 @@ bool Minimap::loadOtmm(const std::string& fileName)
|
||||
|
||||
uint blockSize = MMBLOCK_SIZE * MMBLOCK_SIZE * sizeof(MinimapTile);
|
||||
std::vector<uchar> compressBuffer(compressBound(blockSize));
|
||||
std::vector<uchar> decompressBuffer(blockSize);
|
||||
|
||||
while(true) {
|
||||
Position pos;
|
||||
@ -340,17 +341,19 @@ bool Minimap::loadOtmm(const std::string& fileName)
|
||||
pos.y = fin->getU16();
|
||||
pos.z = fin->getU8();
|
||||
|
||||
// end of file
|
||||
if(!pos.isValid())
|
||||
// end of file or file is corrupted
|
||||
if(!pos.isValid() || pos.z >= Otc::MAX_Z+1)
|
||||
break;
|
||||
|
||||
MinimapBlock& block = getBlock(pos);
|
||||
ulong len = fin->getU16();
|
||||
ulong destLen = blockSize;
|
||||
fin->read(compressBuffer.data(), len);
|
||||
int ret = uncompress((uchar*)&block.getTiles(), &destLen, compressBuffer.data(), len);
|
||||
assert(ret == Z_OK);
|
||||
assert(destLen == blockSize);
|
||||
int ret = uncompress(decompressBuffer.data(), &destLen, compressBuffer.data(), len);
|
||||
if(ret != Z_OK || destLen != blockSize)
|
||||
break;
|
||||
|
||||
memcpy((uchar*)&block.getTiles(), decompressBuffer.data(), blockSize);
|
||||
block.mustUpdate();
|
||||
block.justSaw();
|
||||
}
|
||||
|
@ -583,10 +583,8 @@ void ProtocolGame::sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseMod
|
||||
msg->addU8(fightMode);
|
||||
msg->addU8(chaseMode);
|
||||
msg->addU8(safeFight ? 0x01: 0x00);
|
||||
|
||||
if(g_game.getFeature(Otc::GamePVPMode))
|
||||
msg->addU8(pvpMode);
|
||||
|
||||
send(msg);
|
||||
}
|
||||
|
||||
@ -595,7 +593,8 @@ void ProtocolGame::sendAttack(uint creatureId, uint seq)
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientAttack);
|
||||
msg->addU32(creatureId);
|
||||
msg->addU32(seq);
|
||||
if(g_game.getFeature(Otc::GameAttackSeq))
|
||||
msg->addU32(seq);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
@ -604,7 +603,8 @@ void ProtocolGame::sendFollow(uint creatureId, uint seq)
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientFollow);
|
||||
msg->addU32(creatureId);
|
||||
msg->addU32(seq);
|
||||
if(g_game.getFeature(Otc::GameAttackSeq))
|
||||
msg->addU32(seq);
|
||||
send(msg);
|
||||
}
|
||||
|
||||
@ -652,10 +652,8 @@ void ProtocolGame::sendShareExperience(bool active)
|
||||
OutputMessagePtr msg(new OutputMessage);
|
||||
msg->addU8(Proto::ClientShareExperience);
|
||||
msg->addU8(active ? 0x01 : 0x00);
|
||||
|
||||
if(g_game.getClientVersion() < 910)
|
||||
msg->addU8(0);
|
||||
|
||||
send(msg);
|
||||
}
|
||||
|
||||
|
@ -244,12 +244,12 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
||||
m_attribs.set(attr, market);
|
||||
break;
|
||||
}
|
||||
case ThingAttrUsable:
|
||||
case ThingAttrElevation: {
|
||||
m_elevation = fin->getU16();
|
||||
m_attribs.set(attr, m_elevation);
|
||||
break;
|
||||
}
|
||||
case ThingAttrUsable:
|
||||
case ThingAttrGround:
|
||||
case ThingAttrWritable:
|
||||
case ThingAttrWritableOnce:
|
||||
|
@ -174,7 +174,7 @@ set(CMAKE_CXX_FLAGS_COMPILESPEED "-O0")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O1 -g -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
|
||||
set(CMAKE_CXX_FLAGS_PERFORMANCE "-Ofast -mmmx -msse -msse2")
|
||||
set(CMAKE_CXX_FLAGS_PERFORMANCE "-Ofast -march=native")
|
||||
|
||||
if(USE_LTO)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fwhole-program -flto")
|
||||
|
@ -135,6 +135,12 @@ void PainterOGL1::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
|
||||
#endif
|
||||
}
|
||||
|
||||
void PainterOGL1::drawFillCoords(CoordsBuffer& coordsBuffer)
|
||||
{
|
||||
setTexture(nullptr);
|
||||
drawCoords(coordsBuffer);
|
||||
}
|
||||
|
||||
void PainterOGL1::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)
|
||||
{
|
||||
if(texture->isEmpty())
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
void refreshState();
|
||||
|
||||
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
|
||||
void drawFillCoords(CoordsBuffer& coordsBuffer);
|
||||
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture);
|
||||
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||
void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||
|
@ -120,6 +120,13 @@ void PainterOGL2::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
|
||||
PainterShaderProgram::enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR);
|
||||
}
|
||||
|
||||
void PainterOGL2::drawFillCoords(CoordsBuffer& coordsBuffer)
|
||||
{
|
||||
setDrawProgram(m_shaderProgram ? m_shaderProgram : m_drawSolidColorProgram.get());
|
||||
setTexture(nullptr);
|
||||
drawCoords(coordsBuffer);
|
||||
}
|
||||
|
||||
void PainterOGL2::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)
|
||||
{
|
||||
if(texture && texture->isEmpty())
|
||||
|
@ -41,6 +41,7 @@ public:
|
||||
void unbind();
|
||||
|
||||
void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
|
||||
void drawFillCoords(CoordsBuffer& coordsBuffer);
|
||||
void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture);
|
||||
void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||
void drawUpsideDownTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src);
|
||||
|
@ -62,6 +62,7 @@ public:
|
||||
virtual void clear(const Color& color) = 0;
|
||||
|
||||
virtual void drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles) = 0;
|
||||
virtual void drawFillCoords(CoordsBuffer& coordsBuffer) = 0;
|
||||
virtual void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) = 0;
|
||||
virtual void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) = 0;
|
||||
void drawTexturedRect(const Rect& dest, const TexturePtr& texture) { drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); }
|
||||
|
@ -49,6 +49,9 @@ UITextEdit::UITextEdit()
|
||||
m_updatesEnabled = true;
|
||||
m_selectionColor = Color::white;
|
||||
m_selectionBackgroundColor = Color::black;
|
||||
m_glyphsTextCoordsBuffer.enableHardwareCaching();
|
||||
m_glyphsSelectCoordsBuffer.enableHardwareCaching();
|
||||
m_glyphsMustRecache = true;
|
||||
blinkCursor();
|
||||
}
|
||||
|
||||
@ -62,38 +65,36 @@ void UITextEdit::drawSelf(Fw::DrawPane drawPane)
|
||||
drawImage(m_rect);
|
||||
drawIcon(m_rect);
|
||||
|
||||
//TODO: text rendering could be much optimized by using vertex buffer or caching the render into a texture
|
||||
|
||||
int textLength = m_text.length();
|
||||
const TexturePtr& texture = m_font->getTexture();
|
||||
if(!texture)
|
||||
return;
|
||||
|
||||
if(hasSelection()) {
|
||||
if(m_color != Color::alpha) {
|
||||
g_painter->setColor(m_color);
|
||||
for(int i=0;i<m_selectionStart;++i)
|
||||
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
|
||||
}
|
||||
bool glyphsMustRecache = m_glyphsMustRecache;
|
||||
if(glyphsMustRecache)
|
||||
m_glyphsMustRecache = false;
|
||||
|
||||
for(int i=m_selectionStart;i<m_selectionEnd;++i) {
|
||||
g_painter->setColor(m_selectionBackgroundColor);
|
||||
g_painter->drawFilledRect(m_glyphsCoords[i]);
|
||||
g_painter->setColor(m_selectionColor);
|
||||
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
|
||||
if(m_color != Color::alpha) {
|
||||
if(glyphsMustRecache) {
|
||||
m_glyphsTextCoordsBuffer.clear();
|
||||
for(int i=0;i<textLength;++i)
|
||||
m_glyphsTextCoordsBuffer.addRect(m_glyphsCoords[i], m_glyphsTexCoords[i]);
|
||||
}
|
||||
|
||||
if(m_color != Color::alpha) {
|
||||
g_painter->setColor(m_color);
|
||||
for(int i=m_selectionEnd;i<textLength;++i)
|
||||
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
|
||||
}
|
||||
} else if(m_color != Color::alpha) {
|
||||
g_painter->setColor(m_color);
|
||||
for(int i=0;i<textLength;++i)
|
||||
g_painter->drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
|
||||
g_painter->drawTextureCoords(m_glyphsTextCoordsBuffer, texture);
|
||||
}
|
||||
|
||||
if(hasSelection()) {
|
||||
if(glyphsMustRecache) {
|
||||
m_glyphsSelectCoordsBuffer.clear();
|
||||
for(int i=m_selectionStart;i<m_selectionEnd;++i)
|
||||
m_glyphsSelectCoordsBuffer.addRect(m_glyphsCoords[i], m_glyphsTexCoords[i]);
|
||||
}
|
||||
g_painter->setColor(m_selectionBackgroundColor);
|
||||
g_painter->drawFillCoords(m_glyphsSelectCoordsBuffer);
|
||||
g_painter->setColor(m_selectionColor);
|
||||
g_painter->drawTextureCoords(m_glyphsSelectCoordsBuffer, texture);
|
||||
}
|
||||
|
||||
// render cursor
|
||||
if(isExplicitlyEnabled() && m_cursorVisible && m_cursorInRange && isActive() && m_cursorPos >= 0) {
|
||||
@ -136,6 +137,9 @@ void UITextEdit::update(bool focusCursor)
|
||||
if(m_rect.isEmpty())
|
||||
return;
|
||||
|
||||
// recache coords buffers
|
||||
recacheGlyphs();
|
||||
|
||||
// map glyphs positions
|
||||
Size textBoxSize;
|
||||
const std::vector<Point>& glyphsPositions = m_font->calculateGlyphsPositions(text, m_textAlign, &textBoxSize);
|
||||
@ -360,6 +364,7 @@ void UITextEdit::setSelection(int start, int end)
|
||||
|
||||
m_selectionStart = stdext::clamp<int>(start, 0, (int)m_text.length());
|
||||
m_selectionEnd = stdext::clamp<int>(end, 0, (int)m_text.length());
|
||||
recacheGlyphs();
|
||||
}
|
||||
|
||||
void UITextEdit::setTextHidden(bool hidden)
|
||||
@ -654,7 +659,7 @@ void UITextEdit::onFocusChange(bool focused, Fw::FocusReason reason)
|
||||
else
|
||||
blinkCursor();
|
||||
update(true);
|
||||
} else
|
||||
} else if(m_selectable)
|
||||
clearSelection();
|
||||
UIWidget::onFocusChange(focused, reason);
|
||||
}
|
||||
@ -796,7 +801,6 @@ bool UITextEdit::onMousePress(const Point& mousePos, Fw::MouseButton button)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -807,6 +811,9 @@ bool UITextEdit::onMouseRelease(const Point& mousePos, Fw::MouseButton button)
|
||||
|
||||
bool UITextEdit::onMouseMove(const Point& mousePos, const Point& mouseMoved)
|
||||
{
|
||||
if(UIWidget::onMouseMove(mousePos, mouseMoved))
|
||||
return true;
|
||||
|
||||
if(m_selectable && isPressed()) {
|
||||
int pos = getTextPos(mousePos);
|
||||
if(pos >= 0) {
|
||||
@ -815,7 +822,7 @@ bool UITextEdit::onMouseMove(const Point& mousePos, const Point& mouseMoved)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return UIWidget::onMouseMove(mousePos, mouseMoved);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UITextEdit::onDoubleClick(const Point& mousePos)
|
||||
|
@ -108,6 +108,7 @@ protected:
|
||||
private:
|
||||
void disableUpdates() { m_updatesEnabled = false; }
|
||||
void enableUpdates() { m_updatesEnabled = true; }
|
||||
void recacheGlyphs() { m_glyphsMustRecache = true; }
|
||||
|
||||
Rect m_drawArea;
|
||||
int m_cursorPos;
|
||||
@ -137,6 +138,10 @@ private:
|
||||
|
||||
std::vector<Rect> m_glyphsCoords;
|
||||
std::vector<Rect> m_glyphsTexCoords;
|
||||
|
||||
CoordsBuffer m_glyphsTextCoordsBuffer;
|
||||
CoordsBuffer m_glyphsSelectCoordsBuffer;
|
||||
bool m_glyphsMustRecache;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -66,19 +66,19 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;$(IncludePath)</IncludePath>
|
||||
<IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;..\src;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>D:\otclient-msvc13-libs\libogg-1.3.1\lib;D:\otclient-msvc13-libs\libvorbis-1.3.3\lib;D:\otclient-msvc13-libs\physfs-2.0.3\lib;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;D:\otclient-msvc13-libs\zlib-1.2.5\lib;D:\otclient-msvc13-libs\OpenAL\lib;D:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;D:\otclient-msvc13-libs\glew-1.10.0\lib;D:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;$(IncludePath)</IncludePath>
|
||||
<IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;..\src;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>D:\otclient-msvc13-libs\libogg-1.3.1\lib;D:\otclient-msvc13-libs\libvorbis-1.3.3\lib;D:\otclient-msvc13-libs\physfs-2.0.3\lib;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;D:\otclient-msvc13-libs\zlib-1.2.5\lib;D:\otclient-msvc13-libs\OpenAL\lib;D:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;D:\otclient-msvc13-libs\glew-1.10.0\lib;D:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>C:\otclient-msvc13-libs\libogg-1.3.1\include;C:\otclient-msvc13-libs\libvorbis-1.3.3\include;C:\otclient-msvc13-libs\physfs-2.0.3\include;C:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;C:\otclient-msvc13-libs\zlib-1.2.5\include;C:\Users\Pedro\Documents\GitHub\otclient\src;C:\otclient-msvc13-libs\OpenAL\include\AL;C:\otclient-msvc13-libs\glew-1.10.0\include;C:\otclient-msvc13-libs\LuaJIT-2.0.2\include;C:\otclient-msvc13-libs\boost_1_55_0\include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>C:\otclient-msvc13-libs\libogg-1.3.1\include;C:\otclient-msvc13-libs\libvorbis-1.3.3\include;C:\otclient-msvc13-libs\physfs-2.0.3\include;C:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;C:\otclient-msvc13-libs\zlib-1.2.5\include;C:\otclient-msvc13-libs\OpenAL\include\AL;C:\otclient-msvc13-libs\glew-1.10.0\include;C:\otclient-msvc13-libs\LuaJIT-2.0.2\include;C:\otclient-msvc13-libs\boost_1_55_0\include;..\src;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\otclient-msvc13-libs\libogg-1.3.1\lib;C:\otclient-msvc13-libs\libvorbis-1.3.3\lib;C:\otclient-msvc13-libs\physfs-2.0.3\lib;C:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;C:\otclient-msvc13-libs\zlib-1.2.5\lib;C:\otclient-msvc13-libs\OpenAL\lib;C:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;C:\otclient-msvc13-libs\glew-1.10.0\lib;C:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;$(IncludePath)</IncludePath>
|
||||
<IncludePath>D:\otclient-msvc13-libs\libogg-1.3.1\include;D:\otclient-msvc13-libs\libvorbis-1.3.3\include;D:\otclient-msvc13-libs\physfs-2.0.3\include;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\include;D:\otclient-msvc13-libs\zlib-1.2.5\include;D:\otclient-msvc13-libs\OpenAL\include\AL;D:\otclient-msvc13-libs\glew-1.10.0\include;D:\otclient-msvc13-libs\LuaJIT-2.0.2\include;D:\otclient-msvc13-libs\boost_1_55_0\include;D:\otclient\src;..\src;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>D:\otclient-msvc13-libs\libogg-1.3.1\lib;D:\otclient-msvc13-libs\libvorbis-1.3.3\lib;D:\otclient-msvc13-libs\physfs-2.0.3\lib;D:\otclient-msvc13-libs\OpenSSL-1.0.1e\lib\VC;D:\otclient-msvc13-libs\zlib-1.2.5\lib;D:\otclient-msvc13-libs\OpenAL\lib;D:\otclient-msvc13-libs\LuaJIT-2.0.2\lib;D:\otclient-msvc13-libs\glew-1.10.0\lib;D:\otclient-msvc13-libs\boost_1_55_0\lib;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
@ -491,4 +491,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
Loading…
x
Reference in New Issue
Block a user