28 Commits

Author SHA1 Message Date
divinity76
dab86e6109 Make OutputMessage::addRawString available in Lua (#1218) 2024-09-14 17:26:54 +02:00
vfjpl
e6861d79c9 Use float literals where applicable (#1210) 2023-08-14 04:47:12 +02:00
diath
52475761cd Save the minimap on a per server basis
Co-authored-by: Xagul <eixim@hotmail.com>
2022-12-10 10:52:03 +01:00
diath
a3fdf073b9 Use lambdas instead of std::bind (#1200) 2022-11-26 19:15:38 +01:00
Marcin Michalski
77f05b9476 Run CI on ubuntu 20.04 (#1199) 2022-11-26 01:50:42 +01:00
Marcin Michalski
0e5de3383e Prevent luaL_newlib macro redefinition (#1198) 2022-11-26 01:28:21 +01:00
Marcin Michalski
4a39d49fc1 Update workflow actions (#1197)
* Update workflow actions

* Update actions/checkout to v3
2022-11-26 01:06:57 +01:00
Marcin Michalski
725c200c9f Update vcpkg (#1196) 2022-11-26 00:12:00 +01:00
diath
da4bb92c33 Fix UIWidget::propagateOnMouseMove repeatedly adding the mouse receiver to the list (#1195) 2022-11-25 18:03:51 +01:00
diath
77c844d006 Fix building with newest Boost.Asio (#1194) 2022-11-25 18:00:45 +01:00
Marcin Michalski
fc39ee4adb Correctly include vcpkg LuaJIT in Visual Studio (#1174) 2022-05-26 13:45:13 +02:00
Kacper
b098210c6a move big functions from .h to .cpp 2022-05-26 13:40:01 +02:00
Marcin Michalski
f0d7963883 Fix compilation with GMP 2022-04-28 14:09:08 +02:00
Marcin Michalski
836ea2bdc6 Update vcpkg 2022-04-28 14:09:08 +02:00
Marcin Michalski
45afb65b90 Remove client stats module (#1170) 2022-01-26 20:13:18 +01:00
diath
d3e12b5d44 Make UIWidget::resizeToText() respect widget padding and text offset like text-auto-resize does (#1167) 2021-11-24 20:10:13 +01:00
Marcin Michalski
3092b5b2d5 Update physfs repo in Dockerfile (#1165) 2021-11-15 23:13:41 +01:00
diath
e73f6df221 Fix process hang on fatal errors (#1163) 2021-09-29 21:03:12 +02:00
diath
9eb13494f9 Fix ghost item border when dropping non-item objects (#1164) 2021-09-29 21:03:01 +02:00
vfjpl
1d614e294c Fix std::istream::streampos deprecation warning (#1154) 2021-08-25 19:24:08 +02:00
Marcin Michalski
e0d5b7d7fd Update vcpkg & switch back to ubuntu 18.04 in workflow (#1161) 2021-08-22 01:21:17 +02:00
Marcin Michalski
10100342b9 Fix opening "https://"-prefixed links on Windows (#1160) 2021-08-22 00:51:18 +02:00
Marcin Michalski
302748b2f3 Fix opening URLs on macOS (#1159) 2021-08-22 00:48:34 +02:00
Marcin Michalski
f173b03dbd Map option to alt and command to meta keys on macOS (#1158) 2021-08-22 00:38:58 +02:00
vfjpl
89dc0f87eb Fix stamina minutes check in the skills window (#1155) 2021-07-22 00:02:27 +02:00
vfjpl
9ce2cab9ae Fix uninitialized oldMaxMana variable in Player::setMana (#1152) 2021-06-16 23:25:43 +02:00
TheSumm
1e29b5cb01 Remove unused source file 2021-06-12 19:40:21 +02:00
Samuel
8eb01df240 Fix vcpkg compiling (#1153) 2021-06-12 18:07:18 +02:00
39 changed files with 286 additions and 411 deletions

View File

@@ -10,12 +10,14 @@ on:
- v* - v*
paths: paths:
- .github/workflows/**
- cmake/** - cmake/**
- src/** - src/**
- CMakeLists.txt - CMakeLists.txt
pull_request: pull_request:
paths: paths:
- .github/workflows/**
- cmake/** - cmake/**
- src/** - src/**
- CMakeLists.txt - CMakeLists.txt
@@ -23,7 +25,7 @@ on:
jobs: jobs:
job: job:
name: ${{ matrix.os }}-${{ matrix.cxx }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }} name: ${{ matrix.os }}-${{ matrix.cxx }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}
runs-on: ${{ matrix.os }}-latest runs-on: ${{ matrix.os }}-${{ matrix.os-version }}
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 8 max-parallel: 8
@@ -34,6 +36,7 @@ jobs:
include: include:
- name: windows-msvc - name: windows-msvc
os: windows os: windows
os-version: latest
cxx: cl.exe cxx: cl.exe
cc: cl.exe cc: cl.exe
triplet: x64-windows triplet: x64-windows
@@ -42,6 +45,7 @@ jobs:
glew luajit libogg libvorbis openal-soft opengl openssl physfs zlib glew luajit libogg libvorbis openal-soft opengl openssl physfs zlib
- name: ubuntu-gcc - name: ubuntu-gcc
os: ubuntu os: ubuntu
os-version: 20.04
cxx: g++ cxx: g++
cc: gcc cc: gcc
triplet: x64-linux triplet: x64-linux
@@ -50,6 +54,7 @@ jobs:
boost-filesystem boost-uuid physfs openal-soft libogg libvorbis zlib opengl boost-filesystem boost-uuid physfs openal-soft libogg libvorbis zlib opengl
- name: macos-clang - name: macos-clang
os: macos os: macos
os-version: latest
cxx: clang++ cxx: clang++
cc: clang cc: clang
triplet: x64-osx triplet: x64-osx
@@ -61,7 +66,7 @@ jobs:
luajit: off luajit: off
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
submodules: true submodules: true
@@ -87,12 +92,12 @@ jobs:
echo "CC=${{ matrix.cc }}" >> $GITHUB_ENV echo "CC=${{ matrix.cc }}" >> $GITHUB_ENV
- name: Run vcpkg - name: Run vcpkg
uses: lukka/run-vcpkg@v7.1 uses: lukka/run-vcpkg@v7
with: with:
vcpkgArguments: ${{ matrix.packages }} vcpkgArguments: ${{ matrix.packages }}
vcpkgDirectory: ${{ runner.workspace }}/vcpkg/ vcpkgDirectory: ${{ runner.workspace }}/vcpkg/
vcpkgTriplet: ${{ matrix.triplet }} vcpkgTriplet: ${{ matrix.triplet }}
vcpkgGitCommitId: 9a49e3df7f729655318c59b9985c9c18ad0c99d6 vcpkgGitCommitId: 6f7ffeb18f99796233b958aaaf14ec7bd4fb64b2
- name: Build with CMake - name: Build with CMake
uses: lukka/run-cmake@v3 uses: lukka/run-cmake@v3
@@ -107,21 +112,21 @@ jobs:
shell: bash shell: bash
- name: Upload artifact binary - name: Upload artifact binary
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: otclient-${{ matrix.name }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}-${{ github.sha }} name: otclient-${{ matrix.name }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}-${{ github.sha }}
path: ${{ runner.workspace }}/build/otclient path: ${{ runner.workspace }}/build/otclient
if: "! contains( matrix.os, 'windows')" if: "! contains( matrix.os, 'windows')"
- name: Upload artifact binary (exe) - name: Upload artifact binary (exe)
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: otclient-${{ matrix.name }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}-${{ github.sha }} name: otclient-${{ matrix.name }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}-${{ github.sha }}
path: ${{ runner.workspace }}/build/otclient.exe path: ${{ runner.workspace }}/build/otclient.exe
if: contains( matrix.os, 'windows') if: contains( matrix.os, 'windows')
- name: Upload artifact binary (dlls) - name: Upload artifact binary (dlls)
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: otclient-${{ matrix.name }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}-${{ github.sha }} name: otclient-${{ matrix.name }}-${{ matrix.buildtype }}-luajit=${{ matrix.luajit }}-${{ github.sha }}
path: ${{ runner.workspace }}/build/*.dll path: ${{ runner.workspace }}/build/*.dll

View File

@@ -17,12 +17,11 @@ RUN apt-get update; \
libopenal-dev \ libopenal-dev \
libssl-dev \ libssl-dev \
libvorbis-dev \ libvorbis-dev \
mercurial \
zlib1g-dev; \ zlib1g-dev; \
apt-get clean && apt-get autoclean apt-get clean && apt-get autoclean
WORKDIR / WORKDIR /
RUN hg clone -r stable-3.0 http://hg.icculus.org/icculus/physfs/ RUN git clone --branch release-3.0.2 --depth 1 https://github.com/icculus/physfs.git
WORKDIR /physfs/build/ WORKDIR /physfs/build/
RUN cmake .. RUN cmake ..
RUN make -j$(nproc) RUN make -j$(nproc)

View File

@@ -19,4 +19,3 @@ Module
- client_terminal - client_terminal
- client_modulemanager - client_modulemanager
- client_serverlist - client_serverlist
- client_stats

View File

@@ -1,131 +0,0 @@
UUID = nil
HOST = 'otclient.herokuapp.com'
PORT = 80
FIRST_REPORT_DELAY = 15
REPORT_DELAY = 60
sendReportEvent = nil
firstReportEvent = nil
function initUUID()
UUID = g_settings.getString('report-uuid')
if not UUID or #UUID ~= 36 then
UUID = g_crypt.genUUID()
g_settings.set('report-uuid', UUID)
end
end
function init()
connect(g_game, { onGameStart = onGameStart,
onGameEnd = onGameEnd })
initUUID()
end
function terminate()
disconnect(g_game, { onGameStart = onGameStart,
onGameEnd = onGameEnd })
removeEvent(firstReportEvent)
removeEvent(sendReportEvent)
end
function configure(host, port, delay)
if not host then return end
HOST = host
PORT = port or PORT
REPORT_DELAY = delay or REPORT_DELAY
end
function sendReport()
if not HOST then return end
local protocolHttp = ProtocolHttp.create()
protocolHttp.onConnect = onConnect
protocolHttp.onRecv = onRecv
protocolHttp.onError = onError
protocolHttp:connect(HOST, PORT)
end
function onGameStart()
if not HOST then return end
removeEvent(firstReportEvent)
removeEvent(sendReportEvent)
firstReportEvent = addEvent(sendReport, FIRST_REPORT_DELAY*1000)
sendReportEvent = cycleEvent(sendReport, REPORT_DELAY*1000)
end
function onGameEnd()
removeEvent(firstReportEvent)
removeEvent(sendReportEvent)
end
function onConnect(protocol)
if not g_game.isOnline() then
protocol:disconnect()
return
end
local post = ''
post = post .. 'uid=' .. urlencode(UUID)
post = post .. '&report_delay=' .. REPORT_DELAY
post = post .. '&os=' .. urlencode(g_app.getOs())
post = post .. '&graphics_vendor=' .. urlencode(g_graphics.getVendor())
post = post .. '&graphics_renderer=' .. urlencode(g_graphics.getRenderer())
post = post .. '&graphics_version=' .. urlencode(g_graphics.getVersion())
post = post .. '&painter_engine=' .. urlencode(g_graphics.getPainterEngine())
post = post .. '&fps=' .. urlencode(g_app.getBackgroundPaneFps())
post = post .. '&max_fps=' .. urlencode(g_app.getBackgroundPaneMaxFps())
post = post .. '&fullscreen=' .. urlencode(tostring(g_window.isFullscreen()))
post = post .. '&window_width=' .. urlencode(g_window.getWidth())
post = post .. '&window_height=' .. urlencode(g_window.getHeight())
post = post .. '&player_name=' .. urlencode(g_game.getCharacterName())
post = post .. '&world_name=' .. urlencode(g_game.getWorldName())
post = post .. '&otserv_host=' .. urlencode(G.host)
post = post .. '&otserv_port=' .. G.port
post = post .. '&otserv_protocol=' .. urlencode(g_game.getProtocolVersion())
post = post .. '&otserv_client=' .. urlencode(g_game.getClientVersion())
post = post .. '&build_version=' .. urlencode(g_app.getVersion())
post = post .. '&build_revision=' .. urlencode(g_app.getBuildRevision())
post = post .. '&build_commit=' .. urlencode(g_app.getBuildCommit())
post = post .. '&build_date=' .. urlencode(g_app.getBuildDate())
post = post .. '&display_width=' .. g_window.getDisplayWidth()
post = post .. '&display_height=' .. g_window.getDisplayHeight()
post = post .. '&cpu=' .. urlencode(g_platform.getCPUName())
post = post .. '&mem=' .. g_platform.getTotalSystemMemory()
post = post .. '&os_name=' .. urlencode(g_platform.getOSName())
post = post .. getAdditionalData()
local message = ''
message = message .. "POST /report HTTP/1.1\r\n"
message = message .. "Host: " .. HOST .. "\r\n"
message = message .. "Accept: */*\r\n"
message = message .. "Connection: close\r\n"
message = message .. "Content-Type: application/x-www-form-urlencoded\r\n"
message = message .. "Content-Length: " .. post:len() .. "\r\n\r\n"
message = message .. post
protocol:send(message)
protocol:recv()
end
function getAdditionalData()
return ''
end
function onRecv(protocol, message)
if string.find(message, 'HTTP/1.1 200 OK') then
--pinfo('Stats sent to server successfully!')
end
protocol:disconnect()
end
function onError(protocol, message, code)
pdebug('Could not send statistics: ' .. message)
end
function urlencode(str)
local encodeChar=function(chr)
return string.format("%%%X",string.byte(chr))
end
local output, t = string.gsub(str,"[^%w]",encodeChar)
return output
end

View File

@@ -1,9 +0,0 @@
Module
name: client_stats
description: Sends client statistics to a server
author: baxnie
website: https://github.com/edubart/otclient
sandboxed: true
scripts: [ stats ]
@onLoad: init()
@onUnload: terminate()

View File

@@ -20,6 +20,7 @@ function UIItem:onDragLeave(droppedWidget, mousePos)
end end
function UIItem:onDrop(widget, mousePos) function UIItem:onDrop(widget, mousePos)
self:setBorderWidth(0)
if not self:canAcceptDrop(widget, mousePos) then if not self:canAcceptDrop(widget, mousePos) then
return false return false
@@ -47,7 +48,6 @@ function UIItem:onDrop(widget, mousePos)
g_game.move(item, toPos, 1) g_game.move(item, toPos, 1)
end end
self:setBorderWidth(0)
return true return true
end end

View File

@@ -103,12 +103,12 @@ function loadMap(clean)
end end
if otmm then if otmm then
local minimapFile = '/minimap.otmm' local minimapFile = '/minimap_'.. G.host ..'.otmm'
if g_resources.fileExists(minimapFile) then if g_resources.fileExists(minimapFile) then
g_minimap.loadOtmm(minimapFile) g_minimap.loadOtmm(minimapFile)
end end
else else
local minimapFile = '/minimap_' .. clientVersion .. '.otcm' local minimapFile = '/minimap_' .. clientVersion .. '_'.. G.host ..'.otcm'
if g_resources.fileExists(minimapFile) then if g_resources.fileExists(minimapFile) then
g_map.loadOtcm(minimapFile) g_map.loadOtcm(minimapFile)
end end
@@ -119,10 +119,10 @@ end
function saveMap() function saveMap()
local clientVersion = g_game.getClientVersion() local clientVersion = g_game.getClientVersion()
if otmm then if otmm then
local minimapFile = '/minimap.otmm' local minimapFile = '/minimap_'.. G.host ..'.otmm'
g_minimap.saveOtmm(minimapFile) g_minimap.saveOtmm(minimapFile)
else else
local minimapFile = '/minimap_' .. clientVersion .. '.otcm' local minimapFile = '/minimap_' .. clientVersion .. '_'.. G.host ..'.otcm'
g_map.saveOtcm(minimapFile) g_map.saveOtcm(minimapFile)
end end
minimapWidget:save() minimapWidget:save()

View File

@@ -1,5 +1,5 @@
skillsWindow = nil local skillsWindow = nil
skillsButton = nil local skillsButton = nil
function init() function init()
connect(LocalPlayer, { connect(LocalPlayer, {
@@ -350,11 +350,11 @@ function onStaminaChange(localPlayer, stamina)
local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' .. local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' ..
tr("You will not gain 50%% more experience because you aren't premium player, now you receive only 1x experience points") tr("You will not gain 50%% more experience because you aren't premium player, now you receive only 1x experience points")
setSkillPercent('stamina', percent, text, '#89F013') setSkillPercent('stamina', percent, text, '#89F013')
elseif stamina > 2400 and g_game.getClientVersion() < 1038 then elseif stamina >= 2400 and g_game.getClientVersion() < 1038 then
local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' .. local text = tr("You have %s hours and %s minutes left", hours, minutes) .. '\n' ..
tr("If you are premium player, you will gain 50%% more experience") tr("If you are premium player, you will gain 50%% more experience")
setSkillPercent('stamina', percent, text, 'green') setSkillPercent('stamina', percent, text, 'green')
elseif stamina <= 2400 and stamina > 840 then elseif stamina < 2400 and stamina > 840 then
setSkillPercent('stamina', percent, tr("You have %s hours and %s minutes left", hours, minutes), 'orange') setSkillPercent('stamina', percent, tr("You have %s hours and %s minutes left", hours, minutes), 'orange')
elseif stamina <= 840 and stamina > 0 then elseif stamina <= 840 and stamina > 0 then
local text = tr("You have %s hours and %s minutes left", hours, minutes) .. "\n" .. local text = tr("You have %s hours and %s minutes left", hours, minutes) .. "\n" ..

View File

@@ -53,7 +53,7 @@ void AnimatedText::drawText(const Point& dest, const Rect& visibleRect)
if(visibleRect.contains(rect)) { if(visibleRect.contains(rect)) {
//TODO: cache into a framebuffer //TODO: cache into a framebuffer
float t0 = tf / 1.2; float t0 = tf / 1.2f;
if(t > t0) { if(t > t0) {
Color color = m_color; Color color = m_color;
color.setAlpha((float)(1 - (t - t0) / (tf - t0))); color.setAlpha((float)(1 - (t - t0) / (tf - t0)));
@@ -92,7 +92,7 @@ bool AnimatedText::merge(const AnimatedTextPtr& other)
if(other->getCachedText().getFont() != m_cachedText.getFont()) if(other->getCachedText().getFont() != m_cachedText.getFont())
return false; return false;
if(m_animationTimer.ticksElapsed() > Otc::ANIMATED_TEXT_DURATION / 2.5) if(m_animationTimer.ticksElapsed() > Otc::ANIMATED_TEXT_DURATION / 2.5f)
return false; return false;
try { try {

View File

@@ -59,7 +59,7 @@ LocalPlayer::LocalPlayer()
void LocalPlayer::lockWalk(int millis) void LocalPlayer::lockWalk(int millis)
{ {
m_walkLockExpiration = std::max<int>(m_walkLockExpiration, (ticks_t) g_clock.millis() + millis); m_walkLockExpiration = std::max<ticks_t>(m_walkLockExpiration, g_clock.millis() + millis);
} }
bool LocalPlayer::canWalk(Otc::Direction) bool LocalPlayer::canWalk(Otc::Direction)
@@ -102,8 +102,9 @@ void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
if(newPos == m_lastPrewalkDestination) { if(newPos == m_lastPrewalkDestination) {
updateWalk(); updateWalk();
// was to another direction, replace the walk // was to another direction, replace the walk
} else } else {
Creature::walk(oldPos, newPos); Creature::walk(oldPos, newPos);
}
} }
// no prewalk was going on, this must be an server side automated walk // no prewalk was going on, this must be an server side automated walk
else { else {
@@ -259,8 +260,9 @@ void LocalPlayer::updateWalkOffset(int totalPixelsWalked)
m_walkOffset.x = totalPixelsWalked; m_walkOffset.x = totalPixelsWalked;
else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest) else if(m_direction == Otc::West || m_direction == Otc::NorthWest || m_direction == Otc::SouthWest)
m_walkOffset.x = -totalPixelsWalked; m_walkOffset.x = -totalPixelsWalked;
} else } else {
Creature::updateWalkOffset(totalPixelsWalked); Creature::updateWalkOffset(totalPixelsWalked);
}
} }
void LocalPlayer::updateWalk() void LocalPlayer::updateWalk()
@@ -425,7 +427,7 @@ void LocalPlayer::setMana(double mana, double maxMana)
{ {
if(m_mana != mana || m_maxMana != maxMana) { if(m_mana != mana || m_maxMana != maxMana) {
double oldMana = m_mana; double oldMana = m_mana;
double oldMaxMana; double oldMaxMana = m_maxMana;
m_mana = mana; m_mana = mana;
m_maxMana = maxMana; m_maxMana = maxMana;

View File

@@ -85,7 +85,7 @@ public:
double getStamina() { return m_stamina; } double getStamina() { return m_stamina; }
double getRegenerationTime() { return m_regenerationTime; } double getRegenerationTime() { return m_regenerationTime; }
double getOfflineTrainingTime() { return m_offlineTrainingTime; } double getOfflineTrainingTime() { return m_offlineTrainingTime; }
std::vector<int> getSpells() { return m_spells; } const std::vector<int>& getSpells() { return m_spells; }
ItemPtr getInventoryItem(Otc::InventorySlot inventory) { return m_inventoryItems[inventory]; } ItemPtr getInventoryItem(Otc::InventorySlot inventory) { return m_inventoryItems[inventory]; }
int getBlessings() { return m_blessings; } int getBlessings() { return m_blessings; }

View File

@@ -134,7 +134,7 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos)
if(prevAnimatedText) { if(prevAnimatedText) {
Point offset = prevAnimatedText->getOffset(); Point offset = prevAnimatedText->getOffset();
float t = prevAnimatedText->getTimer().ticksElapsed(); float t = prevAnimatedText->getTimer().ticksElapsed();
if(t < Otc::ANIMATED_TEXT_DURATION / 4.0) { // didnt move 12 pixels if(t < Otc::ANIMATED_TEXT_DURATION / 4.f) { // didnt move 12 pixels
int y = 12 - 48 * t / (float)Otc::ANIMATED_TEXT_DURATION; int y = 12 - 48 * t / (float)Otc::ANIMATED_TEXT_DURATION;
offset += Point(0, y); offset += Point(0, y);
} }

View File

@@ -37,38 +37,38 @@ Color Outfit::getColor(int color)
float loc1 = 0, loc2 = 0, loc3 = 0; float loc1 = 0, loc2 = 0, loc3 = 0;
if(color % HSI_H_STEPS != 0) { if(color % HSI_H_STEPS != 0) {
loc1 = color % HSI_H_STEPS * 1.0/18.0; loc1 = color % HSI_H_STEPS * 1.f/18.f;
loc2 = 1; loc2 = 1;
loc3 = 1; loc3 = 1;
switch(int(color / HSI_H_STEPS)) { switch(int(color / HSI_H_STEPS)) {
case 0: case 0:
loc2 = 0.25; loc2 = 0.25f;
loc3 = 1.00; loc3 = 1.f;
break; break;
case 1: case 1:
loc2 = 0.25; loc2 = 0.25f;
loc3 = 0.75; loc3 = 0.75f;
break; break;
case 2: case 2:
loc2 = 0.50; loc2 = 0.5f;
loc3 = 0.75; loc3 = 0.75f;
break; break;
case 3: case 3:
loc2 = 0.667; loc2 = 0.667f;
loc3 = 0.75; loc3 = 0.75f;
break; break;
case 4: case 4:
loc2 = 1.00; loc2 = 1.f;
loc3 = 1.00; loc3 = 1.f;
break; break;
case 5: case 5:
loc2 = 1.00; loc2 = 1.f;
loc3 = 0.75; loc3 = 0.75f;
break; break;
case 6: case 6:
loc2 = 1.00; loc2 = 1.f;
loc3 = 0.50; loc3 = 0.5f;
break; break;
} }
} }
@@ -88,27 +88,27 @@ Color Outfit::getColor(int color)
float red = 0, green = 0, blue = 0; float red = 0, green = 0, blue = 0;
if(loc1 < 1.0/6.0) { if(loc1 < 1.f/6.f) {
red = loc3; red = loc3;
blue = loc3 * (1 - loc2); blue = loc3 * (1 - loc2);
green = blue + (loc3 - blue) * 6 * loc1; green = blue + (loc3 - blue) * 6 * loc1;
} }
else if(loc1 < 2.0/6.0) { else if(loc1 < 2.f/6.f) {
green = loc3; green = loc3;
blue = loc3 * (1 - loc2); blue = loc3 * (1 - loc2);
red = green - (loc3 - blue) * (6 * loc1 - 1); red = green - (loc3 - blue) * (6 * loc1 - 1);
} }
else if(loc1 < 3.0/6.0) { else if(loc1 < 3.f/6.f) {
green = loc3; green = loc3;
red = loc3 * (1 - loc2); red = loc3 * (1 - loc2);
blue = red + (loc3 - red) * (6 * loc1 - 2); blue = red + (loc3 - red) * (6 * loc1 - 2);
} }
else if(loc1 < 4.0/6.0) { else if(loc1 < 4.f/6.f) {
blue = loc3; blue = loc3;
red = loc3 * (1 - loc2); red = loc3 * (1 - loc2);
green = blue - (loc3 - red) * (6 * loc1 - 3); green = blue - (loc3 - red) * (6 * loc1 - 3);
} }
else if(loc1 < 5.0/6.0) { else if(loc1 < 5.f/6.f) {
blue = loc3; blue = loc3;
green = loc3 * (1 - loc2); green = loc3 * (1 - loc2);
red = green + (loc3 - green) * (6 * loc1 - 4); red = green + (loc3 - green) * (6 * loc1 - 4);

View File

@@ -131,7 +131,7 @@ public:
return positions; return positions;
} }
static double getAngleFromPositions(const Position& fromPos, const Position& toPos) { static float getAngleFromPositions(const Position& fromPos, const Position& toPos) {
// Returns angle in radians from 0 to 2Pi. -1 means positions are equal. // Returns angle in radians from 0 to 2Pi. -1 means positions are equal.
int dx = toPos.x - fromPos.x; int dx = toPos.x - fromPos.x;
int dy = toPos.y - fromPos.y; int dy = toPos.y - fromPos.y;
@@ -145,7 +145,7 @@ public:
return angle; return angle;
} }
double getAngleFromPosition(const Position& position) const { float getAngleFromPosition(const Position& position) const {
return getAngleFromPositions(*this, position); return getAngleFromPositions(*this, position);
} }

View File

@@ -1,67 +0,0 @@
/*
* Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef DATMANAGER_H
#define DATMANAGER_H
#include <framework/global.h>
#include <framework/core/declarations.h>
#include "thingtype.h"
//@bindsingleton g_thingsType
class ThingsType
{
public:
enum Categories {
Item = 0,
Creature,
Effect,
Missile,
LastCategory
};
bool load(const std::string& file);
void unload();
bool parseThingType(const FileStreamPtr& fin, ThingType& thingType);
ThingType *getEmptyThingType() { return &m_emptyThingType; }
ThingType *getThingType(uint16 id, Categories category);
uint32 getSignature() { return m_signature; }
bool isLoaded() { return m_loaded; }
uint16 getFirstItemId() { return 100; }
uint16 getMaxItemid() { return m_things[Item].size() + 99; }
bool isValidItemId(int id) { return id >= getFirstItemId() && id <= getMaxItemid(); }
private:
uint32 m_signature;
stdext::boolean<false> m_loaded;
ThingTypeList m_things[LastCategory];
static ThingType m_emptyThingType;
};
extern ThingsType g_thingsType;
#endif

View File

@@ -550,7 +550,7 @@ bool Tile::isClickable()
bool Tile::isEmpty() bool Tile::isEmpty()
{ {
return m_things.size() == 0; return m_things.empty();
} }
bool Tile::isDrawable() bool Tile::isDrawable()

View File

@@ -43,36 +43,36 @@ void UIProgressRect::drawSelf(Fw::DrawPane drawPane)
// 0% - 12.5% (12.5) // 0% - 12.5% (12.5)
// triangle from top center, to top right (var x) // triangle from top center, to top right (var x)
if(m_percent < 12.5) { if(m_percent < 12.5f) {
Point var = Point(std::max<int>(m_percent - 0.0, 0.0) * (drawRect.right() - drawRect.horizontalCenter()) / 12.5, 0); Point var = Point(std::max<int>(m_percent - 0.f, 0.f) * (drawRect.right() - drawRect.horizontalCenter()) / 12.5f, 0);
g_painter->drawFilledTriangle(drawRect.center(), drawRect.topRight() + Point(1,0), drawRect.topCenter() + var); g_painter->drawFilledTriangle(drawRect.center(), drawRect.topRight() + Point(1,0), drawRect.topCenter() + var);
} }
// 12.5% - 37.5% (25) // 12.5% - 37.5% (25)
// triangle from top right to bottom right (var y) // triangle from top right to bottom right (var y)
if(m_percent < 37.5) { if(m_percent < 37.5f) {
Point var = Point(0, std::max<int>(m_percent - 12.5, 0.0) * (drawRect.bottom() - drawRect.top()) / 25.0); Point var = Point(0, std::max<int>(m_percent - 12.5f, 0.f) * (drawRect.bottom() - drawRect.top()) / 25.f);
g_painter->drawFilledTriangle(drawRect.center(), drawRect.bottomRight() + Point(1,1), drawRect.topRight() + var + Point(1,0)); g_painter->drawFilledTriangle(drawRect.center(), drawRect.bottomRight() + Point(1,1), drawRect.topRight() + var + Point(1,0));
} }
// 37.5% - 62.5% (25) // 37.5% - 62.5% (25)
// triangle from bottom right to bottom left (var x) // triangle from bottom right to bottom left (var x)
if(m_percent < 62.5) { if(m_percent < 62.5f) {
Point var = Point(std::max<int>(m_percent - 37.5, 0.0) * (drawRect.right() - drawRect.left()) / 25.0, 0); Point var = Point(std::max<int>(m_percent - 37.5f, 0.f) * (drawRect.right() - drawRect.left()) / 25.f, 0);
g_painter->drawFilledTriangle(drawRect.center(), drawRect.bottomLeft() + Point(0,1), drawRect.bottomRight() - var + Point(1,1)); g_painter->drawFilledTriangle(drawRect.center(), drawRect.bottomLeft() + Point(0,1), drawRect.bottomRight() - var + Point(1,1));
} }
// 62.5% - 87.5% (25) // 62.5% - 87.5% (25)
// triangle from bottom left to top left // triangle from bottom left to top left
if(m_percent < 87.5) { if(m_percent < 87.5f) {
Point var = Point(0, std::max<int>(m_percent - 62.5, 0.0) * (drawRect.bottom() - drawRect.top()) / 25.0); Point var = Point(0, std::max<int>(m_percent - 62.5f, 0.f) * (drawRect.bottom() - drawRect.top()) / 25.f);
g_painter->drawFilledTriangle(drawRect.center(), drawRect.topLeft(), drawRect.bottomLeft() - var + Point(0,1)); g_painter->drawFilledTriangle(drawRect.center(), drawRect.topLeft(), drawRect.bottomLeft() - var + Point(0,1));
} }
// 87.5% - 100% (12.5) // 87.5% - 100% (12.5)
// triangle from top left to top center // triangle from top left to top center
if(m_percent < 100) { if(m_percent < 100) {
Point var = Point(std::max<int>(m_percent - 87.5, 0.0) * (drawRect.horizontalCenter() - drawRect.left()) / 12.5, 0); Point var = Point(std::max<int>(m_percent - 87.5f, 0.f) * (drawRect.horizontalCenter() - drawRect.left()) / 12.5f, 0);
g_painter->drawFilledTriangle(drawRect.center(), drawRect.topCenter(), drawRect.topLeft() + var); g_painter->drawFilledTriangle(drawRect.center(), drawRect.topCenter(), drawRect.topLeft() + var);
} }
@@ -84,7 +84,7 @@ void UIProgressRect::drawSelf(Fw::DrawPane drawPane)
void UIProgressRect::setPercent(float percent) void UIProgressRect::setPercent(float percent)
{ {
m_percent = stdext::clamp<float>((double)percent, 0.0, 100.0); m_percent = stdext::clamp<float>(percent, 0.f, 100.f);
} }
void UIProgressRect::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode) void UIProgressRect::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)

View File

@@ -46,7 +46,9 @@ void exitSignalHandler(int sig)
case SIGINT: case SIGINT:
if(!signaled && !g_app.isStopping() && !g_app.isTerminated()) { if(!signaled && !g_app.isStopping() && !g_app.isTerminated()) {
signaled = true; signaled = true;
g_dispatcher.addEvent(std::bind(&Application::close, &g_app)); g_dispatcher.addEvent([] () {
g_app.close();
});
} }
break; break;
} }

View File

@@ -38,7 +38,9 @@ void AsyncDispatcher::terminate()
void AsyncDispatcher::spawn_thread() void AsyncDispatcher::spawn_thread()
{ {
m_running = true; m_running = true;
m_threads.emplace_back(std::bind(&AsyncDispatcher::exec_loop, this)); m_threads.emplace_back([this] () {
exec_loop();
});
} }
void AsyncDispatcher::stop() void AsyncDispatcher::stop()

View File

@@ -45,9 +45,15 @@ void GraphicalApplication::init(std::vector<std::string>& args)
// setup platform window // setup platform window
g_window.init(); g_window.init();
g_window.hide(); g_window.hide();
g_window.setOnResize(std::bind(&GraphicalApplication::resize, this, std::placeholders::_1)); g_window.setOnResize([this] (auto size) {
g_window.setOnInputEvent(std::bind(&GraphicalApplication::inputEvent, this, std::placeholders::_1)); resize(size);
g_window.setOnClose(std::bind(&GraphicalApplication::close, this)); });
g_window.setOnInputEvent([this] (const auto &event) {
inputEvent(event);
});
g_window.setOnClose([this] () {
close();
});
g_mouse.init(); g_mouse.init();

View File

@@ -25,6 +25,7 @@
//#include <boost/regex.hpp> //#include <boost/regex.hpp>
#include <framework/core/resourcemanager.h> #include <framework/core/resourcemanager.h>
#include <framework/core/asyncdispatcher.h>
#ifdef FW_GRAPHICS #ifdef FW_GRAPHICS
#include <framework/platform/platformwindow.h> #include <framework/platform/platformwindow.h>
@@ -95,6 +96,10 @@ void Logger::log(Fw::LogLevel level, const std::string& message)
g_window.displayFatalError(message); g_window.displayFatalError(message);
#endif #endif
s_ignoreLogs = true; s_ignoreLogs = true;
// NOTE: Threads must finish before the process can exit.
g_asyncDispatcher.terminate();
exit(-1); exit(-1);
} }
} }

View File

@@ -158,6 +158,7 @@ static lua_Unsigned luaL_checkunsigned (lua_State *L, int arg) {
#define LUAMOD_API LUALIB_API #define LUAMOD_API LUALIB_API
#define LUA_BIT32LIBNAME "bit32" #define LUA_BIT32LIBNAME "bit32"
#undef luaL_newlib
#define luaL_newlib(x, y) luaL_register(x, LUA_BIT32LIBNAME, y) #define luaL_newlib(x, y) luaL_register(x, LUA_BIT32LIBNAME, y)
/* ----- avoid a 'symbol redefined' warning below ----- */ /* ----- avoid a 'symbol redefined' warning below ----- */

View File

@@ -818,6 +818,7 @@ void Application::registerLuaFunctions()
g_lua.bindClassMemberFunction<OutputMessage>("addU32", &OutputMessage::addU32); g_lua.bindClassMemberFunction<OutputMessage>("addU32", &OutputMessage::addU32);
g_lua.bindClassMemberFunction<OutputMessage>("addU64", &OutputMessage::addU64); g_lua.bindClassMemberFunction<OutputMessage>("addU64", &OutputMessage::addU64);
g_lua.bindClassMemberFunction<OutputMessage>("addString", &OutputMessage::addString); g_lua.bindClassMemberFunction<OutputMessage>("addString", &OutputMessage::addString);
g_lua.bindClassMemberFunction<OutputMessage>("addRawString", &OutputMessage::addRawString);
g_lua.bindClassMemberFunction<OutputMessage>("addPaddingBytes", &OutputMessage::addPaddingBytes); g_lua.bindClassMemberFunction<OutputMessage>("addPaddingBytes", &OutputMessage::addPaddingBytes);
g_lua.bindClassMemberFunction<OutputMessage>("encryptRsa", &OutputMessage::encryptRsa); g_lua.bindClassMemberFunction<OutputMessage>("encryptRsa", &OutputMessage::encryptRsa);
g_lua.bindClassMemberFunction<OutputMessage>("getMessageSize", &OutputMessage::getMessageSize); g_lua.bindClassMemberFunction<OutputMessage>("getMessageSize", &OutputMessage::getMessageSize);

View File

@@ -98,20 +98,28 @@ void Connection::connect(const std::string& host, uint16 port, const std::functi
m_connectCallback = connectCallback; m_connectCallback = connectCallback;
asio::ip::tcp::resolver::query query(host, stdext::unsafe_cast<std::string>(port)); asio::ip::tcp::resolver::query query(host, stdext::unsafe_cast<std::string>(port));
m_resolver.async_resolve(query, std::bind(&Connection::onResolve, asConnection(), std::placeholders::_1, std::placeholders::_2)); m_resolver.async_resolve(query, [connection = asConnection()] (auto error, auto iterator) {
connection->onResolve(error, iterator);
});
m_readTimer.cancel(); m_readTimer.cancel();
m_readTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(READ_TIMEOUT))); m_readTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(READ_TIMEOUT)));
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1)); m_readTimer.async_wait([connection = asConnection()] (auto error) {
connection->onTimeout(error);
});
} }
void Connection::internal_connect(asio::ip::basic_resolver<asio::ip::tcp>::iterator endpointIterator) void Connection::internal_connect(asio::ip::basic_resolver<asio::ip::tcp>::iterator endpointIterator)
{ {
m_socket.async_connect(*endpointIterator, std::bind(&Connection::onConnect, asConnection(), std::placeholders::_1)); m_socket.async_connect(*endpointIterator, [connection = asConnection()] (auto error) {
connection->onConnect(error);
});
m_readTimer.cancel(); m_readTimer.cancel();
m_readTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(READ_TIMEOUT))); m_readTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(READ_TIMEOUT)));
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1)); m_readTimer.async_wait([connection = asConnection()] (auto error) {
connection->onTimeout(error);
});
} }
void Connection::write(uint8* buffer, size_t size) void Connection::write(uint8* buffer, size_t size)
@@ -129,7 +137,9 @@ void Connection::write(uint8* buffer, size_t size)
m_delayedWriteTimer.cancel(); m_delayedWriteTimer.cancel();
m_delayedWriteTimer.expires_from_now(boost::posix_time::milliseconds(0)); m_delayedWriteTimer.expires_from_now(boost::posix_time::milliseconds(0));
m_delayedWriteTimer.async_wait(std::bind(&Connection::onCanWrite, asConnection(), std::placeholders::_1)); m_delayedWriteTimer.async_wait([connection = asConnection()] (auto error) {
connection->onCanWrite(error);
});
} }
std::ostream os(m_outputStream.get()); std::ostream os(m_outputStream.get());
@@ -145,13 +155,15 @@ void Connection::internal_write()
std::shared_ptr<asio::streambuf> outputStream = m_outputStream; std::shared_ptr<asio::streambuf> outputStream = m_outputStream;
m_outputStream = nullptr; m_outputStream = nullptr;
asio::async_write(m_socket, asio::async_write(m_socket, *outputStream, [connection = asConnection(), outputStream] (auto error, auto size) {
*outputStream, connection->onWrite(error, size, outputStream);
std::bind(&Connection::onWrite, asConnection(), std::placeholders::_1, std::placeholders::_2, outputStream)); });
m_writeTimer.cancel(); m_writeTimer.cancel();
m_writeTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(WRITE_TIMEOUT))); m_writeTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(WRITE_TIMEOUT)));
m_writeTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1)); m_writeTimer.async_wait([connection = asConnection()] (auto error) {
connection->onTimeout(error);
});
} }
void Connection::read(uint16 bytes, const RecvCallback& callback) void Connection::read(uint16 bytes, const RecvCallback& callback)
@@ -161,13 +173,15 @@ void Connection::read(uint16 bytes, const RecvCallback& callback)
m_recvCallback = callback; m_recvCallback = callback;
asio::async_read(m_socket, asio::async_read(m_socket, asio::mutable_buffer(m_inputStream.prepare(bytes)), [connection = asConnection()] (auto error, auto size) {
asio::buffer(m_inputStream.prepare(bytes)), connection->onRecv(error, size);
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2)); });
m_readTimer.cancel(); m_readTimer.cancel();
m_readTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(READ_TIMEOUT))); m_readTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(READ_TIMEOUT)));
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1)); m_readTimer.async_wait([connection = asConnection()] (auto error) {
connection->onTimeout(error);
});
} }
void Connection::read_until(const std::string& what, const RecvCallback& callback) void Connection::read_until(const std::string& what, const RecvCallback& callback)
@@ -177,14 +191,15 @@ void Connection::read_until(const std::string& what, const RecvCallback& callbac
m_recvCallback = callback; m_recvCallback = callback;
asio::async_read_until(m_socket, asio::async_read_until(m_socket, m_inputStream, what, [connection = asConnection()] (auto error, auto size) {
m_inputStream, connection->onRecv(error, size);
what, });
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2));
m_readTimer.cancel(); m_readTimer.cancel();
m_readTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(READ_TIMEOUT))); m_readTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(READ_TIMEOUT)));
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1)); m_readTimer.async_wait([connection = asConnection()] (auto error) {
connection->onTimeout(error);
});
} }
void Connection::read_some(const RecvCallback& callback) void Connection::read_some(const RecvCallback& callback)
@@ -194,12 +209,15 @@ void Connection::read_some(const RecvCallback& callback)
m_recvCallback = callback; m_recvCallback = callback;
m_socket.async_read_some(asio::buffer(m_inputStream.prepare(RECV_BUFFER_SIZE)), m_socket.async_read_some(asio::mutable_buffer(m_inputStream.prepare(RECV_BUFFER_SIZE)), [connection = asConnection()] (auto buffer, auto size) {
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2)); connection->onRecv(buffer, size);
});
m_readTimer.cancel(); m_readTimer.cancel();
m_readTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(READ_TIMEOUT))); m_readTimer.expires_from_now(boost::posix_time::seconds(static_cast<uint32>(READ_TIMEOUT)));
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1)); m_readTimer.async_wait([connection = asConnection()] (auto error) {
connection->onTimeout(error);
});
} }
void Connection::onResolve(const boost::system::error_code& error, asio::ip::basic_resolver<asio::ip::tcp>::iterator endpointIterator) void Connection::onResolve(const boost::system::error_code& error, asio::ip::basic_resolver<asio::ip::tcp>::iterator endpointIterator)

View File

@@ -89,6 +89,17 @@ void OutputMessage::addString(const std::string& buffer)
m_messageSize += len; m_messageSize += len;
} }
void OutputMessage::addRawString(const std::string& buffer)
{
int len = buffer.length();
if (len > MAX_STRING_LENGTH)
throw stdext::exception(stdext::format("string length > %d", MAX_STRING_LENGTH));
checkWrite(len);
memcpy((char*)(m_buffer + m_writePos), buffer.c_str(), len);
m_writePos += len;
m_messageSize += len;
}
void OutputMessage::addPaddingBytes(int bytes, uint8 byte) void OutputMessage::addPaddingBytes(int bytes, uint8 byte)
{ {
if(bytes <= 0) if(bytes <= 0)

View File

@@ -48,6 +48,7 @@ public:
void addU32(uint32 value); void addU32(uint32 value);
void addU64(uint64 value); void addU64(uint64 value);
void addString(const std::string& buffer); void addString(const std::string& buffer);
void addRawString(const std::string& buffer);
void addPaddingBytes(int bytes, uint8 byte = 0); void addPaddingBytes(int bytes, uint8 byte = 0);
void encryptRsa(); void encryptRsa();

View File

@@ -43,8 +43,12 @@ Protocol::~Protocol()
void Protocol::connect(const std::string& host, uint16 port) void Protocol::connect(const std::string& host, uint16 port)
{ {
m_connection = ConnectionPtr(new Connection); m_connection = ConnectionPtr(new Connection);
m_connection->setErrorCallback(std::bind(&Protocol::onError, asProtocol(), std::placeholders::_1)); m_connection->setErrorCallback([proto = asProtocol()] (auto error) {
m_connection->connect(host, port, std::bind(&Protocol::onConnect, asProtocol())); proto->onError(error);
});
m_connection->connect(host, port, [proto = asProtocol()] () {
proto->onConnect();
});
} }
void Protocol::disconnect() void Protocol::disconnect()
@@ -104,7 +108,9 @@ void Protocol::recv()
// read the first 2 bytes which contain the message size // read the first 2 bytes which contain the message size
if(m_connection) if(m_connection)
m_connection->read(2, std::bind(&Protocol::internalRecvHeader, asProtocol(), std::placeholders::_1, std::placeholders::_2)); m_connection->read(2, [proto = asProtocol()] (auto buffer, auto size) {
proto->internalRecvHeader(buffer, size);
});
} }
void Protocol::internalRecvHeader(uint8* buffer, uint16 size) void Protocol::internalRecvHeader(uint8* buffer, uint16 size)
@@ -115,7 +121,9 @@ void Protocol::internalRecvHeader(uint8* buffer, uint16 size)
// read remaining message data // read remaining message data
if(m_connection) if(m_connection)
m_connection->read(remainingSize, std::bind(&Protocol::internalRecvData, asProtocol(), std::placeholders::_1, std::placeholders::_2)); m_connection->read(remainingSize, [proto = asProtocol()] (auto buffer, auto size) {
proto->internalRecvData(buffer, size);
});
} }
void Protocol::internalRecvData(uint8* buffer, uint16 size) void Protocol::internalRecvData(uint8* buffer, uint16 size)

View File

@@ -39,8 +39,12 @@ ProtocolHttp::~ProtocolHttp()
void ProtocolHttp::connect(const std::string& host, uint16 port) void ProtocolHttp::connect(const std::string& host, uint16 port)
{ {
m_connection = ConnectionPtr(new Connection); m_connection = ConnectionPtr(new Connection);
m_connection->setErrorCallback(std::bind(&ProtocolHttp::onError, asProtocolHttp(), std::placeholders::_1)); m_connection->setErrorCallback([proto = asProtocolHttp()] (auto error) {
m_connection->connect(host, port, std::bind(&ProtocolHttp::onConnect, asProtocolHttp())); proto->onError(error);
});
m_connection->connect(host, port, [proto = asProtocolHttp()] () {
proto->onConnect();
});
} }
void ProtocolHttp::disconnect() void ProtocolHttp::disconnect()
@@ -60,7 +64,9 @@ void ProtocolHttp::send(const std::string& message)
void ProtocolHttp::recv() void ProtocolHttp::recv()
{ {
if(m_connection) if(m_connection)
m_connection->read_until("\r\n\r\n", std::bind(&ProtocolHttp::onRecv, asProtocolHttp(), std::placeholders::_1, std::placeholders::_2)); m_connection->read_until("\r\n\r\n", [proto = asProtocolHttp()] (auto buffer, auto size) {
proto->onRecv(buffer, size);
});
} }
void ProtocolHttp::onConnect() void ProtocolHttp::onConnect()

View File

@@ -119,9 +119,14 @@ ticks_t Platform::getFileModificationTime(std::string file)
void Platform::openUrl(std::string url) void Platform::openUrl(std::string url)
{ {
if(url.find("http://") == std::string::npos) if(url.find("http://") == std::string::npos && url.find("https://") == std::string::npos)
url.insert(0, "http://"); url.insert(0, "http://");
#if defined(__APPLE__)
system(stdext::format("open %s", url).c_str());
#else
system(stdext::format("xdg-open %s", url).c_str()); system(stdext::format("xdg-open %s", url).c_str());
#endif
} }
std::string Platform::getCPUName() std::string Platform::getCPUName()

View File

@@ -148,7 +148,7 @@ ticks_t Platform::getFileModificationTime(std::string file)
void Platform::openUrl(std::string url) void Platform::openUrl(std::string url)
{ {
if(url.find("http://") == std::string::npos) if(url.find("http://") == std::string::npos && url.find("https://") == std::string::npos)
url.insert(0, "http://"); url.insert(0, "http://");
ShellExecuteW(NULL, L"open", stdext::utf8_to_utf16(url).c_str(), NULL, NULL, SW_SHOWNORMAL); ShellExecuteW(NULL, L"open", stdext::utf8_to_utf16(url).c_str(), NULL, NULL, SW_SHOWNORMAL);
} }

View File

@@ -88,6 +88,11 @@ X11Window::X11Window()
m_keyMap[XK_Meta_R] = Fw::KeyMeta; m_keyMap[XK_Meta_R] = Fw::KeyMeta;
m_keyMap[XK_Menu] = Fw::KeyMenu; m_keyMap[XK_Menu] = Fw::KeyMenu;
#if defined(__APPLE__)
m_keyMap[65406] = Fw::KeyAlt;// Option
m_keyMap[65511] = Fw::KeyMeta;// Command
#endif
// ascii characters // ascii characters
m_keyMap[XK_space] = Fw::KeySpace; m_keyMap[XK_space] = Fw::KeySpace;
m_keyMap[XK_exclam] = Fw::KeyExclamation; m_keyMap[XK_exclam] = Fw::KeyExclamation;

View File

@@ -65,7 +65,7 @@ void UIWidget::draw(const Rect& visibleRect, Fw::DrawPane drawPane)
if(m_rotation != 0.0f) { if(m_rotation != 0.0f) {
g_painter->pushTransformMatrix(); g_painter->pushTransformMatrix();
g_painter->rotate(m_rect.center(), m_rotation * (Fw::pi / 180.0)); g_painter->rotate(m_rect.center(), m_rotation * (Fw::pi / 180.f));
} }
drawSelf(drawPane); drawSelf(drawPane);
@@ -1717,9 +1717,9 @@ bool UIWidget::propagateOnMouseMove(const Point& mousePos, const Point& mouseMov
if(child->isExplicitlyVisible() && child->isExplicitlyEnabled() && child->containsPoint(mousePos)) if(child->isExplicitlyVisible() && child->isExplicitlyEnabled() && child->containsPoint(mousePos))
child->propagateOnMouseMove(mousePos, mouseMoved, widgetList); child->propagateOnMouseMove(mousePos, mouseMoved, widgetList);
widgetList.push_back(static_self_cast<UIWidget>());
} }
} }
widgetList.push_back(static_self_cast<UIWidget>());
return true; return true;
} }

View File

@@ -489,7 +489,7 @@ protected:
BitmapFontPtr m_font; BitmapFontPtr m_font;
public: public:
void resizeToText() { setSize(getTextSize()); } void resizeToText();
void clearText() { setText(""); } void clearText() { setText(""); }
void setText(std::string text, bool dontFireLuaCall = false); void setText(std::string text, bool dontFireLuaCall = false);

View File

@@ -56,6 +56,15 @@ void UIWidget::updateText()
m_textMustRecache = true; m_textMustRecache = true;
} }
void UIWidget::resizeToText()
{
auto textSize = getTextSize();
textSize += Size(m_padding.left + m_padding.right, m_padding.top + m_padding.bottom);
textSize += m_textOffset.toSize();
setSize(textSize);
}
void UIWidget::parseTextStyle(const OTMLNodePtr& styleNode) void UIWidget::parseTextStyle(const OTMLNodePtr& styleNode)
{ {
for(const OTMLNodePtr& node : styleNode->children()) { for(const OTMLNodePtr& node : styleNode->children()) {

View File

@@ -21,30 +21,108 @@
*/ */
#include "color.h" #include "color.h"
#include <iomanip>
// NOTE: AABBGGRR order // NOTE: AABBGGRR order
const Color Color::alpha = 0x00000000U; const Color Color::alpha = 0x00000000U;
const Color Color::white = 0xffffffff; const Color Color::white = 0xffffffffU;
const Color Color::black = 0xff000000; const Color Color::black = 0xff000000U;
const Color Color::red = 0xff0000ff; const Color Color::red = 0xff0000ffU;
const Color Color::darkRed = 0xff000080; const Color Color::darkRed = 0xff000080U;
const Color Color::green = 0xff00ff00; const Color Color::green = 0xff00ff00U;
const Color Color::darkGreen = 0xff008000; const Color Color::darkGreen = 0xff008000U;
const Color Color::blue = 0xffff0000; const Color Color::blue = 0xffff0000U;
const Color Color::darkBlue = 0xff800000; const Color Color::darkBlue = 0xff800000U;
const Color Color::pink = 0xffff00ff; const Color Color::pink = 0xffff00ffU;
const Color Color::darkPink = 0xff800080; const Color Color::darkPink = 0xff800080U;
const Color Color::yellow = 0xff00ffff; const Color Color::yellow = 0xff00ffffU;
const Color Color::darkYellow = 0xff008080; const Color Color::darkYellow = 0xff008080U;
const Color Color::teal = 0xffffff00; const Color Color::teal = 0xffffff00U;
const Color Color::darkTeal = 0xff808000; const Color Color::darkTeal = 0xff808000U;
const Color Color::gray = 0xffa0a0a0; const Color Color::gray = 0xffa0a0a0U;
const Color Color::darkGray = 0xff808080; const Color Color::darkGray = 0xff808080U;
const Color Color::lightGray = 0xffc0c0c0; const Color Color::lightGray = 0xffc0c0c0U;
const Color Color::orange = 0xff008cff; const Color Color::orange = 0xff008cffU;
Color::Color(const std::string& coltext) Color::Color(const std::string& coltext)
{ {
std::stringstream ss(coltext); std::stringstream ss(coltext);
ss >> *this; ss >> *this;
} }
std::ostream& operator<<(std::ostream& out, const Color& color)
{
return out << '#'
<< std::hex << std::setfill('0')
<< std::setw(2) << (int)color.r()
<< std::setw(2) << (int)color.g()
<< std::setw(2) << (int)color.b()
<< std::setw(2) << (int)color.a()
<< std::dec << std::setfill(' ');
}
std::istream& operator>>(std::istream& in, Color& color)
{
std::string tmp;
if(in.peek() == '#') {
in.ignore() >> tmp;
if(tmp.length() == 6 || tmp.length() == 8) {
color.setRed((uint8)stdext::hex_to_dec(tmp.substr(0, 2)));
color.setGreen((uint8)stdext::hex_to_dec(tmp.substr(2, 2)));
color.setBlue((uint8)stdext::hex_to_dec(tmp.substr(4, 2)));
if(tmp.length() == 8)
color.setAlpha((uint8)stdext::hex_to_dec(tmp.substr(6, 2)));
else
color.setAlpha(255);
} else {
in.seekg(-tmp.length()-1, std::ios_base::cur);
}
} else {
in >> tmp;
if(tmp == "alpha") {
color = Color::alpha;
} else if(tmp == "black") {
color = Color::black;
} else if(tmp == "white") {
color = Color::white;
} else if(tmp == "red") {
color = Color::red;
} else if(tmp == "darkRed") {
color = Color::darkRed;
} else if(tmp == "green") {
color = Color::green;
} else if(tmp == "darkGreen") {
color = Color::darkGreen;
} else if(tmp == "blue") {
color = Color::blue;
} else if(tmp == "darkBlue") {
color = Color::darkBlue;
} else if(tmp == "pink") {
color = Color::pink;
} else if(tmp == "darkPink") {
color = Color::darkPink;
} else if(tmp == "yellow") {
color = Color::yellow;
} else if(tmp == "darkYellow") {
color = Color::darkYellow;
} else if(tmp == "teal") {
color = Color::teal;
} else if(tmp == "darkTeal") {
color = Color::darkTeal;
} else if(tmp == "gray") {
color = Color::gray;
} else if(tmp == "darkGray") {
color = Color::darkGray;
} else if(tmp == "lightGray") {
color = Color::lightGray;
} else if(tmp == "orange") {
color = Color::orange;
} else {
in.seekg(-tmp.length(), std::ios_base::cur);
}
}
return in;
}

View File

@@ -27,7 +27,6 @@
#include "../stdext/cast.h" #include "../stdext/cast.h"
#include "../stdext/string.h" #include "../stdext/string.h"
#include "../const.h" #include "../const.h"
#include <iomanip>
class Color class Color
{ {
@@ -124,83 +123,7 @@ private:
float m_a; float m_a;
}; };
inline std::ostream& operator<<(std::ostream& out, const Color& color) std::ostream& operator<<(std::ostream& out, const Color& color);
{ std::istream& operator>>(std::istream& in, Color& color);
using namespace std;
out << "#" << hex << setfill('0')
<< setw(2) << (int)color.r()
<< setw(2) << (int)color.g()
<< setw(2) << (int)color.b()
<< setw(2) << (int)color.a();
out << dec << setfill(' ');
return out;
}
inline std::istream& operator>>(std::istream& in, Color& color)
{
using namespace std;
std::string tmp;
if(in.get() == '#') {
in >> tmp;
if(tmp.length() == 6 || tmp.length() == 8) {
color.setRed((uint8)stdext::hex_to_dec(tmp.substr(0, 2)));
color.setGreen((uint8)stdext::hex_to_dec(tmp.substr(2, 2)));
color.setBlue((uint8)stdext::hex_to_dec(tmp.substr(4, 2)));
if(tmp.length() == 8)
color.setAlpha((uint8)stdext::hex_to_dec(tmp.substr(6, 2)));
else
color.setAlpha(255);
} else
in.seekg(-(std::istream::streampos)tmp.length()-1, ios_base::cur);
} else {
in.unget();
in >> tmp;
if(tmp == "alpha") {
color = Color::alpha;
} else if(tmp == "black") {
color = Color::black;
} else if(tmp == "white") {
color = Color::white;
} else if(tmp == "red") {
color = Color::red;
} else if(tmp == "darkRed") {
color = Color::darkRed;
} else if(tmp == "green") {
color = Color::green;
} else if(tmp == "darkGreen") {
color = Color::darkGreen;
} else if(tmp == "blue") {
color = Color::blue;
} else if(tmp == "darkBlue") {
color = Color::darkBlue;
} else if(tmp == "pink") {
color = Color::pink;
} else if(tmp == "darkPink") {
color = Color::darkPink;
} else if(tmp == "yellow") {
color = Color::yellow;
} else if(tmp == "darkYellow") {
color = Color::darkYellow;
} else if(tmp == "teal") {
color = Color::teal;
} else if(tmp == "darkTeal") {
color = Color::darkTeal;
} else if(tmp == "gray") {
color = Color::gray;
} else if(tmp == "darkGray") {
color = Color::darkGray;
} else if(tmp == "lightGray") {
color = Color::lightGray;
} else if(tmp == "orange") {
color = Color::orange;
} else {
in.seekg(-tmp.length(), ios_base::cur);
}
}
return in;
}
#endif #endif

View File

@@ -267,7 +267,7 @@ void Crypt::rsaSetPrivateKey(const std::string& p, const std::string& q, const s
mpz_set_str(m_d, d.c_str(), 10); mpz_set_str(m_d, d.c_str(), 10);
// n = p * q // n = p * q
mpz_mul(n, p, q); mpz_mul(m_n, m_p, m_q);
#else #else
#if OPENSSL_VERSION_NUMBER < 0x10100005L #if OPENSSL_VERSION_NUMBER < 0x10100005L
BN_dec2bn(&m_rsa->p, p.c_str()); BN_dec2bn(&m_rsa->p, p.c_str());

View File

@@ -89,7 +89,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<AdditionalIncludeDirectories>$(VcpkgInstalledDir)$(VcpkgTriplet)\include\luajit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\luajit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<TargetMachine>MachineX86</TargetMachine> <TargetMachine>MachineX86</TargetMachine>
@@ -101,7 +101,7 @@
<PreprocessorDefinitions>$(PREPROCESSOR_DEFS);_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>$(PREPROCESSOR_DEFS);_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet>
<AdditionalIncludeDirectories>$(VcpkgInstalledDir)$(VcpkgTriplet)\include\luajit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\luajit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@@ -115,7 +115,7 @@
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalIncludeDirectories>$(VcpkgInstalledDir)$(VcpkgTriplet)\include\luajit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\luajit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<TargetMachine>MachineX86</TargetMachine> <TargetMachine>MachineX86</TargetMachine>
@@ -134,7 +134,7 @@
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalIncludeDirectories>$(VcpkgInstalledDir)$(VcpkgTriplet)\include\luajit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\luajit;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@@ -323,7 +323,6 @@
<ClInclude Include="..\src\client\spritemanager.h" /> <ClInclude Include="..\src\client\spritemanager.h" />
<ClInclude Include="..\src\client\statictext.h" /> <ClInclude Include="..\src\client\statictext.h" />
<ClInclude Include="..\src\client\thing.h" /> <ClInclude Include="..\src\client\thing.h" />
<ClInclude Include="..\src\client\thingstype.h" />
<ClInclude Include="..\src\client\thingtype.h" /> <ClInclude Include="..\src\client\thingtype.h" />
<ClInclude Include="..\src\client\thingtypemanager.h" /> <ClInclude Include="..\src\client\thingtypemanager.h" />
<ClInclude Include="..\src\client\tile.h" /> <ClInclude Include="..\src\client\tile.h" />

View File

@@ -1010,9 +1010,6 @@
<ClInclude Include="..\src\client\thing.h"> <ClInclude Include="..\src\client\thing.h">
<Filter>Header Files\client</Filter> <Filter>Header Files\client</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\src\client\thingstype.h">
<Filter>Header Files\client</Filter>
</ClInclude>
<ClInclude Include="..\src\client\thingtype.h"> <ClInclude Include="..\src\client\thingtype.h">
<Filter>Header Files\client</Filter> <Filter>Header Files\client</Filter>
</ClInclude> </ClInclude>