Compare commits
15 Commits
0.6.1-alph
...
969d6b3ee7
| Author | SHA1 | Date | |
|---|---|---|---|
| 969d6b3ee7 | |||
| b0de432339 | |||
| 6f7812293e | |||
| 37e28d0fcc | |||
| 954ec6e505 | |||
| b1cd6c6581 | |||
| 248e9cb69a | |||
| caedc293eb | |||
| 2e9a9b810c | |||
| ce4c3e9d93 | |||
| 470509ee52 | |||
| 0ea8b87970 | |||
| b4f54083dc | |||
| f17a11c670 | |||
| adb23d18c6 |
31
README.md
31
README.md
@@ -32,6 +32,12 @@ mkdir build && cd build
|
|||||||
cmake .. -B .
|
cmake .. -B .
|
||||||
make -j4
|
make -j4
|
||||||
```
|
```
|
||||||
|
or
|
||||||
|
```
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake --build . --config Release -j 10
|
||||||
|
```
|
||||||
|
|
||||||
## Visual Studio
|
## Visual Studio
|
||||||
|
|
||||||
1. Open the repository folder in **Visual Studio**.
|
1. Open the repository folder in **Visual Studio**.
|
||||||
@@ -40,17 +46,28 @@ make -j4
|
|||||||
4. Press **Run** (or F5) to build and launch the game.
|
4. Press **Run** (or F5) to build and launch the game.
|
||||||
|
|
||||||
## Android
|
## Android
|
||||||
Download [r14b Android NDK](http://dl.google.com/android/repository/android-ndk-r14b-windows-x86_64.zip) and run `build.ps1`:
|
|
||||||
```
|
1. Download **Android NDK r14b**:
|
||||||
|
http://dl.google.com/android/repository/android-ndk-r14b-windows-x86_64.zip
|
||||||
|
|
||||||
|
2. Extract it to the root of your `C:` drive so the path becomes:
|
||||||
|
|
||||||
|
```
|
||||||
|
C:\android-ndk-r14b
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run the build script:
|
||||||
|
|
||||||
|
```powershell
|
||||||
# Full build (NDK + Java + APK + install)
|
# Full build (NDK + Java + APK + install)
|
||||||
.\build.ps1
|
.\build.ps1
|
||||||
|
|
||||||
# Skip NDK recompile (Java/assets changed only)
|
# Skip C++ compilation (Java/assets changed only)
|
||||||
.\build.ps1 -NoJava
|
|
||||||
|
|
||||||
# Skip Java recompile (C++ changed only)
|
|
||||||
.\build.ps1 -NoCpp
|
.\build.ps1 -NoCpp
|
||||||
|
|
||||||
# Only repackage + install (no recompile at all)
|
# Skip Java compilation (C++ changed only)
|
||||||
|
.\build.ps1 -NoJava
|
||||||
|
|
||||||
|
# Only repackage + install (no compilation)
|
||||||
.\build.ps1 -NoBuild
|
.\build.ps1 -NoBuild
|
||||||
```
|
```
|
||||||
@@ -155,5 +155,5 @@ set(CompileFiles ../../src/main.cpp
|
|||||||
add_executable(mcpe_server ${CompileFiles})
|
add_executable(mcpe_server ${CompileFiles})
|
||||||
target_link_libraries(mcpe_server raknet ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(mcpe_server raknet ${CMAKE_THREAD_LIBS_INIT})
|
||||||
target_include_directories(mcpe_server PUBLIC
|
target_include_directories(mcpe_server PUBLIC
|
||||||
"minecraft-pe-0.6.1/src/"
|
"../../src/"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#if defined(RPI)
|
#if defined(RPI)
|
||||||
#define CREATORMODE
|
#define CREATORMODE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../network/RakNetInstance.h"
|
#include "../network/RakNetInstance.h"
|
||||||
#include "../network/ClientSideNetworkHandler.h"
|
#include "../network/ClientSideNetworkHandler.h"
|
||||||
#include "../network/ServerSideNetworkHandler.h"
|
#include "../network/ServerSideNetworkHandler.h"
|
||||||
@@ -113,7 +112,7 @@ static void checkGlError(const char* tag) {
|
|||||||
}
|
}
|
||||||
#endif /*GLDEBUG*/
|
#endif /*GLDEBUG*/
|
||||||
}
|
}
|
||||||
|
#include <fstream>
|
||||||
/*static*/
|
/*static*/
|
||||||
const char* Minecraft::progressMessages[] = {
|
const char* Minecraft::progressMessages[] = {
|
||||||
"Locating server",
|
"Locating server",
|
||||||
@@ -451,20 +450,21 @@ void Minecraft::update() {
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if (pause && level != NULL) {
|
// If we're paused (local world / invisible server), freeze gameplay and
|
||||||
float lastA = timer.a;
|
// networking and only keep UI responsive.
|
||||||
timer.advanceTime();
|
bool freezeGame = pause;
|
||||||
timer.a = lastA;
|
|
||||||
} else {
|
if (!freezeGame) {
|
||||||
timer.advanceTime();
|
timer.advanceTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (raknetInstance) {
|
if (raknetInstance && !freezeGame) {
|
||||||
raknetInstance->runEvents(netCallback);
|
raknetInstance->runEvents(netCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
TIMER_PUSH("tick");
|
TIMER_PUSH("tick");
|
||||||
int toTick = timer.ticks;
|
int toTick = freezeGame ? 1 : timer.ticks;
|
||||||
|
if (!freezeGame) timer.ticks = 0;
|
||||||
for (int i = 0; i < toTick; ++i, ++ticks)
|
for (int i = 0; i < toTick; ++i, ++ticks)
|
||||||
tick(i, toTick-1);
|
tick(i, toTick-1);
|
||||||
|
|
||||||
@@ -589,7 +589,9 @@ void Minecraft::tick(int nTick, int maxTick) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
TIMER_POP_PUSH("particles");
|
TIMER_POP_PUSH("particles");
|
||||||
particleEngine->tick();
|
if (!pause) {
|
||||||
|
particleEngine->tick();
|
||||||
|
}
|
||||||
if (screen) {
|
if (screen) {
|
||||||
screenMutex = true;
|
screenMutex = true;
|
||||||
screen->tick();
|
screen->tick();
|
||||||
@@ -1018,6 +1020,17 @@ bool Minecraft::isOnline()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Minecraft::pauseGame(bool isBackPaused) {
|
void Minecraft::pauseGame(bool isBackPaused) {
|
||||||
|
// Only freeze gameplay when running a local server and it is not accepting
|
||||||
|
// incoming connections (invisible server), which includes typical single-
|
||||||
|
// player/lobby mode. If the server is visible, the game should keep ticking.
|
||||||
|
bool canFreeze = false;
|
||||||
|
if (raknetInstance && raknetInstance->isServer() && netCallback) {
|
||||||
|
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) netCallback;
|
||||||
|
if (!ss->allowsIncomingConnections())
|
||||||
|
canFreeze = true;
|
||||||
|
}
|
||||||
|
pause = canFreeze;
|
||||||
|
|
||||||
#ifndef STANDALONE_SERVER
|
#ifndef STANDALONE_SERVER
|
||||||
if (screen != NULL) return;
|
if (screen != NULL) return;
|
||||||
screenChooser.setScreen(isBackPaused? SCREEN_PAUSEPREV : SCREEN_PAUSE);
|
screenChooser.setScreen(isBackPaused? SCREEN_PAUSEPREV : SCREEN_PAUSE);
|
||||||
@@ -1070,6 +1083,8 @@ void Minecraft::setScreen( Screen* screen )
|
|||||||
|
|
||||||
//noRender = false;
|
//noRender = false;
|
||||||
} else {
|
} else {
|
||||||
|
// Closing a screen and returning to the game should unpause.
|
||||||
|
pause = false;
|
||||||
grabMouse();
|
grabMouse();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1112,6 +1127,7 @@ void Minecraft::init()
|
|||||||
{
|
{
|
||||||
options.minecraft = this;
|
options.minecraft = this;
|
||||||
options.initDefaultValues();
|
options.initDefaultValues();
|
||||||
|
|
||||||
#ifndef STANDALONE_SERVER
|
#ifndef STANDALONE_SERVER
|
||||||
checkGlError("Init enter");
|
checkGlError("Init enter");
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,21 @@ const char* OptionStrings::Multiplayer_ServerVisible = "mp_server_visible_defa
|
|||||||
const char* OptionStrings::Graphics_Fancy = "gfx_fancygraphics";
|
const char* OptionStrings::Graphics_Fancy = "gfx_fancygraphics";
|
||||||
const char* OptionStrings::Graphics_LowQuality = "gfx_lowquality";
|
const char* OptionStrings::Graphics_LowQuality = "gfx_lowquality";
|
||||||
const char* OptionStrings::Graphics_Vsync = "gfx_vsync";
|
const char* OptionStrings::Graphics_Vsync = "gfx_vsync";
|
||||||
const char* OptionStrings::Graphics_GUIScale = "gfx_guiscale";
|
const char* OptionStrings::Graphics_GUIScale = "gfx_guiscale";
|
||||||
|
const char* OptionStrings::Graphics_SmoothLightning = "gfx_smoothlightning";
|
||||||
|
const char* OptionStrings::Graphics_Anaglyph = "gfx_anaglyph";
|
||||||
|
const char* OptionStrings::Graphics_ViewBobbing = "gfx_viewbobbing";
|
||||||
|
|
||||||
const char* OptionStrings::Controls_Sensitivity = "ctrl_sensitivity";
|
const char* OptionStrings::Controls_Sensitivity = "ctrl_sensitivity";
|
||||||
const char* OptionStrings::Controls_InvertMouse = "ctrl_invertmouse";
|
const char* OptionStrings::Controls_InvertMouse = "ctrl_invertmouse";
|
||||||
const char* OptionStrings::Controls_UseTouchScreen = "ctrl_usetouchscreen";
|
const char* OptionStrings::Controls_UseTouchScreen = "ctrl_usetouchscreen";
|
||||||
const char* OptionStrings::Controls_UseTouchJoypad = "ctrl_usetouchjoypad";
|
const char* OptionStrings::Controls_UseTouchJoypad = "ctrl_usetouchjoypad";
|
||||||
const char* OptionStrings::Controls_IsLefthanded = "ctrl_islefthanded";
|
const char* OptionStrings::Controls_IsLefthanded = "ctrl_islefthanded";
|
||||||
|
// why it isnt ctrl_feedback_vibration? i dont want touch it because compatibility with older versions
|
||||||
const char* OptionStrings::Controls_FeedbackVibration = "feedback_vibration";
|
const char* OptionStrings::Controls_FeedbackVibration = "feedback_vibration";
|
||||||
|
|
||||||
const char* OptionStrings::Game_DifficultyLevel = "game_difficulty";
|
const char* OptionStrings::Audio_Music = "audio_music";
|
||||||
|
const char* OptionStrings::Audio_Sound = "audio_sound";
|
||||||
|
|
||||||
|
const char* OptionStrings::Game_DifficultyLevel = "game_difficulty";
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ public:
|
|||||||
static const char* Graphics_LowQuality;
|
static const char* Graphics_LowQuality;
|
||||||
static const char* Graphics_GUIScale;
|
static const char* Graphics_GUIScale;
|
||||||
static const char* Graphics_Vsync;
|
static const char* Graphics_Vsync;
|
||||||
|
static const char* Graphics_SmoothLightning;
|
||||||
|
static const char* Graphics_Anaglyph;
|
||||||
|
static const char* Graphics_ViewBobbing;
|
||||||
|
|
||||||
static const char* Controls_Sensitivity;
|
static const char* Controls_Sensitivity;
|
||||||
static const char* Controls_InvertMouse;
|
static const char* Controls_InvertMouse;
|
||||||
static const char* Controls_UseTouchScreen;
|
static const char* Controls_UseTouchScreen;
|
||||||
@@ -17,7 +21,12 @@ public:
|
|||||||
static const char* Controls_IsLefthanded;
|
static const char* Controls_IsLefthanded;
|
||||||
static const char* Controls_FeedbackVibration;
|
static const char* Controls_FeedbackVibration;
|
||||||
|
|
||||||
|
static const char* Audio_Music;
|
||||||
|
static const char* Audio_Sound;
|
||||||
|
|
||||||
|
|
||||||
static const char* Game_DifficultyLevel;
|
static const char* Game_DifficultyLevel;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*NET_MINECRAFT_CLIENT__OptionsStrings_H__*/
|
#endif /*NET_MINECRAFT_CLIENT__OptionsStrings_H__*/
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ const Options::Option
|
|||||||
Options::Option::ANAGLYPH (6, "options.anaglyph", false, true),
|
Options::Option::ANAGLYPH (6, "options.anaglyph", false, true),
|
||||||
Options::Option::LIMIT_FRAMERATE (7, "options.limitFramerate",false, true),
|
Options::Option::LIMIT_FRAMERATE (7, "options.limitFramerate",false, true),
|
||||||
Options::Option::DIFFICULTY (8, "options.difficulty", false, false),
|
Options::Option::DIFFICULTY (8, "options.difficulty", false, false),
|
||||||
Options::Option::GRAPHICS (9, "options.graphics", false, false),
|
Options::Option::GRAPHICS (9, "options.graphics", false, true),
|
||||||
Options::Option::AMBIENT_OCCLUSION (10, "options.ao", false, true),
|
Options::Option::AMBIENT_OCCLUSION (10, "options.ao", false, true),
|
||||||
Options::Option::GUI_SCALE (11, "options.guiScale", false, false),
|
Options::Option::GUI_SCALE (11, "options.guiScale", false, false),
|
||||||
Options::Option::THIRD_PERSON (12, "options.thirdperson", false, true),
|
Options::Option::THIRD_PERSON (12, "options.thirdperson", false, true),
|
||||||
@@ -207,7 +207,7 @@ void Options::update()
|
|||||||
if (readFloat(value, sens)) {
|
if (readFloat(value, sens)) {
|
||||||
// sens is in range [0,1] with default/center at 0.5 (for aesthetics)
|
// sens is in range [0,1] with default/center at 0.5 (for aesthetics)
|
||||||
// We wanna map it to something like [0.3, 0.9] BUT keep 0.5 @ ~0.5...
|
// We wanna map it to something like [0.3, 0.9] BUT keep 0.5 @ ~0.5...
|
||||||
sensitivity = 0.3f + std::pow(1.1f * sens, 1.3f) * 0.42f;
|
sensitivity = sens;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key == OptionStrings::Controls_InvertMouse) {
|
if (key == OptionStrings::Controls_InvertMouse) {
|
||||||
@@ -238,13 +238,29 @@ void Options::update()
|
|||||||
fancyGraphics = false;
|
fancyGraphics = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (key == OptionStrings::Graphics_SmoothLightning) {
|
||||||
|
bool isLow;
|
||||||
|
readBool(value, ambientOcclusion);
|
||||||
|
}
|
||||||
|
|
||||||
// Graphics extras
|
// Graphics extras
|
||||||
if (key == OptionStrings::Graphics_Vsync)
|
if (key == OptionStrings::Graphics_Vsync)
|
||||||
readBool(value, vsync);
|
readBool(value, vsync);
|
||||||
|
if (key == OptionStrings::Graphics_Anaglyph)
|
||||||
|
readBool(value, anaglyph3d);
|
||||||
|
if (key == OptionStrings::Graphics_ViewBobbing)
|
||||||
|
readBool(value, bobView);
|
||||||
if (key == OptionStrings::Graphics_GUIScale) {
|
if (key == OptionStrings::Graphics_GUIScale) {
|
||||||
int v;
|
int v;
|
||||||
if (readInt(value, v)) guiScale = v % 5;
|
if (readInt(value, v)) guiScale = v % 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Audio
|
||||||
|
if (key == OptionStrings::Audio_Music)
|
||||||
|
readFloat(value, music);
|
||||||
|
if (key == OptionStrings::Audio_Sound)
|
||||||
|
readFloat(value, sound);
|
||||||
|
|
||||||
// Game
|
// Game
|
||||||
if (key == OptionStrings::Game_DifficultyLevel) {
|
if (key == OptionStrings::Game_DifficultyLevel) {
|
||||||
readInt(value, difficulty);
|
readInt(value, difficulty);
|
||||||
@@ -304,12 +320,12 @@ void Options::load()
|
|||||||
void Options::save()
|
void Options::save()
|
||||||
{
|
{
|
||||||
StringVector stringVec;
|
StringVector stringVec;
|
||||||
|
|
||||||
// Login
|
// Login
|
||||||
addOptionToSaveOutput(stringVec, OptionStrings::Multiplayer_Username, username);
|
addOptionToSaveOutput(stringVec, OptionStrings::Multiplayer_Username, username);
|
||||||
// Game
|
// Game
|
||||||
addOptionToSaveOutput(stringVec, OptionStrings::Multiplayer_ServerVisible, serverVisible);
|
addOptionToSaveOutput(stringVec, OptionStrings::Multiplayer_ServerVisible, serverVisible);
|
||||||
addOptionToSaveOutput(stringVec, OptionStrings::Game_DifficultyLevel, difficulty);
|
addOptionToSaveOutput(stringVec, OptionStrings::Game_DifficultyLevel, difficulty);
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
addOptionToSaveOutput(stringVec, OptionStrings::Controls_InvertMouse, invertYMouse);
|
addOptionToSaveOutput(stringVec, OptionStrings::Controls_InvertMouse, invertYMouse);
|
||||||
addOptionToSaveOutput(stringVec, OptionStrings::Controls_Sensitivity, sensitivity);
|
addOptionToSaveOutput(stringVec, OptionStrings::Controls_Sensitivity, sensitivity);
|
||||||
@@ -317,8 +333,20 @@ void Options::save()
|
|||||||
addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchScreen, useTouchScreen);
|
addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchScreen, useTouchScreen);
|
||||||
addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchJoypad, isJoyTouchArea);
|
addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchJoypad, isJoyTouchArea);
|
||||||
addOptionToSaveOutput(stringVec, OptionStrings::Controls_FeedbackVibration, destroyVibration);
|
addOptionToSaveOutput(stringVec, OptionStrings::Controls_FeedbackVibration, destroyVibration);
|
||||||
|
// Graphics
|
||||||
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_Vsync, vsync);
|
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_Vsync, vsync);
|
||||||
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_GUIScale, guiScale);
|
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_GUIScale, guiScale);
|
||||||
|
addOptionToSaveOutput(stringVec, OptionStrings::Game_DifficultyLevel, difficulty);
|
||||||
|
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_Fancy, fancyGraphics);
|
||||||
|
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_SmoothLightning, ambientOcclusion);
|
||||||
|
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_Anaglyph, anaglyph3d);
|
||||||
|
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_ViewBobbing, bobView);
|
||||||
|
|
||||||
|
//addOptionToSaveOutput(stringVec, OptionStrings::VIEW_BOBBING, fancyGraphics);
|
||||||
|
// Audio
|
||||||
|
addOptionToSaveOutput(stringVec, OptionStrings::Audio_Music, music);
|
||||||
|
addOptionToSaveOutput(stringVec, OptionStrings::Audio_Sound, sound);
|
||||||
|
|
||||||
//
|
//
|
||||||
// static const Option MUSIC;
|
// static const Option MUSIC;
|
||||||
// static const Option SOUND;
|
// static const Option SOUND;
|
||||||
|
|||||||
@@ -275,6 +275,8 @@ public:
|
|||||||
return limitFramerate;
|
return limitFramerate;
|
||||||
if (item == &Option::VSYNC)
|
if (item == &Option::VSYNC)
|
||||||
return vsync;
|
return vsync;
|
||||||
|
if (item == &Option::GRAPHICS)
|
||||||
|
return fancyGraphics;
|
||||||
if (item == &Option::AMBIENT_OCCLUSION)
|
if (item == &Option::AMBIENT_OCCLUSION)
|
||||||
return ambientOcclusion;
|
return ambientOcclusion;
|
||||||
if (item == &Option::THIRD_PERSON)
|
if (item == &Option::THIRD_PERSON)
|
||||||
|
|||||||
@@ -78,6 +78,14 @@ void Screen::updateEvents()
|
|||||||
void Screen::mouseEvent()
|
void Screen::mouseEvent()
|
||||||
{
|
{
|
||||||
const MouseAction& e = Mouse::getEvent();
|
const MouseAction& e = Mouse::getEvent();
|
||||||
|
// forward wheel events to subclasses
|
||||||
|
if (e.action == MouseAction::ACTION_WHEEL) {
|
||||||
|
int xm = e.x * width / minecraft->width;
|
||||||
|
int ym = e.y * height / minecraft->height - 1;
|
||||||
|
mouseWheel(e.dx, e.dy, xm, ym);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!e.isButton())
|
if (!e.isButton())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ protected:
|
|||||||
virtual void mouseClicked(int x, int y, int buttonNum);
|
virtual void mouseClicked(int x, int y, int buttonNum);
|
||||||
virtual void mouseReleased(int x, int y, int buttonNum);
|
virtual void mouseReleased(int x, int y, int buttonNum);
|
||||||
|
|
||||||
|
// mouse wheel movement (dx/dy are wheel deltas, xm/ym are GUI coords)
|
||||||
|
virtual void mouseWheel(int dx, int dy, int xm, int ym) {}
|
||||||
|
|
||||||
virtual void keyPressed(int eventKey);
|
virtual void keyPressed(int eventKey);
|
||||||
virtual void keyboardNewChar(char inputChar) {}
|
virtual void keyboardNewChar(char inputChar) {}
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -548,6 +548,14 @@ void ScrollingPane::stepThroughDecelerationAnimation(bool noAnimation) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScrollingPane::scrollBy(float dx, float dy) {
|
||||||
|
// adjust the translation offsets fpx/fpy by the requested amount
|
||||||
|
float nfpx = fpx + dx;
|
||||||
|
float nfpy = fpy + dy;
|
||||||
|
// convert back to content offset (fpx = -contentOffset.x)
|
||||||
|
setContentOffset(Vec3(-nfpx, -nfpy, 0));
|
||||||
|
}
|
||||||
|
|
||||||
void ScrollingPane::setContentOffset(float x, float y) {
|
void ScrollingPane::setContentOffset(float x, float y) {
|
||||||
this->setContentOffsetWithAnimation(Vec3(x, y, 0), false);
|
this->setContentOffsetWithAnimation(Vec3(x, y, 0), false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ public:
|
|||||||
void tick();
|
void tick();
|
||||||
void render(int xm, int ym, float alpha);
|
void render(int xm, int ym, float alpha);
|
||||||
|
|
||||||
|
// scroll the content by the given amount (dx horizontal, dy vertical)
|
||||||
|
// positive values move content downward/rightward
|
||||||
|
void scrollBy(float dx, float dy);
|
||||||
|
|
||||||
bool getGridItemFor_slow(int itemIndex, GridItem& out);
|
bool getGridItemFor_slow(int itemIndex, GridItem& out);
|
||||||
|
|
||||||
void setSelected(int id, bool selected);
|
void setSelected(int id, bool selected);
|
||||||
|
|||||||
@@ -202,6 +202,25 @@ void IngameBlockSelectionScreen::keyPressed(int eventKey)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// wheel support for creative inventory; scroll moves selection vertically
|
||||||
|
void IngameBlockSelectionScreen::mouseWheel(int dx, int dy, int xm, int ym)
|
||||||
|
{
|
||||||
|
if (dy == 0) return;
|
||||||
|
// just move selection up/down one row; desktop UI doesn't have a pane
|
||||||
|
int cols = InventoryCols;
|
||||||
|
int maxIndex = InventorySize - 1;
|
||||||
|
int idx = selectedItem;
|
||||||
|
if (dy > 0) {
|
||||||
|
// wheel up -> previous row
|
||||||
|
if (idx >= cols) idx -= cols;
|
||||||
|
} else {
|
||||||
|
// wheel down -> next row
|
||||||
|
if (idx + cols <= maxIndex) idx += cols;
|
||||||
|
}
|
||||||
|
selectedItem = idx;
|
||||||
|
}
|
||||||
|
|
||||||
int IngameBlockSelectionScreen::getSelectedSlot(int x, int y)
|
int IngameBlockSelectionScreen::getSelectedSlot(int x, int y)
|
||||||
{
|
{
|
||||||
int left = width / 2 - InventoryCols * 10;
|
int left = width / 2 - InventoryCols * 10;
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ protected:
|
|||||||
|
|
||||||
virtual void buttonClicked(Button* button);
|
virtual void buttonClicked(Button* button);
|
||||||
|
|
||||||
|
// wheel input for creative inventory scrolling
|
||||||
|
virtual void mouseWheel(int dx, int dy, int xm, int ym) override;
|
||||||
|
|
||||||
virtual void keyPressed(int eventKey);
|
virtual void keyPressed(int eventKey);
|
||||||
private:
|
private:
|
||||||
void renderSlots();
|
void renderSlots();
|
||||||
|
|||||||
@@ -243,7 +243,6 @@ void OptionsScreen::generateOptionScreens() {
|
|||||||
.addOptionItem(&Options::Option::VIEW_BOBBING, minecraft)
|
.addOptionItem(&Options::Option::VIEW_BOBBING, minecraft)
|
||||||
.addOptionItem(&Options::Option::AMBIENT_OCCLUSION, minecraft)
|
.addOptionItem(&Options::Option::AMBIENT_OCCLUSION, minecraft)
|
||||||
.addOptionItem(&Options::Option::ANAGLYPH, minecraft)
|
.addOptionItem(&Options::Option::ANAGLYPH, minecraft)
|
||||||
.addOptionItem(&Options::Option::LIMIT_FRAMERATE, minecraft)
|
|
||||||
.addOptionItem(&Options::Option::VSYNC, minecraft)
|
.addOptionItem(&Options::Option::VSYNC, minecraft)
|
||||||
.addOptionItem(&Options::Option::MUSIC, minecraft)
|
.addOptionItem(&Options::Option::MUSIC, minecraft)
|
||||||
.addOptionItem(&Options::Option::SOUND, minecraft);
|
.addOptionItem(&Options::Option::SOUND, minecraft);
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ void SelectWorldScreen::render( int xm, int ym, float a )
|
|||||||
worldsList->setComponentSelected(bWorldView.selected);
|
worldsList->setComponentSelected(bWorldView.selected);
|
||||||
// #ifdef PLATFORM_DESKTOP
|
// #ifdef PLATFORM_DESKTOP
|
||||||
|
|
||||||
// We should add scrolling with mouse wheel but currently i dont know how to implement it
|
// desktop: render the list normally (mouse wheel handled separately below)
|
||||||
if (_mouseHasBeenUp)
|
if (_mouseHasBeenUp)
|
||||||
worldsList->render(xm, ym, a);
|
worldsList->render(xm, ym, a);
|
||||||
else {
|
else {
|
||||||
@@ -412,6 +412,28 @@ std::string SelectWorldScreen::getUniqueLevelName( const std::string& level )
|
|||||||
|
|
||||||
bool SelectWorldScreen::isInGameScreen() { return true; }
|
bool SelectWorldScreen::isInGameScreen() { return true; }
|
||||||
|
|
||||||
|
void SelectWorldScreen::mouseWheel(int dx, int dy, int xm, int ym)
|
||||||
|
{
|
||||||
|
if (!worldsList)
|
||||||
|
return;
|
||||||
|
if (dy == 0)
|
||||||
|
return;
|
||||||
|
int num = worldsList->getNumberOfItems();
|
||||||
|
int idx = worldsList->selectedItem;
|
||||||
|
if (dy > 0) {
|
||||||
|
if (idx > 0) {
|
||||||
|
idx--;
|
||||||
|
worldsList->stepLeft();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (idx < num - 1) {
|
||||||
|
idx++;
|
||||||
|
worldsList->stepRight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
worldsList->selectedItem = idx;
|
||||||
|
}
|
||||||
|
|
||||||
void SelectWorldScreen::keyPressed( int eventKey )
|
void SelectWorldScreen::keyPressed( int eventKey )
|
||||||
{
|
{
|
||||||
if (bWorldView.selected) {
|
if (bWorldView.selected) {
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ public:
|
|||||||
|
|
||||||
void render(int xm, int ym, float a);
|
void render(int xm, int ym, float a);
|
||||||
|
|
||||||
|
// mouse wheel scroll (new in desktop implementation)
|
||||||
|
virtual void mouseWheel(int dx, int dy, int xm, int ym);
|
||||||
|
|
||||||
bool isInGameScreen();
|
bool isInGameScreen();
|
||||||
private:
|
private:
|
||||||
void loadLevelSource();
|
void loadLevelSource();
|
||||||
|
|||||||
@@ -12,11 +12,13 @@
|
|||||||
SimpleChooseLevelScreen::SimpleChooseLevelScreen(const std::string& levelName)
|
SimpleChooseLevelScreen::SimpleChooseLevelScreen(const std::string& levelName)
|
||||||
: bHeader(0),
|
: bHeader(0),
|
||||||
bGamemode(0),
|
bGamemode(0),
|
||||||
|
bCheats(0),
|
||||||
bBack(0),
|
bBack(0),
|
||||||
bCreate(0),
|
bCreate(0),
|
||||||
levelName(levelName),
|
levelName(levelName),
|
||||||
hasChosen(false),
|
hasChosen(false),
|
||||||
gamemode(GameType::Survival),
|
gamemode(GameType::Survival),
|
||||||
|
cheatsEnabled(false),
|
||||||
tLevelName(0, "World name"),
|
tLevelName(0, "World name"),
|
||||||
tSeed(1, "World seed")
|
tSeed(1, "World seed")
|
||||||
{
|
{
|
||||||
@@ -26,12 +28,20 @@ SimpleChooseLevelScreen::~SimpleChooseLevelScreen()
|
|||||||
{
|
{
|
||||||
if (bHeader) delete bHeader;
|
if (bHeader) delete bHeader;
|
||||||
delete bGamemode;
|
delete bGamemode;
|
||||||
|
delete bCheats;
|
||||||
delete bBack;
|
delete bBack;
|
||||||
delete bCreate;
|
delete bCreate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleChooseLevelScreen::init()
|
void SimpleChooseLevelScreen::init()
|
||||||
{
|
{
|
||||||
|
// make sure the base class loads the existing level list; the
|
||||||
|
// derived screen uses ChooseLevelScreen::getUniqueLevelName(), which
|
||||||
|
// depends on `levels` being populated. omitting this used to result
|
||||||
|
// in duplicate IDs ("creating the second world would load the
|
||||||
|
// first") when the name already existed.
|
||||||
|
ChooseLevelScreen::init();
|
||||||
|
|
||||||
tLevelName.text = "New world";
|
tLevelName.text = "New world";
|
||||||
|
|
||||||
// header + close button
|
// header + close button
|
||||||
@@ -48,18 +58,22 @@ void SimpleChooseLevelScreen::init()
|
|||||||
}
|
}
|
||||||
if (minecraft->useTouchscreen()) {
|
if (minecraft->useTouchscreen()) {
|
||||||
bGamemode = new Touch::TButton(1, "Survival mode");
|
bGamemode = new Touch::TButton(1, "Survival mode");
|
||||||
|
bCheats = new Touch::TButton(4, "Cheats: Off");
|
||||||
bCreate = new Touch::TButton(3, "Create");
|
bCreate = new Touch::TButton(3, "Create");
|
||||||
} else {
|
} else {
|
||||||
bGamemode = new Button(1, "Survival mode");
|
bGamemode = new Button(1, "Survival mode");
|
||||||
|
bCheats = new Button(4, "Cheats: Off");
|
||||||
bCreate = new Button(3, "Create");
|
bCreate = new Button(3, "Create");
|
||||||
}
|
}
|
||||||
|
|
||||||
buttons.push_back(bHeader);
|
buttons.push_back(bHeader);
|
||||||
buttons.push_back(bBack);
|
buttons.push_back(bBack);
|
||||||
buttons.push_back(bGamemode);
|
buttons.push_back(bGamemode);
|
||||||
|
buttons.push_back(bCheats);
|
||||||
buttons.push_back(bCreate);
|
buttons.push_back(bCreate);
|
||||||
|
|
||||||
tabButtons.push_back(bGamemode);
|
tabButtons.push_back(bGamemode);
|
||||||
|
tabButtons.push_back(bCheats);
|
||||||
tabButtons.push_back(bBack);
|
tabButtons.push_back(bBack);
|
||||||
tabButtons.push_back(bCreate);
|
tabButtons.push_back(bCreate);
|
||||||
|
|
||||||
@@ -94,16 +108,26 @@ void SimpleChooseLevelScreen::setupPositions()
|
|||||||
tSeed.x = tLevelName.x;
|
tSeed.x = tLevelName.x;
|
||||||
tSeed.y = tLevelName.y + 30;
|
tSeed.y = tLevelName.y + 30;
|
||||||
|
|
||||||
bGamemode->width = 140;
|
const int buttonWidth = 120;
|
||||||
bGamemode->x = centerX - bGamemode->width / 2;
|
const int buttonSpacing = 10;
|
||||||
// compute vertical centre for gamemode in remaining space
|
const int totalButtonWidth = buttonWidth * 2 + buttonSpacing;
|
||||||
|
|
||||||
|
bGamemode->width = buttonWidth;
|
||||||
|
bCheats->width = buttonWidth;
|
||||||
|
|
||||||
|
bGamemode->x = centerX - totalButtonWidth / 2;
|
||||||
|
bCheats->x = bGamemode->x + buttonWidth + buttonSpacing;
|
||||||
|
|
||||||
|
// compute vertical centre for buttons in remaining space
|
||||||
{
|
{
|
||||||
int bottomPad = 20;
|
int bottomPad = 20;
|
||||||
int availTop = buttonHeight + 20 + 30 + 10; // just below seed
|
int availTop = buttonHeight + 20 + 30 + 10; // just below seed
|
||||||
int availBottom = height - bottomPad - bCreate->height - 10; // leave some gap before create
|
int availBottom = height - bottomPad - bCreate->height - 10; // leave some gap before create
|
||||||
int availHeight = availBottom - availTop;
|
int availHeight = availBottom - availTop;
|
||||||
if (availHeight < 0) availHeight = 0;
|
if (availHeight < 0) availHeight = 0;
|
||||||
bGamemode->y = availTop + (availHeight - bGamemode->height) / 2;
|
int y = availTop + (availHeight - bGamemode->height) / 2;
|
||||||
|
bGamemode->y = y;
|
||||||
|
bCheats->y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
bCreate->width = 100;
|
bCreate->width = 100;
|
||||||
@@ -124,14 +148,14 @@ void SimpleChooseLevelScreen::render( int xm, int ym, float a )
|
|||||||
renderDirtBackground(0);
|
renderDirtBackground(0);
|
||||||
glEnable2(GL_BLEND);
|
glEnable2(GL_BLEND);
|
||||||
|
|
||||||
const char* str = NULL;
|
const char* modeDesc = NULL;
|
||||||
if (gamemode == GameType::Survival) {
|
if (gamemode == GameType::Survival) {
|
||||||
str = "Mobs, health and gather resources";
|
modeDesc = "Mobs, health and gather resources";
|
||||||
} else if (gamemode == GameType::Creative) {
|
} else if (gamemode == GameType::Creative) {
|
||||||
str = "Unlimited resources and flying";
|
modeDesc = "Unlimited resources and flying";
|
||||||
}
|
}
|
||||||
if (str) {
|
if (modeDesc) {
|
||||||
drawCenteredString(minecraft->font, str, width/2, bGamemode->y + bGamemode->height + 4, 0xffcccccc);
|
drawCenteredString(minecraft->font, modeDesc, width / 2, bGamemode->y + bGamemode->height + 4, 0xffcccccc);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawString(minecraft->font, "World name:", tLevelName.x, tLevelName.y - Font::DefaultLineHeight - 2, 0xffcccccc);
|
drawString(minecraft->font, "World name:", tLevelName.x, tLevelName.y - Font::DefaultLineHeight - 2, 0xffcccccc);
|
||||||
@@ -188,6 +212,12 @@ void SimpleChooseLevelScreen::buttonClicked( Button* button )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (button == bCheats) {
|
||||||
|
cheatsEnabled = !cheatsEnabled;
|
||||||
|
bCheats->msg = cheatsEnabled ? "Cheats: On" : "Cheats: Off";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (button == bCreate && !tLevelName.text.empty()) {
|
if (button == bCreate && !tLevelName.text.empty()) {
|
||||||
int seed = getEpochTimeS();
|
int seed = getEpochTimeS();
|
||||||
if (!tSeed.text.empty()) {
|
if (!tSeed.text.empty()) {
|
||||||
@@ -200,7 +230,7 @@ void SimpleChooseLevelScreen::buttonClicked( Button* button )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string levelId = getUniqueLevelName(tLevelName.text);
|
std::string levelId = getUniqueLevelName(tLevelName.text);
|
||||||
LevelSettings settings(seed, gamemode);
|
LevelSettings settings(seed, gamemode, cheatsEnabled);
|
||||||
minecraft->selectLevel(levelId, levelId, settings);
|
minecraft->selectLevel(levelId, levelId, settings);
|
||||||
minecraft->hostMultiplayer();
|
minecraft->hostMultiplayer();
|
||||||
minecraft->setScreen(new ProgressScreen());
|
minecraft->setScreen(new ProgressScreen());
|
||||||
|
|||||||
@@ -29,12 +29,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
Touch::THeader* bHeader;
|
Touch::THeader* bHeader;
|
||||||
Button* bGamemode;
|
Button* bGamemode;
|
||||||
|
Button* bCheats;
|
||||||
ImageButton* bBack;
|
ImageButton* bBack;
|
||||||
Button* bCreate;
|
Button* bCreate;
|
||||||
bool hasChosen;
|
bool hasChosen;
|
||||||
|
|
||||||
std::string levelName;
|
std::string levelName;
|
||||||
int gamemode;
|
int gamemode;
|
||||||
|
bool cheatsEnabled;
|
||||||
|
|
||||||
TextBox tLevelName;
|
TextBox tLevelName;
|
||||||
TextBox tSeed;
|
TextBox tSeed;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "OptionsScreen.h"
|
#include "OptionsScreen.h"
|
||||||
#include "PauseScreen.h"
|
#include "PauseScreen.h"
|
||||||
#include "PrerenderTilesScreen.h" // test button
|
#include "PrerenderTilesScreen.h" // test button
|
||||||
|
#include "../components/ImageButton.h"
|
||||||
|
|
||||||
#include "../../../util/Mth.h"
|
#include "../../../util/Mth.h"
|
||||||
|
|
||||||
@@ -25,7 +26,8 @@
|
|||||||
StartMenuScreen::StartMenuScreen()
|
StartMenuScreen::StartMenuScreen()
|
||||||
: bHost( 2, 0, 0, 160, 24, "Start Game"),
|
: bHost( 2, 0, 0, 160, 24, "Start Game"),
|
||||||
bJoin( 3, 0, 0, 160, 24, "Join Game"),
|
bJoin( 3, 0, 0, 160, 24, "Join Game"),
|
||||||
bOptions( 4, 0, 0, 78, 22, "Options")
|
bOptions( 4, 0, 0, 78, 22, "Options"),
|
||||||
|
bQuit( 5, "")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,10 +56,18 @@ void StartMenuScreen::init()
|
|||||||
tabButtons.push_back(&bOptions);
|
tabButtons.push_back(&bOptions);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEMO_MODE
|
// add quit button (top right X icon) – match OptionsScreen style
|
||||||
buttons.push_back(&bBuy);
|
{
|
||||||
tabButtons.push_back(&bBuy);
|
ImageDef def;
|
||||||
#endif
|
def.name = "gui/touchgui.png";
|
||||||
|
def.width = 34;
|
||||||
|
def.height = 26;
|
||||||
|
def.setSrc(IntRectangle(150, 0, (int)def.width, (int)def.height));
|
||||||
|
bQuit.setImageDef(def, true);
|
||||||
|
bQuit.scaleWhenPressed = false;
|
||||||
|
buttons.push_back(&bQuit);
|
||||||
|
// don't include in tab navigation
|
||||||
|
}
|
||||||
|
|
||||||
copyright = "\xffMojang AB";//. Do not distribute!";
|
copyright = "\xffMojang AB";//. Do not distribute!";
|
||||||
|
|
||||||
@@ -100,8 +110,9 @@ void StartMenuScreen::setupPositions() {
|
|||||||
bJoin.x = (width - bJoin.width) / 2;
|
bJoin.x = (width - bJoin.width) / 2;
|
||||||
bOptions.x = (width - bJoin.width) / 2;
|
bOptions.x = (width - bJoin.width) / 2;
|
||||||
|
|
||||||
copyrightPosX = width - minecraft->font->width(copyright) - 1;
|
// position quit icon at top-right (use image-defined size)
|
||||||
versionPosX = (width - minecraft->font->width(version)) / 2;// - minecraft->font->width(version) - 2;
|
bQuit.x = width - bQuit.width;
|
||||||
|
bQuit.y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartMenuScreen::tick() {
|
void StartMenuScreen::tick() {
|
||||||
@@ -130,6 +141,10 @@ void StartMenuScreen::buttonClicked(Button* button) {
|
|||||||
{
|
{
|
||||||
minecraft->setScreen(new OptionsScreen());
|
minecraft->setScreen(new OptionsScreen());
|
||||||
}
|
}
|
||||||
|
if (button == &bQuit)
|
||||||
|
{
|
||||||
|
minecraft->quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartMenuScreen::isInGameScreen() { return false; }
|
bool StartMenuScreen::isInGameScreen() { return false; }
|
||||||
@@ -138,6 +153,10 @@ void StartMenuScreen::render( int xm, int ym, float a )
|
|||||||
{
|
{
|
||||||
renderBackground();
|
renderBackground();
|
||||||
|
|
||||||
|
// Show current username in the top-left corner
|
||||||
|
std::string username = minecraft->options.username.empty() ? "unknown" : minecraft->options.username;
|
||||||
|
drawString(font, std::string("Username: ") + username, 2, 2, 0xffffffff);
|
||||||
|
|
||||||
#if defined(RPI)
|
#if defined(RPI)
|
||||||
TextureId id = minecraft->textures->loadTexture("gui/pi_title.png");
|
TextureId id = minecraft->textures->loadTexture("gui/pi_title.png");
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "../Screen.h"
|
#include "../Screen.h"
|
||||||
#include "../components/Button.h"
|
#include "../components/Button.h"
|
||||||
|
#include "../components/ImageButton.h"
|
||||||
|
|
||||||
class StartMenuScreen: public Screen
|
class StartMenuScreen: public Screen
|
||||||
{
|
{
|
||||||
@@ -25,6 +26,7 @@ private:
|
|||||||
Button bHost;
|
Button bHost;
|
||||||
Button bJoin;
|
Button bJoin;
|
||||||
Button bOptions;
|
Button bOptions;
|
||||||
|
ImageButton bQuit; // X button in top-right corner
|
||||||
|
|
||||||
std::string copyright;
|
std::string copyright;
|
||||||
int copyrightPosX;
|
int copyrightPosX;
|
||||||
|
|||||||
@@ -33,15 +33,16 @@ void UsernameScreen::setupPositions()
|
|||||||
int cx = width / 2;
|
int cx = width / 2;
|
||||||
int cy = height / 2;
|
int cy = height / 2;
|
||||||
|
|
||||||
_btnDone.width = 120;
|
// Make the done button match the touch-style option tabs
|
||||||
_btnDone.height = 20;
|
_btnDone.width = 66;
|
||||||
|
_btnDone.height = 26;
|
||||||
_btnDone.x = (width - _btnDone.width) / 2;
|
_btnDone.x = (width - _btnDone.width) / 2;
|
||||||
_btnDone.y = height / 2 + 52;
|
_btnDone.y = height / 2 + 52;
|
||||||
|
|
||||||
tUsername.x = _btnDone.x;
|
|
||||||
tUsername.y = _btnDone.y - 60;
|
|
||||||
tUsername.width = 120;
|
tUsername.width = 120;
|
||||||
tUsername.height = 20;
|
tUsername.height = 20;
|
||||||
|
tUsername.x = (width - tUsername.width) / 2;
|
||||||
|
tUsername.y = _btnDone.y - 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UsernameScreen::tick()
|
void UsernameScreen::tick()
|
||||||
@@ -58,14 +59,20 @@ void UsernameScreen::keyPressed(int eventKey)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// deliberately do NOT call super::keyPressed — that would close the screen on Escape
|
// deliberately do NOT call super::keyPressed — that would close the screen on Escape
|
||||||
_btnDone.active = !tUsername.text.empty();
|
|
||||||
|
|
||||||
Screen::keyPressed(eventKey);
|
Screen::keyPressed(eventKey);
|
||||||
|
|
||||||
|
// enable the Done button only when there is some text (and ensure it updates after backspace)
|
||||||
|
_btnDone.active = !tUsername.text.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UsernameScreen::keyboardNewChar(char inputChar)
|
void UsernameScreen::keyboardNewChar(char inputChar)
|
||||||
{
|
{
|
||||||
for (auto* tb : textBoxes) tb->handleChar(inputChar);
|
// limit username length to 12 characters
|
||||||
|
if (tUsername.text.size() < 12) {
|
||||||
|
for (auto* tb : textBoxes) tb->handleChar(inputChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
_btnDone.active = !tUsername.text.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UsernameScreen::mouseClicked(int x, int y, int button)
|
void UsernameScreen::mouseClicked(int x, int y, int button)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ protected:
|
|||||||
virtual void buttonClicked(Button* button);
|
virtual void buttonClicked(Button* button);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Button _btnDone;
|
Touch::TButton _btnDone;
|
||||||
TextBox tUsername;
|
TextBox tUsername;
|
||||||
std::string _input;
|
std::string _input;
|
||||||
int _cursorBlink;
|
int _cursorBlink;
|
||||||
|
|||||||
@@ -153,6 +153,11 @@ int IngameBlockSelectionScreen::getSlotPosY(int slotY) {
|
|||||||
return height - 16 - 3 - 22 * 2 - 22 * slotY;
|
return height - 16 - 3 - 22 * 2 - 22 * slotY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IngameBlockSelectionScreen::getSlotHeight() {
|
||||||
|
// same as non-touch implementation
|
||||||
|
return 22;
|
||||||
|
}
|
||||||
|
|
||||||
void IngameBlockSelectionScreen::mouseClicked(int x, int y, int buttonNum) {
|
void IngameBlockSelectionScreen::mouseClicked(int x, int y, int buttonNum) {
|
||||||
_pendingClose = _blockList->_clickArea->isInside((float)x, (float)y);
|
_pendingClose = _blockList->_clickArea->isInside((float)x, (float)y);
|
||||||
if (!_pendingClose)
|
if (!_pendingClose)
|
||||||
@@ -166,6 +171,24 @@ void IngameBlockSelectionScreen::mouseReleased(int x, int y, int buttonNum) {
|
|||||||
super::mouseReleased(x, y, buttonNum);
|
super::mouseReleased(x, y, buttonNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IngameBlockSelectionScreen::mouseWheel(int dx, int dy, int xm, int ym)
|
||||||
|
{
|
||||||
|
if (dy == 0) return;
|
||||||
|
if (_blockList) {
|
||||||
|
float amount = -dy * getSlotHeight();
|
||||||
|
_blockList->scrollBy(0, amount);
|
||||||
|
}
|
||||||
|
int cols = InventoryColumns;
|
||||||
|
int maxIndex = InventorySize - 1;
|
||||||
|
int idx = selectedItem;
|
||||||
|
if (dy > 0) {
|
||||||
|
if (idx >= cols) idx -= cols;
|
||||||
|
} else {
|
||||||
|
if (idx + cols <= maxIndex) idx += cols;
|
||||||
|
}
|
||||||
|
selectedItem = idx;
|
||||||
|
}
|
||||||
|
|
||||||
bool IngameBlockSelectionScreen::addItem(const InventoryPane* pane, int itemId)
|
bool IngameBlockSelectionScreen::addItem(const InventoryPane* pane, int itemId)
|
||||||
{
|
{
|
||||||
Inventory* inventory = minecraft->player->inventory;
|
Inventory* inventory = minecraft->player->inventory;
|
||||||
|
|||||||
@@ -39,12 +39,16 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void mouseClicked(int x, int y, int buttonNum);
|
virtual void mouseClicked(int x, int y, int buttonNum);
|
||||||
virtual void mouseReleased(int x, int y, int buttonNum);
|
virtual void mouseReleased(int x, int y, int buttonNum);
|
||||||
|
|
||||||
|
// also support wheel scrolling
|
||||||
|
virtual void mouseWheel(int dx, int dy, int xm, int ym) override;
|
||||||
private:
|
private:
|
||||||
void renderDemoOverlay();
|
void renderDemoOverlay();
|
||||||
|
|
||||||
//int getLinearSlotId(int x, int y);
|
//int getLinearSlotId(int x, int y);
|
||||||
int getSlotPosX(int slotX);
|
int getSlotPosX(int slotX);
|
||||||
int getSlotPosY(int slotY);
|
int getSlotPosY(int slotY);
|
||||||
|
int getSlotHeight();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int selectedItem;
|
int selectedItem;
|
||||||
|
|||||||
@@ -389,6 +389,26 @@ static char ILLEGAL_FILE_CHARACTERS[] = {
|
|||||||
'/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':'
|
'/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void SelectWorldScreen::mouseWheel(int dx, int dy, int xm, int ym)
|
||||||
|
{
|
||||||
|
if (!worldsList) return;
|
||||||
|
if (dy == 0) return;
|
||||||
|
int num = worldsList->getNumberOfItems();
|
||||||
|
int idx = worldsList->selectedItem;
|
||||||
|
if (dy > 0) {
|
||||||
|
if (idx > 0) {
|
||||||
|
idx--;
|
||||||
|
worldsList->stepLeft();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (idx < num - 1) {
|
||||||
|
idx++;
|
||||||
|
worldsList->stepRight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
worldsList->selectedItem = idx;
|
||||||
|
}
|
||||||
|
|
||||||
void SelectWorldScreen::tick()
|
void SelectWorldScreen::tick()
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ public:
|
|||||||
virtual void buttonClicked(Button* button);
|
virtual void buttonClicked(Button* button);
|
||||||
virtual void keyPressed(int eventKey);
|
virtual void keyPressed(int eventKey);
|
||||||
|
|
||||||
|
// support for mouse wheel when desktop code uses touch variant
|
||||||
|
virtual void mouseWheel(int dx, int dy, int xm, int ym) override;
|
||||||
|
|
||||||
bool isInGameScreen();
|
bool isInGameScreen();
|
||||||
private:
|
private:
|
||||||
void loadLevelSource();
|
void loadLevelSource();
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ namespace Touch {
|
|||||||
StartMenuScreen::StartMenuScreen()
|
StartMenuScreen::StartMenuScreen()
|
||||||
: bHost( 2, "Start Game"),
|
: bHost( 2, "Start Game"),
|
||||||
bJoin( 3, "Join Game"),
|
bJoin( 3, "Join Game"),
|
||||||
bOptions( 4, "Options")
|
bOptions( 4, "Options"),
|
||||||
|
bQuit( 5, "")
|
||||||
{
|
{
|
||||||
ImageDef def;
|
ImageDef def;
|
||||||
bJoin.width = 75;
|
bJoin.width = 75;
|
||||||
@@ -59,7 +60,17 @@ void StartMenuScreen::init()
|
|||||||
buttons.push_back(&bJoin);
|
buttons.push_back(&bJoin);
|
||||||
buttons.push_back(&bOptions);
|
buttons.push_back(&bOptions);
|
||||||
|
|
||||||
|
// add quit icon (same look as options header)
|
||||||
|
{
|
||||||
|
ImageDef def;
|
||||||
|
def.name = "gui/touchgui.png";
|
||||||
|
def.width = 34;
|
||||||
|
def.height = 26;
|
||||||
|
def.setSrc(IntRectangle(150, 0, (int)def.width, (int)def.height));
|
||||||
|
bQuit.setImageDef(def, true);
|
||||||
|
bQuit.scaleWhenPressed = false;
|
||||||
|
buttons.push_back(&bQuit);
|
||||||
|
}
|
||||||
|
|
||||||
tabButtons.push_back(&bHost);
|
tabButtons.push_back(&bHost);
|
||||||
tabButtons.push_back(&bJoin);
|
tabButtons.push_back(&bJoin);
|
||||||
@@ -108,6 +119,10 @@ void StartMenuScreen::setupPositions() {
|
|||||||
bHost.x = 1*buttonWidth + (int)(2*spacing);
|
bHost.x = 1*buttonWidth + (int)(2*spacing);
|
||||||
bOptions.x = 2*buttonWidth + (int)(3*spacing);
|
bOptions.x = 2*buttonWidth + (int)(3*spacing);
|
||||||
|
|
||||||
|
// quit icon top-right (use size assigned in init)
|
||||||
|
bQuit.x = width - bQuit.width;
|
||||||
|
bQuit.y = 0;
|
||||||
|
|
||||||
copyrightPosX = width - minecraft->font->width(copyright) - 1;
|
copyrightPosX = width - minecraft->font->width(copyright) - 1;
|
||||||
versionPosX = (width - minecraft->font->width(version)) / 2;// - minecraft->font->width(version) - 2;
|
versionPosX = (width - minecraft->font->width(version)) / 2;// - minecraft->font->width(version) - 2;
|
||||||
}
|
}
|
||||||
@@ -135,6 +150,10 @@ void StartMenuScreen::buttonClicked(::Button* button) {
|
|||||||
{
|
{
|
||||||
minecraft->setScreen(new OptionsScreen());
|
minecraft->setScreen(new OptionsScreen());
|
||||||
}
|
}
|
||||||
|
if (button == &bQuit)
|
||||||
|
{
|
||||||
|
minecraft->quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartMenuScreen::isInGameScreen() { return false; }
|
bool StartMenuScreen::isInGameScreen() { return false; }
|
||||||
@@ -143,6 +162,10 @@ void StartMenuScreen::render( int xm, int ym, float a )
|
|||||||
{
|
{
|
||||||
renderBackground();
|
renderBackground();
|
||||||
|
|
||||||
|
// Show current username in the top-left corner
|
||||||
|
std::string username = minecraft->options.username.empty() ? "unknown" : minecraft->options.username;
|
||||||
|
drawString(font, std::string("Username: ") + username, 2, 2, 0xffffffff);
|
||||||
|
|
||||||
glEnable2(GL_BLEND);
|
glEnable2(GL_BLEND);
|
||||||
|
|
||||||
#if defined(RPI)
|
#if defined(RPI)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "../../Screen.h"
|
#include "../../Screen.h"
|
||||||
#include "../../components/LargeImageButton.h"
|
#include "../../components/LargeImageButton.h"
|
||||||
|
#include "../../components/ImageButton.h"
|
||||||
#include "../../components/TextBox.h"
|
#include "../../components/TextBox.h"
|
||||||
|
|
||||||
namespace Touch {
|
namespace Touch {
|
||||||
@@ -27,6 +28,7 @@ private:
|
|||||||
LargeImageButton bHost;
|
LargeImageButton bHost;
|
||||||
LargeImageButton bJoin;
|
LargeImageButton bJoin;
|
||||||
LargeImageButton bOptions;
|
LargeImageButton bOptions;
|
||||||
|
ImageButton bQuit; // X close icon
|
||||||
|
|
||||||
std::string copyright;
|
std::string copyright;
|
||||||
int copyrightPosX;
|
int copyrightPosX;
|
||||||
|
|||||||
@@ -113,6 +113,14 @@ LRESULT WINAPI windowProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|||||||
Multitouch::feed(0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0);
|
Multitouch::feed(0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WM_MOUSEWHEEL: {
|
||||||
|
// wheel delta is multiples of WHEEL_DELTA (120); convert to +/-1
|
||||||
|
int delta = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
|
||||||
|
short x = GET_X_LPARAM(lParam);
|
||||||
|
short y = GET_Y_LPARAM(lParam);
|
||||||
|
Mouse::feed(MouseAction::ACTION_WHEEL, 0, x, y, 0, delta);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
if (uMsg == WM_NCDESTROY) g_running = false;
|
if (uMsg == WM_NCDESTROY) g_running = false;
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -255,16 +255,16 @@ void Inventory::setupDefault() {
|
|||||||
} else {
|
} else {
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
// Survival
|
// Survival
|
||||||
addItem(new ItemInstance(Item::ironIngot, 64));
|
// addItem(new ItemInstance(Item::ironIngot, 64));
|
||||||
addItem(new ItemInstance(Item::ironIngot, 34));
|
// addItem(new ItemInstance(Item::ironIngot, 34));
|
||||||
addItem(new ItemInstance(Tile::stonecutterBench));
|
// addItem(new ItemInstance(Tile::stonecutterBench));
|
||||||
addItem(new ItemInstance(Tile::workBench));
|
// addItem(new ItemInstance(Tile::workBench));
|
||||||
addItem(new ItemInstance(Tile::furnace));
|
// addItem(new ItemInstance(Tile::furnace));
|
||||||
addItem(new ItemInstance(Tile::wood, 54));
|
// addItem(new ItemInstance(Tile::wood, 54));
|
||||||
addItem(new ItemInstance(Item::stick, 14));
|
// addItem(new ItemInstance(Item::stick, 14));
|
||||||
addItem(new ItemInstance(Item::coal, 31));
|
// addItem(new ItemInstance(Item::coal, 31));
|
||||||
addItem(new ItemInstance(Tile::sand, 6));
|
// addItem(new ItemInstance(Tile::sand, 6));
|
||||||
addItem(new ItemInstance(Item::dye_powder, 23, DyePowderItem::PURPLE));
|
// addItem(new ItemInstance(Item::dye_powder, 23, DyePowderItem::PURPLE));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,13 +14,14 @@ namespace GameType {
|
|||||||
class LevelSettings
|
class LevelSettings
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LevelSettings(long seed, int gameType)
|
LevelSettings(long seed, int gameType, bool allowCheats = false)
|
||||||
: seed(seed),
|
: seed(seed),
|
||||||
gameType(gameType)
|
gameType(gameType),
|
||||||
|
allowCheats(allowCheats)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static LevelSettings None() {
|
static LevelSettings None() {
|
||||||
return LevelSettings(-1,-1);
|
return LevelSettings(-1,-1,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
long getSeed() const {
|
long getSeed() const {
|
||||||
@@ -31,6 +32,10 @@ public:
|
|||||||
return gameType;
|
return gameType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getAllowCheats() const {
|
||||||
|
return allowCheats;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Those two should actually not be here
|
// Those two should actually not be here
|
||||||
// @todo: Move out when we add LevelSettings.cpp :p
|
// @todo: Move out when we add LevelSettings.cpp :p
|
||||||
@@ -53,6 +58,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
const long seed;
|
const long seed;
|
||||||
const int gameType;
|
const int gameType;
|
||||||
|
const bool allowCheats;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*NET_MINECRAFT_WORLD_LEVEL__LevelSettings_H__*/
|
#endif /*NET_MINECRAFT_WORLD_LEVEL__LevelSettings_H__*/
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ LevelData::LevelData()
|
|||||||
dimension(Dimension::NORMAL),
|
dimension(Dimension::NORMAL),
|
||||||
playerDataVersion(-1),
|
playerDataVersion(-1),
|
||||||
storageVersion(0),
|
storageVersion(0),
|
||||||
gameType(GameType::Default),
|
gameType(GameType::Default), spawnMobs(false),
|
||||||
loadedPlayerTag(NULL)
|
allowCheats(false), loadedPlayerTag(NULL)
|
||||||
{
|
{
|
||||||
//LOGI("ctor 1: %p\n", this);
|
//LOGI("ctor 1: %p\n", this);
|
||||||
spawnMobs = (gameType == GameType::Survival);
|
spawnMobs = (gameType == GameType::Survival);
|
||||||
@@ -21,8 +21,7 @@ LevelData::LevelData()
|
|||||||
|
|
||||||
LevelData::LevelData( const LevelSettings& settings, const std::string& levelName, int generatorVersion /*= -1*/ )
|
LevelData::LevelData( const LevelSettings& settings, const std::string& levelName, int generatorVersion /*= -1*/ )
|
||||||
: seed(settings.getSeed()),
|
: seed(settings.getSeed()),
|
||||||
gameType(settings.getGameType()),
|
gameType(settings.getGameType()), allowCheats(settings.getAllowCheats()), levelName(levelName),
|
||||||
levelName(levelName),
|
|
||||||
xSpawn(128),
|
xSpawn(128),
|
||||||
ySpawn(64),
|
ySpawn(64),
|
||||||
zSpawn(128),
|
zSpawn(128),
|
||||||
@@ -62,6 +61,7 @@ LevelData::LevelData( const LevelData& rhs )
|
|||||||
playerDataVersion(rhs.playerDataVersion),
|
playerDataVersion(rhs.playerDataVersion),
|
||||||
generatorVersion(rhs.generatorVersion),
|
generatorVersion(rhs.generatorVersion),
|
||||||
spawnMobs(rhs.spawnMobs),
|
spawnMobs(rhs.spawnMobs),
|
||||||
|
allowCheats(rhs.allowCheats),
|
||||||
loadedPlayerTag(NULL),
|
loadedPlayerTag(NULL),
|
||||||
playerData(rhs.playerData)
|
playerData(rhs.playerData)
|
||||||
{
|
{
|
||||||
@@ -84,6 +84,7 @@ LevelData& LevelData::operator=( const LevelData& rhs )
|
|||||||
time = rhs.time;
|
time = rhs.time;
|
||||||
dimension = rhs.dimension;
|
dimension = rhs.dimension;
|
||||||
spawnMobs = rhs.spawnMobs;
|
spawnMobs = rhs.spawnMobs;
|
||||||
|
allowCheats = rhs.allowCheats;
|
||||||
playerData = rhs.playerData;
|
playerData = rhs.playerData;
|
||||||
playerDataVersion = rhs.playerDataVersion;
|
playerDataVersion = rhs.playerDataVersion;
|
||||||
generatorVersion = rhs.generatorVersion;
|
generatorVersion = rhs.generatorVersion;
|
||||||
@@ -161,6 +162,7 @@ void LevelData::setTagData( CompoundTag* tag, CompoundTag* playerTag )
|
|||||||
if (!tag) return;
|
if (!tag) return;
|
||||||
tag->putLong("RandomSeed", seed);
|
tag->putLong("RandomSeed", seed);
|
||||||
tag->putInt("GameType", gameType);
|
tag->putInt("GameType", gameType);
|
||||||
|
tag->putBoolean("AllowCommands", allowCheats);
|
||||||
tag->putInt("SpawnX", xSpawn);
|
tag->putInt("SpawnX", xSpawn);
|
||||||
tag->putInt("SpawnY", ySpawn);
|
tag->putInt("SpawnY", ySpawn);
|
||||||
tag->putInt("SpawnZ", zSpawn);
|
tag->putInt("SpawnZ", zSpawn);
|
||||||
@@ -181,6 +183,7 @@ void LevelData::getTagData( const CompoundTag* tag )
|
|||||||
if (!tag) return;
|
if (!tag) return;
|
||||||
seed = (long)tag->getLong("RandomSeed");
|
seed = (long)tag->getLong("RandomSeed");
|
||||||
gameType = tag->getInt("GameType");
|
gameType = tag->getInt("GameType");
|
||||||
|
allowCheats = tag->getBoolean("AllowCommands");
|
||||||
xSpawn = tag->getInt("SpawnX");
|
xSpawn = tag->getInt("SpawnX");
|
||||||
ySpawn = tag->getInt("SpawnY");
|
ySpawn = tag->getInt("SpawnY");
|
||||||
zSpawn = tag->getInt("SpawnZ");
|
zSpawn = tag->getInt("SpawnZ");
|
||||||
@@ -362,3 +365,13 @@ void LevelData::setSpawnMobs( bool doSpawn )
|
|||||||
{
|
{
|
||||||
spawnMobs = doSpawn;
|
spawnMobs = doSpawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LevelData::getAllowCheats() const
|
||||||
|
{
|
||||||
|
return allowCheats;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LevelData::setAllowCheats( bool allow )
|
||||||
|
{
|
||||||
|
allowCheats = allow;
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ public:
|
|||||||
bool getSpawnMobs() const;
|
bool getSpawnMobs() const;
|
||||||
void setSpawnMobs(bool doSpawn);
|
void setSpawnMobs(bool doSpawn);
|
||||||
|
|
||||||
|
bool getAllowCheats() const;
|
||||||
|
void setAllowCheats(bool allow);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PlayerData playerData;
|
PlayerData playerData;
|
||||||
int playerDataVersion;
|
int playerDataVersion;
|
||||||
@@ -89,6 +92,7 @@ private:
|
|||||||
int gameType;
|
int gameType;
|
||||||
int storageVersion;
|
int storageVersion;
|
||||||
bool spawnMobs;
|
bool spawnMobs;
|
||||||
|
bool allowCheats;
|
||||||
//@note: This version is never written or loaded to disk. The only purpose
|
//@note: This version is never written or loaded to disk. The only purpose
|
||||||
// is to use it in the level generator on server and clients.
|
// is to use it in the level generator on server and clients.
|
||||||
int generatorVersion;
|
int generatorVersion;
|
||||||
|
|||||||
@@ -165,7 +165,8 @@ void DoorTile::neighborChanged(Level* level, int x, int y, int z, int type) {
|
|||||||
}
|
}
|
||||||
if (spawn) {
|
if (spawn) {
|
||||||
if (!level->isClientSide) {
|
if (!level->isClientSide) {
|
||||||
spawnResources(level, x, y, z, data, 0);
|
// use default chance (1.0) so the drop always occurs
|
||||||
|
spawnResources(level, x, y, z, data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bool signal = level->hasNeighborSignal(x, y, z) || level->hasNeighborSignal(x, y + 1, z);
|
bool signal = level->hasNeighborSignal(x, y, z) || level->hasNeighborSignal(x, y + 1, z);
|
||||||
@@ -174,13 +175,12 @@ void DoorTile::neighborChanged(Level* level, int x, int y, int z, int type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// upper half: removal should not drop a second door. the
|
||||||
|
// lower half neighbour handler takes care of spawning the item
|
||||||
|
// whenever the door is broken from either end.
|
||||||
if (level->getTile(x, y - 1, z) != id) {
|
if (level->getTile(x, y - 1, z) != id) {
|
||||||
level->setTile(x, y, z, 0);
|
level->setTile(x, y, z, 0);
|
||||||
if(material == Material::metal) {
|
// no resource spawn here
|
||||||
popResource(level, x, y, z, ItemInstance(Item::door_iron));
|
|
||||||
} else {
|
|
||||||
popResource(level, x, y, z, ItemInstance(Item::door_wood));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (type > 0 && type != id) {
|
if (type > 0 && type != id) {
|
||||||
neighborChanged(level, x, y - 1, z, type);
|
neighborChanged(level, x, y - 1, z, type);
|
||||||
@@ -189,7 +189,11 @@ void DoorTile::neighborChanged(Level* level, int x, int y, int z, int type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int DoorTile::getResource(int data, Random* random) {
|
int DoorTile::getResource(int data, Random* random) {
|
||||||
if ((data & 8) != 0) return 0;
|
// only the lower half should return a resource ID; the upper half
|
||||||
|
// itself never drops anything and playerDestroy suppresses spawning
|
||||||
|
// from the top. This prevents duplicate drops if the bottom half is
|
||||||
|
// mined.
|
||||||
|
if ((data & UPPER_BIT) != 0) return 0;
|
||||||
if (material == Material::metal) return Item::door_iron->id;
|
if (material == Material::metal) return Item::door_iron->id;
|
||||||
return Item::door_wood->id;
|
return Item::door_wood->id;
|
||||||
}
|
}
|
||||||
@@ -199,6 +203,14 @@ HitResult DoorTile::clip(Level* level, int xt, int yt, int zt, const Vec3& a, co
|
|||||||
return super::clip(level, xt, yt, zt, a, b);
|
return super::clip(level, xt, yt, zt, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// override to prevent double-dropping when top half is directly mined
|
||||||
|
void DoorTile::playerDestroy(Level* level, Player* player, int x, int y, int z, int data) {
|
||||||
|
if ((data & UPPER_BIT) == 0) {
|
||||||
|
// only let the lower half handle the actual spawning
|
||||||
|
super::playerDestroy(level, player, x, y, z, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int DoorTile::getDir(LevelSource* level, int x, int y, int z) {
|
int DoorTile::getDir(LevelSource* level, int x, int y, int z) {
|
||||||
return getCompositeData(level, x, y, z) & C_DIR_MASK;
|
return getCompositeData(level, x, y, z) & C_DIR_MASK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ public:
|
|||||||
|
|
||||||
int getResource(int data, Random* random);
|
int getResource(int data, Random* random);
|
||||||
|
|
||||||
|
// override to avoid duplicate drops when upper half is mined directly
|
||||||
|
void playerDestroy(Level* level, Player* player, int x, int y, int z, int data) override;
|
||||||
|
|
||||||
HitResult clip(Level* level, int xt, int yt, int zt, const Vec3& a, const Vec3& b);
|
HitResult clip(Level* level, int xt, int yt, int zt, const Vec3& a, const Vec3& b);
|
||||||
|
|
||||||
int getDir(LevelSource* level, int x, int y, int z);
|
int getDir(LevelSource* level, int x, int y, int z);
|
||||||
|
|||||||
Reference in New Issue
Block a user