1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Merge vcmi/beta into vcmi/develop

This commit is contained in:
Ivan Savenko 2023-01-29 18:21:55 +02:00
commit 57ee9a9bf3
21 changed files with 267 additions and 107 deletions

View File

@ -1,3 +0,0 @@
#!/usr/bin/env bash
"$1/ios/zip2ipa.sh" "$2"

View File

@ -729,6 +729,7 @@ elseif(APPLE_MACOS AND NOT ENABLE_MONOLITHIC_INSTALL)
add_subdirectory(osx)
elseif(APPLE_IOS)
set(CPACK_GENERATOR ZIP)
set(CPACK_ARCHIVE_FILE_EXTENSION ipa)
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_CURRENT_BINARY_DIR};${CMAKE_PROJECT_NAME};app;/")
else()

View File

@ -376,7 +376,8 @@ int main(int argc, char * argv[])
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
#endif // VCMI_ANDROID
GH.mainFPSmng->init(); //(!)init here AFTER SDL_Init() while using SDL for FPS management
//(!)init here AFTER SDL_Init() while using SDL for FPS management
GH.init();
SDL_LogSetOutputFunction(&SDLLogCallback, nullptr);
@ -432,11 +433,20 @@ int main(int argc, char * argv[])
CCS->musich->setVolume((ui32)settings["general"]["music"].Float());
logGlobal->info("Initializing screen and sound handling: %d ms", pomtime.getDiff());
}
#ifdef VCMI_MAC
// Ctrl+click should be treated as a right click on Mac OS X
SDL_SetHint(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, "1");
#endif
#ifdef SDL_HINT_MOUSE_TOUCH_EVENTS
if(GH.isPointerRelativeMode)
{
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
}
#endif
#ifndef VCMI_NO_THREADED_LOAD
//we can properly play intro only in the main thread, so we have to move loading to the separate thread
boost::thread loading(init);

View File

@ -263,8 +263,7 @@ elseif(APPLE_IOS)
set_source_files_properties(${XCODE_RESOURCE_PATH} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
# workaround to prevent CMAKE_SKIP_PRECOMPILE_HEADERS being added as compile flag
# add max version condition when https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7562 is merged
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.22.0")
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.22.0" AND CMAKE_VERSION VERSION_LESS "3.25.0")
set_source_files_properties(${XCODE_RESOURCE_PATH} PROPERTIES LANGUAGE CXX)
endif()
endforeach()

View File

@ -775,14 +775,14 @@ void CClient::removeGUI()
}
#ifdef VCMI_ANDROID
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_clientSetupJNI(JNIEnv * env, jobject cls)
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_clientSetupJNI(JNIEnv * env, jclass cls)
{
logNetwork->info("Received clientSetupJNI");
CAndroidVMHelper::cacheVM(env);
}
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_notifyServerClosed(JNIEnv * env, jobject cls)
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_notifyServerClosed(JNIEnv * env, jclass cls)
{
logNetwork->info("Received server closed signal");
if (CSH) {
@ -790,13 +790,13 @@ extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_notifyServerCl
}
}
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_notifyServerReady(JNIEnv * env, jobject cls)
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_notifyServerReady(JNIEnv * env, jclass cls)
{
logNetwork->info("Received server ready signal");
androidTestServerReadyFlag.store(true);
}
extern "C" JNIEXPORT bool JNICALL Java_eu_vcmi_vcmi_NativeMethods_tryToSaveTheGame(JNIEnv * env, jobject cls)
extern "C" JNIEXPORT jboolean JNICALL Java_eu_vcmi_vcmi_NativeMethods_tryToSaveTheGame(JNIEnv * env, jclass cls)
{
logGlobal->info("Received emergency save game request");
if(!LOCPLINT || !LOCPLINT->cb)

View File

@ -79,6 +79,13 @@ void CGuiHandler::processLists(const ui16 activityFlag, std::function<void (std:
processList(CIntObject::TEXTINPUT,activityFlag,&textInterested,cb);
}
void CGuiHandler::init()
{
mainFPSmng->init();
isPointerRelativeMode = settings["general"]["userRelativePointer"].Bool();
pointerSpeedMultiplier = settings["general"]["relativePointerSpeedMultiplier"].Float();
}
void CGuiHandler::handleElementActivate(CIntObject * elem, ui16 activityFlag)
{
processLists(activityFlag,[&](std::list<CIntObject*> * lst){
@ -207,7 +214,79 @@ void CGuiHandler::handleEvents()
}
}
void CGuiHandler::handleCurrentEvent(const SDL_Event & current )
void CGuiHandler::convertTouchToMouse(SDL_Event * current)
{
int rLogicalWidth, rLogicalHeight;
SDL_RenderGetLogicalSize(mainRenderer, &rLogicalWidth, &rLogicalHeight);
int adjustedMouseY = (int)(current->tfinger.y * rLogicalHeight);
int adjustedMouseX = (int)(current->tfinger.x * rLogicalWidth);
current->button.x = adjustedMouseX;
current->motion.x = adjustedMouseX;
current->button.y = adjustedMouseY;
current->motion.y = adjustedMouseY;
}
void CGuiHandler::fakeMoveCursor(float dx, float dy)
{
int x, y, w, h;
SDL_Event event;
SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0, 0, 0};
sme.state = SDL_GetMouseState(&x, &y);
SDL_GetWindowSize(mainWindow, &w, &h);
sme.x = CCS->curh->position().x + (int)(GH.pointerSpeedMultiplier * w * dx);
sme.y = CCS->curh->position().y + (int)(GH.pointerSpeedMultiplier * h * dy);
vstd::abetween(sme.x, 0, w);
vstd::abetween(sme.y, 0, h);
event.motion = sme;
SDL_PushEvent(&event);
}
void CGuiHandler::fakeMouseMove()
{
fakeMoveCursor(0, 0);
}
void CGuiHandler::fakeMouseButtonEventRelativeMode(bool down, bool right)
{
SDL_Event event;
SDL_MouseButtonEvent sme = {SDL_MOUSEBUTTONDOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if(!down)
{
sme.type = SDL_MOUSEBUTTONUP;
}
sme.button = right ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT;
sme.x = CCS->curh->position().x;
sme.y = CCS->curh->position().y;
float xScale, yScale;
int w, h, rLogicalWidth, rLogicalHeight;
SDL_GetWindowSize(mainWindow, &w, &h);
SDL_RenderGetLogicalSize(mainRenderer, &rLogicalWidth, &rLogicalHeight);
SDL_RenderGetScale(mainRenderer, &xScale, &yScale);
SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
CSDL_Ext::warpMouse(
(int)(sme.x * xScale) + (w - rLogicalWidth * xScale) / 2,
(int)(sme.y * yScale + (h - rLogicalHeight * yScale) / 2));
SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
event.button = sme;
SDL_PushEvent(&event);
}
void CGuiHandler::handleCurrentEvent( SDL_Event & current )
{
if(current.type == SDL_KEYDOWN || current.type == SDL_KEYUP)
{
@ -344,22 +423,78 @@ void CGuiHandler::handleCurrentEvent(const SDL_Event & current )
it->textEdited(current.edit);
}
}
//todo: muiltitouch
else if(current.type == SDL_MOUSEBUTTONUP)
{
switch(current.button.button)
if(!multifinger)
{
case SDL_BUTTON_LEFT:
handleMouseButtonClick(lclickable, EIntObjMouseBtnType::LEFT, false);
break;
case SDL_BUTTON_RIGHT:
handleMouseButtonClick(rclickable, EIntObjMouseBtnType::RIGHT, false);
break;
case SDL_BUTTON_MIDDLE:
handleMouseButtonClick(mclickable, EIntObjMouseBtnType::MIDDLE, false);
break;
switch(current.button.button)
{
case SDL_BUTTON_LEFT:
handleMouseButtonClick(lclickable, EIntObjMouseBtnType::LEFT, false);
break;
case SDL_BUTTON_RIGHT:
handleMouseButtonClick(rclickable, EIntObjMouseBtnType::RIGHT, false);
break;
case SDL_BUTTON_MIDDLE:
handleMouseButtonClick(mclickable, EIntObjMouseBtnType::MIDDLE, false);
break;
}
}
}
else if(current.type == SDL_FINGERMOTION)
{
if(isPointerRelativeMode)
{
fakeMoveCursor(current.tfinger.dx, current.tfinger.dy);
}
}
else if(current.type == SDL_FINGERDOWN)
{
auto fingerCount = SDL_GetNumTouchFingers(current.tfinger.touchId);
multifinger = fingerCount > 1;
if(isPointerRelativeMode)
{
if(current.tfinger.x > 0.5)
{
bool isRightClick = current.tfinger.y < 0.5;
fakeMouseButtonEventRelativeMode(true, isRightClick);
}
}
#ifndef VCMI_IOS
else if(fingerCount == 2)
{
convertTouchToMouse(&current);
handleMouseMotion(current);
handleMouseButtonClick(rclickable, EIntObjMouseBtnType::RIGHT, true);
}
#endif //VCMI_IOS
}
else if(current.type == SDL_FINGERUP)
{
auto fingerCount = SDL_GetNumTouchFingers(current.tfinger.touchId);
if(isPointerRelativeMode)
{
if(current.tfinger.x > 0.5)
{
bool isRightClick = current.tfinger.y < 0.5;
fakeMouseButtonEventRelativeMode(false, isRightClick);
}
}
#ifndef VCMI_IOS
else if(multifinger)
{
convertTouchToMouse(&current);
handleMouseMotion(current);
handleMouseButtonClick(rclickable, EIntObjMouseBtnType::RIGHT, false);
multifinger = fingerCount != 0;
}
#endif //VCMI_IOS
}
} //event end
void CGuiHandler::handleMouseButtonClick(CIntObjectList & interestedObjs, EIntObjMouseBtnType btn, bool isPressed)
@ -431,20 +566,6 @@ void CGuiHandler::handleMoveInterested(const SDL_MouseMotionEvent & motion)
}
}
void CGuiHandler::fakeMouseMove()
{
SDL_Event event;
SDL_MouseMotionEvent sme = {SDL_MOUSEMOTION, 0, 0, 0, 0, 0, 0, 0, 0};
int x, y;
sme.state = SDL_GetMouseState(&x, &y);
sme.x = x;
sme.y = y;
event.motion = sme;
SDL_PushEvent(&event);
}
void CGuiHandler::renderFrame()
{
@ -486,7 +607,8 @@ void CGuiHandler::renderFrame()
CGuiHandler::CGuiHandler()
: lastClick(-500, -500),lastClickTime(0), defActionsDef(0), captureChildren(false)
: lastClick(-500, -500),lastClickTime(0), defActionsDef(0), captureChildren(false),
multifinger(false)
{
continueEventHandling = true;
curInt = nullptr;

View File

@ -92,9 +92,12 @@ private:
void handleMouseButtonClick(CIntObjectList & interestedObjs, EIntObjMouseBtnType btn, bool isPressed);
void processLists(const ui16 activityFlag, std::function<void (std::list<CIntObject*> *)> cb);
void handleCurrentEvent(const SDL_Event & current);
void handleCurrentEvent(SDL_Event &current);
void handleMouseMotion(const SDL_Event & current);
void handleMoveInterested( const SDL_MouseMotionEvent & motion );
void convertTouchToMouse(SDL_Event * current);
void fakeMoveCursor(float dx, float dy);
void fakeMouseButtonEventRelativeMode(bool down, bool right);
public:
void handleElementActivate(CIntObject * elem, ui16 activityFlag);
@ -110,6 +113,9 @@ public:
Point lastClick;
unsigned lastClickTime;
bool multifinger;
bool isPointerRelativeMode;
float pointerSpeedMultiplier;
ui8 defActionsDef; //default auto actions
bool captureChildren; //all newly created objects will get their parents from stack and will be added to parents children list
@ -118,6 +124,7 @@ public:
CGuiHandler();
~CGuiHandler();
void init();
void renderFrame();
void totalRedraw(); //forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering

View File

@ -889,22 +889,10 @@ SDL_Color CSDL_Ext::makeColor(ui8 r, ui8 g, ui8 b, ui8 a)
void CSDL_Ext::startTextInput(const Rect & whereInput)
{
const SDL_Rect where = CSDL_Ext::toSDL(whereInput);
auto impl = [](SDL_Rect where)
{
if (SDL_IsTextInputActive() == SDL_FALSE)
{
SDL_StartTextInput();
}
SDL_SetTextInputRect(&where);
};
#ifdef VCMI_APPLE
dispatch_async(dispatch_get_main_queue(), ^{
#endif
#ifdef VCMI_IOS
// TODO ios: looks like SDL bug actually, try fixing there
auto renderer = SDL_GetRenderer(mainWindow);
float scaleX, scaleY;
@ -912,17 +900,25 @@ void CSDL_Ext::startTextInput(const Rect & whereInput)
SDL_RenderGetScale(renderer, &scaleX, &scaleY);
SDL_RenderGetViewport(renderer, &viewport);
#ifdef VCMI_IOS
const auto nativeScale = iOS_utils::screenScale();
auto rectInScreenCoordinates = where;
rectInScreenCoordinates.x = (viewport.x + rectInScreenCoordinates.x) * scaleX / nativeScale;
rectInScreenCoordinates.y = (viewport.y + rectInScreenCoordinates.y) * scaleY / nativeScale;
rectInScreenCoordinates.w = rectInScreenCoordinates.w * scaleX / nativeScale;
rectInScreenCoordinates.h = rectInScreenCoordinates.h * scaleY / nativeScale;
impl(rectInScreenCoordinates);
#else
impl(where);
scaleX /= nativeScale;
scaleY /= nativeScale;
#endif
SDL_Rect rectInScreenCoordinates;
rectInScreenCoordinates.x = (viewport.x + whereInput.x) * scaleX;
rectInScreenCoordinates.y = (viewport.y + whereInput.y) * scaleY;
rectInScreenCoordinates.w = whereInput.w * scaleX;
rectInScreenCoordinates.h = whereInput.h * scaleY;
SDL_SetTextInputRect(&rectInScreenCoordinates);
if (SDL_IsTextInputActive() == SDL_FALSE)
{
SDL_StartTextInput();
}
#ifdef VCMI_APPLE
});
#endif

View File

@ -10,11 +10,13 @@
#import <UIKit/UIKit.h>
#include <SDL_events.h>
NS_ASSUME_NONNULL_BEGIN
@interface GameChatKeyboardHandler : NSObject
- (void)triggerInput;
+ (void)sendKeyEventWithKeyCode:(SDL_KeyCode)keyCode;
@end

View File

@ -10,20 +10,8 @@
#import "GameChatKeyboardHandler.h"
#include <SDL_events.h>
static int watchReturnKey(void * userdata, SDL_Event * event);
static void sendKeyEvent(SDL_KeyCode keyCode)
{
SDL_Event keyEvent;
keyEvent.key = (SDL_KeyboardEvent){
.type = SDL_KEYDOWN,
.keysym.sym = keyCode,
};
SDL_PushEvent(&keyEvent);
}
@interface GameChatKeyboardHandler ()
@property (nonatomic) BOOL wasChatMessageSent;
@ -31,28 +19,40 @@ static void sendKeyEvent(SDL_KeyCode keyCode)
@implementation GameChatKeyboardHandler
- (void)triggerInput {
+ (void)sendKeyEventWithKeyCode:(SDL_KeyCode)keyCode
{
SDL_Event keyEvent;
keyEvent.key = (SDL_KeyboardEvent){
.type = SDL_KEYDOWN,
.state = SDL_PRESSED,
.keysym.sym = keyCode,
};
SDL_PushEvent(&keyEvent);
}
- (instancetype)init {
self = [super init];
__auto_type notificationCenter = NSNotificationCenter.defaultCenter;
[notificationCenter addObserver:self selector:@selector(textDidBeginEditing:) name:UITextFieldTextDidBeginEditingNotification object:nil];
[notificationCenter addObserver:self selector:@selector(textDidEndEditing:) name:UITextFieldTextDidEndEditingNotification object:nil];
self.wasChatMessageSent = NO;
sendKeyEvent(SDLK_TAB);
return self;
}
#pragma mark - Notifications
- (void)textDidBeginEditing:(NSNotification *)n {
self.wasChatMessageSent = NO;
// watch for pressing Return to ignore sending Escape key after keyboard is closed
SDL_AddEventWatch(watchReturnKey, (__bridge void *)self);
}
- (void)textDidEndEditing:(NSNotification *)n {
[NSNotificationCenter.defaultCenter removeObserver:self];
// discard chat message
if(!self.wasChatMessageSent)
sendKeyEvent(SDLK_ESCAPE);
[[self class] sendKeyEventWithKeyCode:SDLK_ESCAPE];
}
@end

View File

@ -95,7 +95,7 @@
- (void)handlePinch:(UIGestureRecognizer *)gesture {
if(gesture.state != UIGestureRecognizerStateBegan || CSH->state != EClientState::GAMEPLAY)
return;
[self.gameChatHandler triggerInput];
[GameChatKeyboardHandler sendKeyEventWithKeyCode:SDLK_SPACE];
}
#pragma mark - UIGestureRecognizerDelegate

View File

@ -177,7 +177,7 @@ void CTerrainRect::mouseMoved(const SDL_MouseMotionEvent & sEvent)
void CTerrainRect::handleSwipeMove(const SDL_MouseMotionEvent & sEvent)
{
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
if(sEvent.state == 0) // any "button" is enough on mobile
if(sEvent.state == 0 || GH.multifinger) // any "button" is enough on mobile
#else
if((sEvent.state & SDL_BUTTON_MMASK) == 0) // swipe only works with middle mouse on other platforms
#endif

View File

@ -101,7 +101,7 @@ void QuickRecruitmentWindow::maxAllCards(std::vector<std::shared_ptr<CreaturePur
void QuickRecruitmentWindow::purchaseUnits()
{
for(auto selected : cards)
for(auto selected : boost::adaptors::reverse(cards))
{
if(selected->slider->getValue())
{

View File

@ -17,7 +17,21 @@
"type" : "object",
"default": {},
"additionalProperties" : false,
"required" : [ "playerName", "showfps", "music", "sound", "encoding", "language", "swipe", "saveRandomMaps", "saveFrequency", "notifications", "extraDump" ],
"required" : [
"playerName",
"showfps",
"music",
"sound",
"encoding",
"language",
"swipe",
"saveRandomMaps",
"saveFrequency",
"notifications",
"extraDump",
"userRelativePointer",
"relativePointerSpeedMultiplier"
],
"properties" : {
"playerName" : {
"type":"string",
@ -75,6 +89,14 @@
"extraDump" : {
"type" : "boolean",
"default" : false
},
"userRelativePointer" : {
"type" : "boolean",
"default" : false
},
"relativePointerSpeedMultiplier" : {
"type" : "number",
"default" : 1
}
}
},

View File

@ -1,9 +0,0 @@
#!/usr/bin/env bash
generatedZip="$1"
if [[ -z "$generatedZip" ]]; then
echo 'generated zip not provided as param'
exit 1
fi
mv "$generatedZip" "$(basename "$generatedZip" .zip).ipa"

View File

@ -96,7 +96,7 @@ jclass CAndroidVMHelper::findClass(const std::string & name, bool classloaded)
return get()->FindClass(name.c_str());
}
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_initClassloader(JNIEnv * baseEnv, jobject * cls)
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_initClassloader(JNIEnv * baseEnv, jclass cls)
{
CAndroidVMHelper::cacheVM(baseEnv);
CAndroidVMHelper envHelper;

View File

@ -1583,7 +1583,7 @@ bool NBonus::hasOfType(const CBonusSystemNode *obj, Bonus::BonusType type, int s
return false;
}
std::string Bonus::Description() const
std::string Bonus::Description(boost::optional<si32> customValue) const
{
std::ostringstream str;
@ -1622,8 +1622,8 @@ std::string Bonus::Description() const
str << description;
}
if(val != 0)
str << " " << std::showpos << val;
if(auto value = customValue.value_or(val))
str << " " << std::showpos << value;
return str.str();
}

View File

@ -510,7 +510,7 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
return (high << 16) + low;
}
std::string Description() const;
std::string Description(boost::optional<si32> customValue = {}) const;
JsonNode toJsonNode() const;
std::string nameForBonus() const; // generate suitable name for bonus - e.g. for storing in json struct

View File

@ -554,24 +554,26 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
if(hasBuilt(BuildingID::HORDE_2))
ret.entries.push_back(GrowthInfo::Entry(subID, BuildingID::HORDE_2, creature->hordeGrowth));
int dwellingBonus = 0;
if(const PlayerState *p = cb->getPlayerState(tempOwner, false))
//statue-of-legion-like bonus: % to base+castle
TConstBonusListPtr bonuses2 = getBonuses(Selector::type()(Bonus::CREATURE_GROWTH_PERCENT));
for(const auto & b : *bonuses2)
{
dwellingBonus = getDwellingBonus(creatures[level].second, p->dwellings);
const auto growth = b->val * (base + castleBonus) / 100;
ret.entries.push_back(GrowthInfo::Entry(growth, b->Description(growth)));
}
if(dwellingBonus)
ret.entries.push_back(GrowthInfo::Entry(VLC->generaltexth->allTexts[591], dwellingBonus));// \nExternal dwellings %+d
//other *-of-legion-like bonuses (%d to growth cumulative with grail)
TConstBonusListPtr bonuses = getBonuses(Selector::type()(Bonus::CREATURE_GROWTH).And(Selector::subtype()(level)));
for(const auto & b : *bonuses)
ret.entries.push_back(GrowthInfo::Entry(b->val, b->Description()));
//statue-of-legion-like bonus: % to base+castle
TConstBonusListPtr bonuses2 = getBonuses(Selector::type()(Bonus::CREATURE_GROWTH_PERCENT));
for(const auto & b : *bonuses2)
ret.entries.push_back(GrowthInfo::Entry(b->val * (base + castleBonus) / 100, b->Description()));
int dwellingBonus = 0;
if(const PlayerState *p = cb->getPlayerState(tempOwner, false))
{
dwellingBonus = getDwellingBonus(creatures[level].second, p->dwellings);
}
if(dwellingBonus)
ret.entries.push_back(GrowthInfo::Entry(VLC->generaltexth->allTexts[591], dwellingBonus));// \nExternal dwellings %+d
if(hasBuilt(BuildingID::GRAIL)) //grail - +50% to ALL (so far added) growth
ret.entries.push_back(GrowthInfo::Entry(subID, BuildingID::GRAIL, ret.totalGrowth() / 2));

View File

@ -1326,10 +1326,10 @@ std::string CMapSaverJson::writeTerrainTile(const TerrainTile & tile)
out << tile.terType->shortIdentifier << (int)tile.terView << flipCodes[tile.extTileFlags % 4];
if(tile.roadType->getId() != Road::NO_ROAD)
out << tile.roadType << (int)tile.roadDir << flipCodes[(tile.extTileFlags >> 4) % 4];
out << tile.roadType->shortIdentifier << (int)tile.roadDir << flipCodes[(tile.extTileFlags >> 4) % 4];
if(tile.riverType->getId() != River::NO_RIVER)
out << tile.riverType << (int)tile.riverDir << flipCodes[(tile.extTileFlags >> 2) % 4];
out << tile.riverType->shortIdentifier << (int)tile.riverDir << flipCodes[(tile.extTileFlags >> 2) % 4];
return out.str();
}

View File

@ -28,6 +28,8 @@
#include "../lib/mapping/CMap.h"
#include "../lib/rmg/CMapGenOptions.h"
#ifdef VCMI_ANDROID
#include <jni.h>
#include <android/log.h>
#include "lib/CAndroidVMHelper.h"
#elif !defined(VCMI_IOS)
#include "../lib/Interprocess.h"
@ -1122,12 +1124,21 @@ int main(int argc, char * argv[])
}
#ifdef VCMI_ANDROID
extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_createServer(JNIEnv * env, jclass cls)
{
__android_log_write(ANDROID_LOG_INFO, "VCMI", "Got jni call to init server");
CAndroidVMHelper::cacheVM(env);
CVCMIServer::create();
}
void CVCMIServer::create()
{
const char * foo = "android-server";
std::vector<const void *> argv = {foo};
main(argv.size(), reinterpret_cast<char **>(const_cast<void **>(&*argv.begin())));
}
#elif defined(SINGLE_PROCESS_APP)
void CVCMIServer::create(boost::condition_variable * cond, const std::vector<std::string> & args)
{