85 Commits

Author SHA1 Message Date
867114b0f3 1 2026-07-27 15:45:40 +02:00
1a8ead4955 2 2026-07-27 15:45:17 +02:00
dddd69472a ok 2026-07-27 01:33:26 +02:00
881c1188a1 lol 2026-07-27 00:12:58 +02:00
f1ff828027 i 2026-07-26 19:43:51 +02:00
f93521a879 login plugin works yoy 2026-07-26 01:02:27 +02:00
d9dfff3339 1 2026-07-25 21:54:02 +02:00
c62daa9c1c Merge branch 'plugins-support' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 into plugins-support 2026-07-22 23:28:17 +02:00
f6377bc5a2 lol 2026-07-22 23:27:50 +02:00
431b2a2704 add iostream 2026-07-23 00:26:44 +03:00
67acd7f9a6 update 2026-07-21 22:42:28 +02:00
6f1ca8fc3b begin 2026-07-20 14:49:38 +02:00
f7ad5acd33 remove includes for server 2026-07-19 01:04:34 +03:00
444e826d1b aa 2026-07-18 23:41:05 +02:00
6b6ad48617 Merge branch 'dedicated-rewrite' 2026-07-18 23:23:46 +02:00
e43da17d66 oh i didnt know 2026-07-18 23:02:25 +03:00
3fcf3e3418 link WSA with server 2026-07-18 22:47:41 +03:00
8955b6ea47 ADD: server build for windows 2026-07-18 22:32:13 +03:00
4f21343e3b release soon but we need to fix large world in mp 2026-07-18 21:01:13 +02:00
fcf7427fb2 gg fixed 2026-07-18 19:14:16 +02:00
50d1de49e0 FIX: multiplayer leave crash and compilation 2026-07-18 15:25:03 +03:00
3811964689 ffqwfqwfw 2026-07-18 14:02:45 +02:00
26e5376030 FIX: Crash when server is disaibling 2026-07-10 21:45:52 +02:00
d3d9b1a238 anticheat sucks xdxd 2026-07-10 00:59:26 +02:00
f0df3fe257 Server for windows wow 2026-07-10 00:46:36 +02:00
3ebed84cdb FIX: crash while joining to large world server 2026-07-02 16:32:17 +03:00
Shredder
d08948fb00 renable generation features 2026-05-23 06:03:34 +05:00
Shredder
061d6db3a9 add burp1.ogg to fix android compilation 2026-05-23 05:46:11 +05:00
Shredder
346ec7469e merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-05-23 05:30:27 +05:00
Shredder
d7d887f882 few additions and bug fixes
Added Hand Sway (not an option yet) from b1,8

Fire works properly in multiplayer now and also renders on undead mobs in sunlight now

hopefully fixed bow stuck bug on touchscreen devices

Fire on entites uses updated rendering from b1.6.6

Shadow bug fix attempt the 15th

Added looking at block in debug screen

Zombie Pigman now renders his hat layer

Temporarily disabled most randomlevelsource cave, canyon and tall grass code just for this commit to test performance
2026-05-23 05:29:47 +05:00
ce182b676f Merge pull request 'added missing audio random.burp when finishing a food item' (#14) from sas3/minecraft-pe-0.6.1:main into main
Reviewed-on: Kolyah35/minecraft-pe-0.6.1#14
2026-05-12 21:50:28 +02:00
b73f7f121d ee 2026-05-12 21:29:17 +02:00
Kolyah35
5e19ef778e FIX: memset ._. 2026-05-12 22:12:52 +03:00
5bc19c4ab2 FEAT: Ban command, save ops and banned ppl in files
TODO: fix many crashes...
2026-05-09 16:37:11 +02:00
dfb3bf1da7 FIX: render
ty shredder
2026-05-09 14:41:31 +02:00
263118f2e0 Fix 2026-05-09 13:09:45 +02:00
1d0264a9c5 FEAT: World size 2026-05-09 01:45:19 +02:00
43f0d1f75f server config 2026-05-08 23:42:41 +02:00
70308d4151 qqqqqq 2026-05-05 21:55:03 +02:00
830549791a 121 2026-05-05 21:51:35 +02:00
27b22d8108 vegetables 2026-05-05 21:41:26 +02:00
4047fd71e1 oi 2026-05-05 21:36:35 +02:00
30dd344208 123 2026-05-05 21:33:28 +02:00
7e9de7a461 fck android build!!! 2026-05-05 21:19:08 +02:00
2465292473 jopa 2026-05-05 21:14:17 +02:00
26b2c196fa :\ 2026-05-05 21:09:42 +02:00
18793a6e05 idk? 2026-05-05 20:40:41 +02:00
Kolyah35
3e48c7fabd FIX: compilation 2026-05-02 21:31:48 +03:00
de72a9a3b7 all was broken :\ 2026-04-27 23:43:36 +02:00
0645905fc6 eeee it doesnt work 😭 2026-04-27 22:18:18 +02:00
Kolyah35
4023d70687 FEAT: server-side commands 2026-04-04 01:13:56 +03:00
Kolyah35
4dc7055d9d FIX: make antispeedhack working 2026-03-31 23:34:41 +03:00
Kolyah35
1ec347d5d5 FEAT: Server operators 2026-03-31 00:40:10 +03:00
Kolyah35
5194575092 FEAT: Meet the commands 2026-03-30 14:04:16 +03:00
3cfa2d9ee7 FIX IT AHTUNG AHTUNG ALL DOESNT WORK FIX IT FIX IT FIX IT FIX IT BIG WARNING BIG WARNING 2026-03-29 16:53:46 +02:00
f016f00eab idk?? 2026-03-29 00:16:19 +02:00
Kolyah35
470c28d83a I dont know what im doin please help 2026-03-29 00:36:36 +03:00
4363157cd9 Delete useless class 2026-03-28 21:08:52 +02:00
ba3ed3b4dd i dont see reason of this error 2026-03-28 18:37:02 +02:00
5783fb93f3 forgot to comment 2026-03-28 17:39:37 +02:00
73fb2a2b3d wtf 2026-03-28 17:18:38 +02:00
bcf48eb5e3 FEAT: Damage on server 2026-03-28 16:41:00 +02:00
Kolyah35
f5fecbc928 Merge remote-tracking branch 'refs/remotes/origin/dedicated-rewrite' into dedicated-rewrite 2026-03-27 22:15:26 +03:00
Kolyah35
77d02fcca2 FIX: workbench compatibility 2026-03-27 22:15:03 +03:00
6d696af235 FEAT: taken nickname 2026-03-27 21:08:17 +02:00
Kolyah35
370363f792 Merge remote-tracking branch 'refs/remotes/origin/dedicated-rewrite' into dedicated-rewrite 2026-03-27 21:26:48 +03:00
Kolyah35
61a2349b8b FEAT: Player data saving/loading 2026-03-27 21:26:25 +03:00
eed3a6df61 FEAT: Message for outdated clients 2026-03-27 20:22:05 +02:00
97b0fb4d46 FEAT: New proto check 2026-03-27 20:16:59 +02:00
8be842a8ac FEAT: player anticheat speed 2026-03-27 19:41:54 +02:00
6957f144e1 FIX: Inventory change when cheating items (TODO: Linked slots) 2026-03-27 17:05:50 +02:00
f9d9a0f0f9 FIX: Recheck recipes in MP 2026-03-27 13:47:33 +02:00
Kolyah35
28febb4e63 FIX: tool durablity mismatch 2026-03-27 14:01:49 +03:00
Kolyah35
aeef442f76 FIX: Server-side item remove when crafting 2026-03-27 04:02:27 +03:00
8098ab8906 easy 2026-03-27 02:48:56 +02:00
f0cb6d0b7c Fix compile errors 2026-03-27 02:42:34 +02:00
d1672c0ee2 Merge branch 'dedicated-rewrite' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 into dedicated-rewrite 2026-03-27 02:40:55 +02:00
c234abe3aa FIX: Item crafting 2026-03-27 02:40:52 +02:00
Kolyah35
e4ff7728af Merge remote-tracking branch 'refs/remotes/origin/dedicated-rewrite' into dedicated-rewrite 2026-03-27 03:34:29 +03:00
Kolyah35
41c5bdf243 FIX: The end of item cheating 2026-03-27 03:33:21 +03:00
96e8826f01 FEAT: Crafting on server 2026-03-27 02:14:28 +02:00
db8993683f Merge branch 'dedicated-rewrite' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 into dedicated-rewrite 2026-03-26 22:48:52 +02:00
2c1b5e256e change proto ver 2026-03-26 22:48:50 +02:00
Kolyah35
4beb5cb0f9 i think i fixed player equip 2026-03-26 23:32:09 +03:00
SAS_OP
88ef7f3d17 added missing audio random.burp when finishing a food item 2026-03-25 06:07:49 +03:00
110 changed files with 5496 additions and 914 deletions

View File

@@ -60,13 +60,16 @@ jobs:
- name: Build
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE --target MinecraftPE --parallel
run: |
cmake --build . --config $BUILD_TYPE --target MinecraftPE --parallel
cmake --build . --config $BUILD_TYPE --target MinecraftPE-server --parallel
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: mcpe-windows
path: |
${{github.workspace}}/build/MinecraftPE-server.exe
${{github.workspace}}/build/MinecraftPE.exe
${{github.workspace}}/build/libpng16.dll
${{github.workspace}}/build/OpenAL32.dll
@@ -299,6 +302,12 @@ jobs:
with:
files: mcpe-windows/MinecraftPE.exe mcpe-windows/libpng16.dll mcpe-windows/OpenAL32.dll mcpe-windows/libz.dll
dest: minecraftpe-${{ steps.ref.outputs.hash }}-windows.zip
- name: Zip Windows Server Artifacts
uses: vimtor/action-zip@v1.2
with:
files: mcpe-windows/MinecraftPE-server.exe
dest: minecraftpe-server-${{ steps.ref.outputs.hash }}-windows.zip
- name: Zip Linux Artifacts
uses: vimtor/action-zip@v1.2
@@ -310,7 +319,7 @@ jobs:
uses: vimtor/action-zip@v1.2
with:
files: mcpe-linux/MinecraftPE-server
dest: minecraftpe-server-${{ steps.ref.outputs.hash }}.zip
dest: minecraftpe-server-${{ steps.ref.outputs.hash }}-linux.zip
- name: Rename Android Artifacts
run: |
@@ -343,7 +352,11 @@ jobs:
./data.zip
./minecraftpe-server-${{ steps.ref.outputs.hash }}.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-windows.zip
./minecraftpe-server-${{ steps.ref.outputs.hash }}-windows.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-linux.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-android-arm64-v8a.apk
./minecraftpe-${{ steps.ref.outputs.hash }}-android-armeabi-v7a.apk
./minecraftpe-server-${{ steps.ref.outputs.hash }}-linux.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-android-arm64-v8a.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-android-armeabi-v7a.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-web.zip

View File

@@ -3,10 +3,9 @@ project(MinecraftPE)
include(cmake/CPM.cmake)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_POLICY_VERSION_MINIMUM 3.10)
include(cmake/EnumOption.cmake)
if(EMSCRIPTEN)
@@ -34,9 +33,11 @@ if (${PLATFORM} STREQUAL "Desktop")
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
include_directories(misc/windows)
set(EXTRA_LIBS ws2_32 winhttp)
add_definitions(-DLUA_DL_DLL=1)
elseif(UNIX)
find_library(pthread NAMES pthread)
set(EXTRA_LIBS pthread m)
add_definitions(-DLUA_USE_DLOPEN=1)
endif()
elseif (${PLATFORM} STREQUAL "Web")
@@ -95,6 +96,46 @@ else()
"GLFW_BUILD_TESTS OFF"
"GLFW_BUILD_DOCS OFF"
)
CPMAddPackage("gh:halx99/sol2#support-lua-5.5")
CPMAddPackage("gh:lua/lua#master")
add_library(
lua STATIC
${lua_SOURCE_DIR}/lapi.c
${lua_SOURCE_DIR}/lauxlib.c
${lua_SOURCE_DIR}/lbaselib.c
${lua_SOURCE_DIR}/lcode.c
${lua_SOURCE_DIR}/lcorolib.c
${lua_SOURCE_DIR}/lctype.c
${lua_SOURCE_DIR}/ldblib.c
${lua_SOURCE_DIR}/ldebug.c
${lua_SOURCE_DIR}/ldo.c
${lua_SOURCE_DIR}/ldump.c
${lua_SOURCE_DIR}/lfunc.c
${lua_SOURCE_DIR}/lgc.c
${lua_SOURCE_DIR}/linit.c
${lua_SOURCE_DIR}/liolib.c
${lua_SOURCE_DIR}/llex.c
${lua_SOURCE_DIR}/lmathlib.c
${lua_SOURCE_DIR}/lmem.c
${lua_SOURCE_DIR}/loadlib.c
${lua_SOURCE_DIR}/lobject.c
${lua_SOURCE_DIR}/lopcodes.c
${lua_SOURCE_DIR}/loslib.c
${lua_SOURCE_DIR}/lparser.c
${lua_SOURCE_DIR}/lstate.c
${lua_SOURCE_DIR}/lstring.c
${lua_SOURCE_DIR}/lstrlib.c
${lua_SOURCE_DIR}/ltable.c
${lua_SOURCE_DIR}/ltablib.c
${lua_SOURCE_DIR}/ltm.c
${lua_SOURCE_DIR}/lua.c
${lua_SOURCE_DIR}/lundump.c
${lua_SOURCE_DIR}/lutf8lib.c
${lua_SOURCE_DIR}/lvm.c
${lua_SOURCE_DIR}/lzio.c
)
endif()
CPMAddPackage(
@@ -111,7 +152,6 @@ CPMAddPackage(
"ALSOFT_STATIC_LIBGCC ON"
)
# TODO: Clear this paths with *
file(GLOB SERVER_SOURCES
"project/lib_projects/raknet/jni/RaknetSources/*.cpp"
"src/NinecraftApp.cpp"
@@ -150,7 +190,6 @@ file(GLOB SERVER_SOURCES
"src/platform/CThread.cpp"
"src/platform/HttpClient.cpp"
"src/platform/PngLoader.cpp"
"src/platform/time.cpp"
"src/platform/input/Controller.cpp"
@@ -216,6 +255,9 @@ file(GLOB SERVER_SOURCES
"src/world/level/tile/entity/*.cpp"
"src/world/phys/HitResult.cpp"
"src/commands/*.cpp"
"src/plugins/*.cpp"
)
file(GLOB CLIENT_SOURCES
@@ -299,6 +341,10 @@ file(GLOB CLIENT_SOURCES
"src/AppPlatform_glfw.cpp"
"src/main.cpp"
"src/commands/*.cpp"
"src/plugins/*.cpp"
)
if (${PLATFORM} STREQUAL "Desktop")
@@ -306,21 +352,21 @@ if (${PLATFORM} STREQUAL "Desktop")
endif()
# Server
if(UNIX)
add_executable("${PROJECT_NAME}-server" ${SERVER_SOURCES})
add_executable("${PROJECT_NAME}-server" ${SERVER_SOURCES})
set_target_properties("${PROJECT_NAME}-server" PROPERTIES ENABLE_EXPORTS TRUE)
target_compile_definitions("${PROJECT_NAME}-server" PUBLIC "STANDALONE_SERVER" "SERVER_PROFILER")
target_compile_definitions("${PROJECT_NAME}-server" PUBLIC "STANDALONE_SERVER" "SERVER_PROFILER")
target_include_directories("${PROJECT_NAME}-server" PUBLIC
"${CMAKE_SOURCE_DIR}/src/"
"${lua_SOURCE_DIR}/"
target_include_directories("${PROJECT_NAME}-server" PUBLIC
"${CMAKE_SOURCE_DIR}/glad/include/"
"${CMAKE_SOURCE_DIR}/src/"
"project/lib_projects/raknet/jni/RaknetSources"
)
"project/lib_projects/raknet/jni/RaknetSources"
)
target_link_libraries("${PROJECT_NAME}-server" ${CMAKE_THREAD_LIBS_INIT})
endif()
target_link_libraries("${PROJECT_NAME}-server" ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_LIBS} lua sol2::sol2)
add_executable(${PROJECT_NAME} ${CLIENT_SOURCES})
set_target_properties(${PROJECT_NAME} PROPERTIES ENABLE_EXPORTS TRUE)
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PLATFORM_CPP})
@@ -330,6 +376,8 @@ target_include_directories(${PROJECT_NAME} PUBLIC
"${openal_SOURCE_DIR}/include"
"${glfw_SOURCE_DIR}/include"
"lib/include"
"${lua_SOURCE_DIR}/"
)
if(${PLATFORM} MATCHES "Web")
@@ -377,7 +425,7 @@ endif()
# Client
target_compile_definitions(${PROJECT_NAME} PUBLIC "OPENGL_ES" "NO_EGL" ${PLATFORM})
target_link_libraries(${PROJECT_NAME} zlib ${PNG_LIB} OpenAL::OpenAL glfw ${EXTRA_LIBS})
target_link_libraries(${PROJECT_NAME} zlib ${PNG_LIB} OpenAL::OpenAL glfw ${EXTRA_LIBS} lua sol2::sol2)
if (OpenSSL_FOUND)
target_link_libraries(${PROJECT_NAME} OpenSSL::SSL OpenSSL::Crypto)

View File

@@ -110,6 +110,7 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/client/renderer/Textures.cpp \
../../../src/client/renderer/TileRenderer.cpp \
../../../src/client/renderer/gles.cpp \
../../../src/world/level/LevelConstants.cpp \
../../../src/client/renderer/culling/Frustum.cpp \
../../../src/client/renderer/entity/ArrowRenderer.cpp \
../../../src/client/renderer/entity/ChickenRenderer.cpp \
@@ -140,6 +141,12 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/network/Packet.cpp \
../../../src/network/RakNetInstance.cpp \
../../../src/network/ServerSideNetworkHandler.cpp \
../../../src/commands/Command.cpp \
../../../src/commands/CommandHelp.cpp \
../../../src/commands/CommandKick.cpp \
../../../src/commands/CommandBan.cpp \
../../../src/commands/CommandManager.cpp \
../../../src/commands/CommandOp.cpp \
../../../src/server/ServerLevel.cpp \
../../../src/server/ServerPlayer.cpp \
../../../src/util/DataIO.cpp \

View File

@@ -232,6 +232,7 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/world/level/tile/entity/TileEntity.cpp \
../../../src/world/level/tile/entity/FurnaceTileEntity.cpp \
../../../src/world/phys/HitResult.cpp
../../../src/world/level/LevelConstants.cpp
LOCAL_CFLAGS := -Wno-psabi $(LOCAL_CFLAGS)

Binary file not shown.

View File

@@ -129,6 +129,7 @@ public class SoundPlayer
new SoundId(R.raw.eat1, "random.eat"),
new SoundId(R.raw.eat2, "random.eat"),
new SoundId(R.raw.eat3, "random.eat"),
new SoundId(R.raw.burp1, "random.burp"),
new SoundId(R.raw.fuse, "random.fuse"),
new SoundId(R.raw.zpig1, "mob.zombiepig.zpig"),

View File

@@ -140,7 +140,7 @@ RakNet::TimeUS GetTimeUS_Windows( void )
#if _MSC_VER >= 1400 && defined (_M_X64)
GetProcessAffinityMask(mProc, (PDWORD_PTR)&mProcMask, (PDWORD_PTR)&mSysMask);
#else
GetProcessAffinityMask(mProc, &mProcMask, &mSysMask);
GetProcessAffinityMask(mProc, (PDWORD_PTR)&mProcMask, (PDWORD_PTR)&mSysMask);
#endif
mThread = GetCurrentThread();

View File

@@ -142,8 +142,8 @@ void seedMT( unsigned int seed, unsigned int *state, unsigned int *&next, int &l
// so-- that's why the only change I made is to restrict to odd seeds.
//
register unsigned int x = ( seed | 1U ) & 0xFFFFFFFFU, *s = state;
register int j;
unsigned int x = ( seed | 1U ) & 0xFFFFFFFFU, *s = state;
int j;
for ( left = 0, *s++ = x, j = N; --j;
*s++ = ( x *= 69069U ) & 0xFFFFFFFFU )
@@ -154,8 +154,8 @@ void seedMT( unsigned int seed, unsigned int *state, unsigned int *&next, int &l
unsigned int reloadMT( unsigned int *state, unsigned int *&next, int &left )
{
register unsigned int * p0 = state, *p2 = state + 2, *pM = state + M, s0, s1;
register int j;
unsigned int * p0 = state, *p2 = state + 2, *pM = state + M, s0, s1;
int j;
if ( left < -1 )
seedMT( 4357U );

View File

@@ -136,7 +136,7 @@ void NinecraftApp::teardown()
Recipes ::teardownRecipes();
TileEntity::teardownTileEntities();
#endif
#ifdef WIN32
#if defined(WIN32) && !defined(STANDALONE_SERVER)
ItemRenderer::teardown_static();
if (EntityTileRenderer::instance != NULL) {
delete EntityTileRenderer::instance;

View File

@@ -2,6 +2,7 @@
#include "Options.h"
#include "client/Options.h"
#include "client/player/input/IBuildInput.h"
#include "commands/CommandManager.hpp"
#include "platform/input/Keyboard.h"
#include "world/item/Item.h"
#include "world/item/ItemInstance.h"
@@ -91,10 +92,14 @@
#include "../network/command/CommandServer.h"
#include "gamemode/CreatorMode.h"
#ifndef STANDALONE_SERVER
#include "../world/level/GrassColor.h"
#include "renderer/LevelRenderer.h"
#include "particle/ParticleEngine.h"
#endif
#include "../world/level/Level.h"
static void checkGlError(const char* tag) {
#ifdef GLDEBUG
while (1) {
@@ -180,7 +185,8 @@ Minecraft::Minecraft() :
_powerVr(false),
commandPort(4711),
reserved_d1(0),reserved_d2(0),
reserved_f1(0),reserved_f2(0), options(this)
reserved_f1(0),reserved_f2(0), options(this),
m_commandManager()
{
//#ifdef ANDROID
@@ -261,9 +267,10 @@ void Minecraft::selectLevel( const std::string& levelId, const std::string& leve
void Minecraft::setLevel(Level* level, const std::string& message /* ="" */, LocalPlayer* forceInsertPlayer /* = NULL */) {
cameraTargetPlayer = NULL;
LOGI("Seed is %ld\n", level->getSeed());
if (level != NULL) {
LOGI("Seed is %ld\n", level->getSeed());
level->raknetInstance = raknetInstance;
gameMode->initLevel(level);
@@ -280,6 +287,7 @@ void Minecraft::setLevel(Level* level, const std::string& message /* ="" */, Loc
}
}
this->level = level;
_hasSignaledGeneratingLevelFinished = false;
#ifdef STANDALONE_SERVER
const bool threadedLevelCreation = false;
@@ -363,12 +371,12 @@ void Minecraft::prepareLevel(const std::string& title) {
if (!level->isNew())
level->setUpdateLights(false);
int Max = CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH;
int Max = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH;
int pp = 0;
for (int x = 8; x < (CHUNK_CACHE_WIDTH * CHUNK_WIDTH); x += CHUNK_WIDTH) {
for (int z = 8; z < (CHUNK_CACHE_WIDTH * CHUNK_WIDTH); z += CHUNK_WIDTH) {
progressStagePercentage = 100 * pp++ / Max;
//printf("level generation progress %d\n", progressStagePercentage);
for (int x = 8; x < (LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH); x += LevelConstants::CHUNK_WIDTH) {
for (int z = 8; z < (LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH); z += LevelConstants::CHUNK_WIDTH) {
progressStagePercentage = 100 * pp++ / Max;
//printf("level generation progress %d\n", progressStagePercentage);
B.start();
level->getTile(x, 64, z);
B.stop();
@@ -383,9 +391,9 @@ void Minecraft::prepareLevel(const std::string& title) {
level->setUpdateLights(true);
C.start();
for (int x = 0; x < CHUNK_CACHE_WIDTH; x++)
for (int x = 0; x < LevelConstants::CHUNK_CACHE_WIDTH; x++)
{
for (int z = 0; z < CHUNK_CACHE_WIDTH; z++)
for (int z = 0; z < LevelConstants::CHUNK_CACHE_WIDTH; z++)
{
LevelChunk* chunk = level->getChunk(x, z);
if (chunk && !chunk->createdFromSave)
@@ -559,7 +567,7 @@ void Minecraft::tick(int nTick, int maxTick) {
level->tickEntities();
level->tick();
#ifndef STANDALONE_SERVER
TIMER_POP_PUSH("animateTick");
TIMER_POP_PUSH("animateTick");
if (player) {
level->animateTick(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z));
}
@@ -732,6 +740,21 @@ void Minecraft::tickInput() {
if (key == Keyboard::KEY_F3) {
options.toggle(OPTIONS_RENDER_DEBUG);
}
// TODO: replace it with client /give command :face_vomiting:
// if (key == Keyboard::KEY_F4) {
// player->inventory->add(new ItemInstance(Tile::redBrick));
// player->inventory->add(new ItemInstance(Item::ironIngot, 64));
// player->inventory->add(new ItemInstance(Item::ironIngot, 34));
// player->inventory->add(new ItemInstance(Tile::stonecutterBench));
// player->inventory->add(new ItemInstance(Tile::workBench));
// player->inventory->add(new ItemInstance(Tile::furnace));
// player->inventory->add(new ItemInstance(Tile::wood, 54));
// player->inventory->add(new ItemInstance(Item::stick, 14));
// player->inventory->add(new ItemInstance(Item::coal, 31));
// player->inventory->add(new ItemInstance(Tile::sand, 6));
// }
if (key == Keyboard::KEY_F5) {
options.toggle(OPTIONS_THIRD_PERSON_VIEW);
@@ -857,6 +880,7 @@ void Minecraft::tickInput() {
for (int i = 0; i < 5 * SharedConstants::TicksPerSecond; ++i)
level->tick();
}
#endif
}
@@ -882,6 +906,9 @@ void Minecraft::tickInput() {
handleBuildAction(&bai);
} else {
gameMode->stopDestroyBlock();
if (player && player->isUsingItem()) {
gameMode->releaseUsingItem(player);
}
}
} else {
// Desktop: left mouse = destroy/attack
@@ -1132,6 +1159,7 @@ bool Minecraft::supportNonTouchScreen() {
}
void Minecraft::init()
{
LevelChunk::ChunkBlockCount = LevelConstants::CHUNK_BLOCK_COUNT;
#ifndef STANDALONE_SERVER
checkGlError("Init enter");
@@ -1182,6 +1210,8 @@ void Minecraft::init()
checkGlError("Init complete");
#endif
PluginsManager::get().init(*this);
options.load();
setIsCreativeMode(false); // false means it's Survival Mode
@@ -1369,12 +1399,9 @@ bool Minecraft::joinMultiplayerFromString( const std::string& server )
} else {
ip = server;
}
printf("%s \n", port.c_str());
if (isLookingForMultiplayer && netCallback) {
isLookingForMultiplayer = false;
printf("test");
int portNum = atoi(port.c_str());
return raknetInstance->connect(ip.c_str(), portNum);
}
@@ -1682,3 +1709,11 @@ void Minecraft::optionUpdated(OptionId option, int value ) {
setSize(width, height);
}
}
void Minecraft::addMessage(const std::string& msg) {
#ifndef STANDALONE_SERVER
gui.addMessage(msg);
#else
LOGI("%s \n", msg.c_str());
#endif
}

View File

@@ -2,6 +2,9 @@
#define NET_MINECRAFT_CLIENT__Minecraft_H__
#include "Options.h"
#include "commands/CommandManager.hpp"
#include <plugins/PluginsManager.hpp>
#ifndef STANDALONE_SERVER
#include "MouseHandler.h"
#include "gui/Gui.h"
@@ -128,11 +131,17 @@ public:
void optionUpdated(OptionId option, bool value);
void optionUpdated(OptionId option, float value);
void optionUpdated(OptionId option, int value);
int getTicks() { return ticks; }
void addMessage(const std::string& msg);
#ifdef __APPLE__
bool _isSuperFast;
bool isSuperFast() { return _isSuperFast; }
#endif
CommandManager& commandManager() { return m_commandManager; }
protected:
void _levelGenerated();
@@ -205,7 +214,8 @@ public:
std::string externalCacheStoragePath;
protected:
Timer timer;
// @note @attn @warn: this is dangerous as fuck!
// @note @attn @warn: this is dangerous as fuck!
volatile bool isGeneratingLevel;
bool _hasSignaledGeneratingLevelFinished;
@@ -233,6 +243,8 @@ private:
PerfRenderer* _perfRenderer;
CommandServer* _commandServer;
CommandManager m_commandManager;
};
#endif /*NET_MINECRAFT_CLIENT__Minecraft_H__*/

View File

@@ -90,8 +90,12 @@ bool GameMode::useItemOn(Player* player, Level* level, ItemInstance* item, int x
float clickY = hit.y - y;
float clickZ = hit.z - z;
if (level->isClientSide) {
LOGI("%f %f %f \n", player->x, player->y, player->z);
item = player->inventory->getSelected();
UseItemPacket packet(x, y, z, face, item, player->entityId, clickX, clickY, clickZ);
UseItemPacket packet(x, y, z, face, item, player->entityId, clickX, clickY, clickZ, player->x, player->y, player->z,
player->bb.x0, player->bb.y0, player->bb.z0, player->bb.x1, player->bb.y1, player->bb.z1);
minecraft->raknetInstance->send(packet);
}
int t = level->getTile(x, y, z);
@@ -100,7 +104,7 @@ bool GameMode::useItemOn(Player* player, Level* level, ItemInstance* item, int x
return true;
if (item == NULL) return false;
if(isCreativeType()) {
if (isCreativeType()) {
int aux = item->getAuxValue();
int count = item->count;
bool success = item->useOn(player, level, x, y, z, face, clickX, clickY, clickZ);
@@ -117,7 +121,8 @@ bool GameMode::useItem( Player* player, Level* level, ItemInstance* item ) {
ItemInstance* itemInstance = item->use(level, player);
if(level->isClientSide) {
UseItemPacket packet(item, player->entityId, player->aimDirection);
UseItemPacket packet(item, player->entityId, player->aimDirection, player->x, player->y, player->z,
player->bb.x0, player->bb.y0, player->bb.z0, player->bb.x1, player->bb.y1, player->bb.z1);
minecraft->raknetInstance->send(packet);
}
if (itemInstance != item || (itemInstance != NULL && itemInstance->count != oldCount)) {

View File

@@ -68,6 +68,7 @@ bool SurvivalMode::destroyBlock( int x, int y, int z, int face ) {
minecraft->player->inventory->clearSlot(minecraft->player->inventory->selected);
}
}
if (changed && couldDestroy) {
ItemInstance instance(t, 1, data);
Tile::tiles[t]->playerDestroy(minecraft->level, minecraft->player, x, y, z, data);

View File

@@ -224,58 +224,58 @@ void Gui::handleClick(int button, int x, int y) {
}
}
void Gui::handleKeyPressed(int key)
{
bool isChatting = (minecraft->screen && (dynamic_cast<ChatScreen*>(minecraft->screen) || dynamic_cast<ConsoleScreen*>(minecraft->screen)));
if (isChatting) {
// Allow scrolling the chat history with the mouse/keyboard when chat is open
if (key == 38) { // VK_UP
scrollChat(1);
return;
} else if (key == 40) { // VK_DOWN
scrollChat(-1);
return;
} else if (key == 33) { // VK_PRIOR (Page Up)
// Scroll by a page
int screenHeight = (int)(minecraft->height * InvGuiScale);
int maxVisible = (screenHeight - 48) / 9;
scrollChat(maxVisible);
return;
} else if (key == 34) { // VK_NEXT (Page Down)
int screenHeight = (int)(minecraft->height * InvGuiScale);
int maxVisible = (screenHeight - 48) / 9;
scrollChat(-maxVisible);
return;
void Gui::handleKeyPressed(int key)
{
bool isChatting = (minecraft->screen && (dynamic_cast<ChatScreen*>(minecraft->screen) || dynamic_cast<ConsoleScreen*>(minecraft->screen)));
if (isChatting) {
// Allow scrolling the chat history with the mouse/keyboard when chat is open
if (key == 38) { // VK_UP
scrollChat(1);
return;
} else if (key == 40) { // VK_DOWN
scrollChat(-1);
return;
} else if (key == 33) { // VK_PRIOR (Page Up)
// Scroll by a page
int screenHeight = (int)(minecraft->height * InvGuiScale);
int maxVisible = (screenHeight - 48) / 9;
scrollChat(maxVisible);
return;
} else if (key == 34) { // VK_NEXT (Page Down)
int screenHeight = (int)(minecraft->height * InvGuiScale);
int maxVisible = (screenHeight - 48) / 9;
scrollChat(-maxVisible);
return;
}
}
}
if (key == Keyboard::KEY_F1) {
minecraft->options.toggle(OPTIONS_HIDEGUI);
}
if (key == Keyboard::KEY_F1) {
minecraft->options.toggle(OPTIONS_HIDEGUI);
}
if (key == 99)
{
if (minecraft->player->inventory->selected > 0)
if (key == 99)
{
minecraft->player->inventory->selected--;
if (minecraft->player->inventory->selected > 0)
{
minecraft->player->inventory->selected--;
}
}
else if (key == 4)
{
if (minecraft->player->inventory->selected < (getNumSlots() - 2))
{
minecraft->player->inventory->selected++;
}
}
else if (key == 100)
{
minecraft->screenChooser.setScreen(SCREEN_BLOCKSELECTION);
}
else if (key == minecraft->options.getIntValue(OPTIONS_KEY_DROP))
{
minecraft->player->inventory->dropSlot(minecraft->player->inventory->selected, false);
}
}
else if (key == 4)
{
if (minecraft->player->inventory->selected < (getNumSlots() - 2))
{
minecraft->player->inventory->selected++;
}
}
else if (key == 100)
{
minecraft->screenChooser.setScreen(SCREEN_BLOCKSELECTION);
}
else if (key == minecraft->options.getIntValue(OPTIONS_KEY_DROP))
{
minecraft->player->inventory->dropSlot(minecraft->player->inventory->selected, false);
}
}
void Gui::scrollChat(int delta) {
if (delta == 0)
@@ -755,7 +755,6 @@ void Gui::renderDebugInfo() {
// Position
float px = p->x, py = p->y - p->heightOffset, pz = p->z;
posTranslator.to(px, py, pz);
int bx = (int)floorf(px), by = (int)floorf(py), bz = (int)floorf(pz);
int cx = bx >> 4, cz = bz >> 4;
@@ -782,6 +781,25 @@ void Gui::renderDebugInfo() {
long day = worldTime / Level::TICKS_PER_DAY;
long seed = lvl ? lvl->getSeed() : 0;
// Block looking at
std::string CurrentTile = "Air";
if (minecraft->hitResult.type == TILE) {
int LookingX = minecraft->hitResult.x;
int LookingY = minecraft->hitResult.y;
int LookingZ = minecraft->hitResult.z;
int tileID = minecraft->level->getTile(LookingX, LookingY, LookingZ);
if (tileID > 0 && tileID < 256){
Tile* LookingTile = Tile::tiles[tileID];
if (LookingTile != NULL) {
CurrentTile = LookingTile->getDescriptionId();
} else {
CurrentTile = "Unknown Tile";
}
} else {
CurrentTile = "Air";
}
}
// Build lines (NULL entry = blank gap)
Font* font = minecraft->font;
@@ -820,6 +838,9 @@ void Gui::renderDebugInfo() {
sprintf(buf, "Biome: %s", biomeName);
drawString(font, buf, 2, 124, 0xE0E0E0);
sprintf(buf, "Looking at: %s", CurrentTile.c_str());
drawString(font, buf, 2, 134, 0xE0E0E0);
}
else if (minecraft->options.getIntValue(OPTIONS_DEBUG_STYLE) == 1){

View File

@@ -8,6 +8,7 @@
#include "../../../network/ServerSideNetworkHandler.h"
#include "../../../network/packet/ChatPacket.h"
#include "../../../platform/log.h"
#include "util/StringUtils.h"
#include <sstream>
#include <cstdlib>
@@ -54,141 +55,37 @@ void ConsoleScreen::charPressed(char inputChar)
_input += inputChar;
}
// ---------------------------------------------------------------------------
// execute: run _input as a command, print result, close screen
// ---------------------------------------------------------------------------
void ConsoleScreen::execute()
{
if (!minecraft->level) return;
if (_input.empty()) {
minecraft->setScreen(NULL);
return;
return minecraft->setScreen(NULL);
}
if (_input[0] == '/') {
// Command
std::string result = processCommand(_input);
if (!result.empty())
minecraft->gui.addMessage(result);
} else {
// Chat message: <name> message
std::string msg = std::string("<") + minecraft->player->name + "> " + _input;
// if (_input[0] == '/') {
// // Command
// _input = Util::stringTrim(_input.substr(1));
// std::istringstream iss(minecraft->commandManager().execute(*minecraft, *minecraft->player, _input));
// for (std::string line; std::getline(iss, line); ) {
// minecraft->gui.addMessage(line);
// }
// } else {
// @ai @rewrite
if (minecraft->netCallback && minecraft->raknetInstance->isServer()) {
// Hosting a LAN game: displayGameMessage shows locally + broadcasts MessagePacket to clients
static_cast<ServerSideNetworkHandler*>(minecraft->netCallback)->displayGameMessage(msg);
static_cast<ServerSideNetworkHandler*>(minecraft->netCallback)->displayGameMessage(_input);
} else if (minecraft->netCallback) {
// Connected client: send ChatPacket to server; server echoes it back as MessagePacket
ChatPacket chatPkt(msg);
ChatPacket chatPkt(_input);
minecraft->raknetInstance->send(chatPkt);
} else {
// Singleplayer: show locally only
minecraft->gui.addMessage(msg);
minecraft->gui.addMessage("<" + minecraft->player->name + "> " + _input);
}
}
// }
minecraft->setScreen(NULL);
}
// ---------------------------------------------------------------------------
// processCommand
// ---------------------------------------------------------------------------
static std::string trim(const std::string& s) {
size_t a = s.find_first_not_of(" \t");
if (a == std::string::npos) return "";
size_t b = s.find_last_not_of(" \t");
return s.substr(a, b - a + 1);
}
std::string ConsoleScreen::processCommand(const std::string& raw)
{
// strip leading '/'
std::string line = raw;
if (!line.empty() && line[0] == '/') line = line.substr(1);
line = trim(line);
// tokenise
std::vector<std::string> args;
{
std::istringstream ss(line);
std::string tok;
while (ss >> tok) args.push_back(tok);
}
if (args.empty()) return "";
Level* level = minecraft->level;
if (!level) return "No level loaded.";
// -----------------------------------------------------------------------
// /time ...
// -----------------------------------------------------------------------
if (args[0] == "time") {
if (args.size() < 2)
return "Usage: /time <add|set|query> ...";
const std::string& sub = args[1];
// -- time add <value> -----------------------------------------------
if (sub == "add") {
if (args.size() < 3) return "Usage: /time add <value>";
long delta = std::atol(args[2].c_str());
long newTime = level->getTime() + delta;
level->setTime(newTime);
std::ostringstream out;
out << "Set the time to " << (newTime % Level::TICKS_PER_DAY);
return out.str();
}
// -- time set <value|day|night|noon|midnight> -----------------------
if (sub == "set") {
if (args.size() < 3) return "Usage: /time set <value|day|night|noon|midnight>";
const std::string& val = args[2];
long t = -1;
if (val == "day") t = 1000;
else if (val == "noon") t = 6000;
else if (val == "night") t = 13000;
else if (val == "midnight") t = 18000;
else {
// numeric — accept positive integers only
bool numeric = true;
for (char c : val)
if (!std::isdigit((unsigned char)c)) { numeric = false; break; }
if (!numeric) return std::string("Unknown value: ") + val;
t = std::atol(val.c_str());
}
// Preserve the total day count so only the time-of-day changes
long dayCount = level->getTime() / Level::TICKS_PER_DAY;
long newTime = dayCount * Level::TICKS_PER_DAY + (t % Level::TICKS_PER_DAY);
level->setTime(newTime);
std::ostringstream out;
out << "Set the time to " << t;
return out.str();
}
// -- time query <daytime|gametime|day> ------------------------------
if (sub == "query") {
if (args.size() < 3) return "Usage: /time query <daytime|gametime|day>";
const std::string& what = args[2];
long total = level->getTime();
long daytime = total % Level::TICKS_PER_DAY;
long day = total / Level::TICKS_PER_DAY;
std::ostringstream out;
if (what == "daytime") { out << "The time of day is " << daytime; }
else if (what == "gametime") { out << "The game time is " << total; }
else if (what == "day") { out << "The day is " << day; }
else return std::string("Unknown query: ") + what;
return out.str();
}
return "Unknown sub-command. Usage: /time <add|set|query> ...";
}
return std::string("Unknown command: /") + args[0];
}
// ---------------------------------------------------------------------------
// render
// ---------------------------------------------------------------------------

View File

@@ -25,7 +25,6 @@ public:
private:
void execute();
std::string processCommand(const std::string& cmd);
std::string _input;
int _cursorBlink; // tick counter for cursor blink

View File

@@ -16,7 +16,12 @@
#include "../../../../world/level/Level.h"
#include "../../../../world/item/DyePowderItem.h"
#include "../../../../world/item/crafting/Recipe.h"
#include "network/RakNetInstance.h"
#include "network/packet/WantCreatePacket.h"
#include "platform/input/Keyboard.h"
#include <cstdint>
#include <iostream>
#include <string>
static NinePatchLayer* guiPaneFrame = NULL;
@@ -193,6 +198,26 @@ void PaneCraftingScreen::setupPositions() {
}
void PaneCraftingScreen::tick() {
if (minecraft->isOnline()) {
// TODO: Make better algorithm
static std::map<uint8_t, uint16_t> oldMap = {};
std::map<uint8_t, uint16_t> newMap = {};
for (int i = Inventory::MAX_SELECTION_SIZE; i < minecraft->player->inventory->getContainerSize(); ++i) {
auto itm = minecraft->player->inventory->getItem(i);
if (itm != NULL) {
newMap[itm->id] += itm->count;
}
}
if (oldMap != newMap) {
oldMap = newMap;
newMap = {};
recheckRecipes();
}
}
if (pane) pane->tick();
}
@@ -439,25 +464,29 @@ void PaneCraftingScreen::craftSelectedItem()
ItemInstance resultItem = currentItem->item;
if (minecraft->player) {
if (minecraft->isOnline()) {
WantCreatePacket packet(minecraft->player->entityId, resultItem.count, resultItem.getAuxValue(), resultItem.id);
minecraft->raknetInstance->send(packet);
}
// Remove all items required for the recipe and ...
for (unsigned int i = 0; i < currentItem->neededItems.size(); ++i) {
CItem::ReqItem& req = currentItem->neededItems[i];
// If the recipe allows any aux-value as ingredients, first deplete
// aux == 0 from inventory. Since I'm not sure if this always is
// correct, let's only do it for ingredient sandstone for now.
ItemInstance toRemove = req.item;
// If the recipe allows any aux-value as ingredients, first deplete
// aux == 0 from inventory. Since I'm not sure if this always is
// correct, let's only do it for ingredient sandstone for now.
ItemInstance toRemove = req.item;
if (Tile::sandStone->id == req.item.id
&& Recipe::ANY_AUX_VALUE == req.item.getAuxValue()) {
toRemove.setAuxValue(0);
toRemove.count = minecraft->player->inventory->removeResource(toRemove, true);
toRemove.setAuxValue(Recipe::ANY_AUX_VALUE);
}
if (Tile::sandStone->id == req.item.id
&& Recipe::ANY_AUX_VALUE == req.item.getAuxValue()) {
toRemove.setAuxValue(0);
toRemove.count = minecraft->player->inventory->removeResource(toRemove, true);
toRemove.setAuxValue(Recipe::ANY_AUX_VALUE);
}
if (toRemove.count > 0) {
minecraft->player->inventory->removeResource(toRemove);
}
if (toRemove.count > 0) {
minecraft->player->inventory->removeResource(toRemove);
}
}
// ... add the new one! (in this order, to fill empty slots better)
// if it doesn't fit, throw it on the ground!

View File

@@ -40,10 +40,9 @@ HumanoidModel::HumanoidModel( float g /*= 0*/, float yOffset /*= 0*/, int texW /
head.addBox(-4, -8, -4, 8, 8, 8, g); // Head
head.setPos(0, 0 + yOffset, 0);
if (modernSkin) {
hair.addBox(-4, -8, -4, 8, 8, 8, g + 0.5f); // Outer head layer (hat)
hair.setPos(0, 0 + yOffset, 0);
}
hair.addBox(-4, -8, -4, 8, 8, 8, g + 0.5f); // Outer head layer (hat)
hair.setPos(0, 0 + yOffset, 0);
body.addBox(-4, 0, -2, 8, 12, 4, g); // Body
body.setPos(0, 0 + yOffset, 0);
@@ -99,17 +98,17 @@ void HumanoidModel::render(Entity* e, float time, float r, float bob, float yRot
setupAnim(time, r, bob, yRot, xRot, scale);
// Sync overlay with head rotation/position
if (texWidth == 64 && texHeight == 64) {
hair.xRot = head.xRot;
hair.yRot = head.yRot;
hair.zRot = head.zRot;
hair.y = head.y;
}
hair.xRot = head.xRot;
hair.yRot = head.yRot;
hair.zRot = head.zRot;
hair.y = head.y;
head.render(scale);
if (texWidth == 64 && texHeight == 64) {
hair.render(scale);
}
hair.render(scale);
body.render(scale);
arm0.render(scale);
arm1.render(scale);
@@ -123,12 +122,12 @@ void HumanoidModel::render( HumanoidModel* model, float scale )
head.yRot = model->head.yRot;
head.y = model->head.y;
head.xRot = model->head.xRot;
if (texWidth == 64 && texHeight == 64) {
hair.yRot = head.yRot;
hair.xRot = head.xRot;
hair.zRot = head.zRot;
hair.y = head.y;
}
hair.yRot = head.yRot;
hair.xRot = head.xRot;
hair.zRot = head.zRot;
hair.y = head.y;
arm0.xRot = model->arm0.xRot;
arm0.zRot = model->arm0.zRot;
@@ -273,7 +272,7 @@ void HumanoidModel::onGraphicsReset()
arm1.onGraphicsReset();
leg0.onGraphicsReset();
leg1.onGraphicsReset();
//hair.onGraphicsReset();
hair.onGraphicsReset();
}
//void renderHair(float scale) {

View File

@@ -355,7 +355,11 @@ LocalPlayer::LocalPlayer(Minecraft* minecraft, Level* level, const std::string&
armorTypeHash(0),
sprinting(false),
sprintDoubleTapTimer(0),
prevForwardHeld(false)
prevForwardHeld(false),
xBob(0.0f),
yBob(0.0f),
xBobO(0.0f),
yBobO(0.0f)
{
this->dimension = dimension;
_init();
@@ -456,7 +460,7 @@ void LocalPlayer::tick() {
{
sentInventoryItemId = newItemId;
sentInventoryItemData = newItemData;
PlayerEquipmentPacket packet(entityId, newItemId, newItemData);
PlayerEquipmentPacket packet(entityId, newItemId, newItemData, inventory->selected, inventory->getSlot(newItemId, newItemData));
minecraft->raknetInstance->send(packet);
}
}
@@ -550,6 +554,10 @@ void LocalPlayer::aiStep() {
//if (onGround && abilities.flying)
// abilities.flying = false;
yBobO = yBob;
xBobO = xBob;
xBob += (xRot - xBob) * 0.5;
yBob += (yRot - yBob) * 0.5;
if (interpolateOnly())
updateAi();

View File

@@ -22,6 +22,10 @@ public:
virtual void reset();
void tick();
float yBob, xBob; // shredder added from b1.8/4j for the hand swaying animation
float yBobO, xBobO; // shredder added from b1.8/4j for the hand swaying animation
void move(float xa, float ya, float za);
void aiStep();

View File

@@ -347,6 +347,7 @@ void GameRenderer::renderLevel(float a) {
Lighting::turnOff();
glDisable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Lighting::turnOff();
setupFog(0);
glEnable2(GL_BLEND);
glDisable2(GL_CULL_FACE);

View File

@@ -280,6 +280,9 @@ void ItemInHandRenderer::render( float a )
float h = oHeight + (height - oHeight) * a;
Player* player = mc->player;
// if (selectedTile==NULL) return;
LocalPlayer* localPlayer = (LocalPlayer*)(player);
float xr = player->xRotO + (player->xRot - player->xRotO) * a; // shredder added for hand swaying
glPushMatrix2();
glRotatef2(player->xRotO + (player->xRot - player->xRotO) * a, 1, 0, 0);
@@ -288,6 +291,16 @@ void ItemInHandRenderer::render( float a )
Lighting::turnOn(mc);
glPopMatrix2();
if (localPlayer) // shredder added, basically does the hand swaying animation from b1.8
{
float xrr = localPlayer->xBobO + (localPlayer->xBob - localPlayer->xBobO) * a;
float yrr = localPlayer->yBobO + (localPlayer->yBob - localPlayer->yBobO) * a;
// 4J - was using player->xRot and yRot directly here rather than interpolating between old & current with a
float yr = player->yRotO + (player->yRot - player->yRotO) * a;
glRotatef((xr - xrr) * 0.1f, 1, 0, 0);
glRotatef((yr - yrr) * 0.1f, 0, 1, 0);
}
float br = mc->level->getBrightness(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z));
ItemInstance* item;// = selectedItem;

View File

@@ -69,7 +69,7 @@ LevelRenderer::LevelRenderer( Minecraft* mc)
destroyProgress(0)
{
#ifdef OPENGL_ES
int maxChunksWidth = 2 * LEVEL_WIDTH / CHUNK_SIZE + 1;
int maxChunksWidth = 2 * LevelConstants::LEVEL_WIDTH / CHUNK_SIZE + 1;
numListsOrBuffers = maxChunksWidth * maxChunksWidth * (128/CHUNK_SIZE) * 3;
chunkBuffers = new GLuint[numListsOrBuffers];
glGenBuffers2(numListsOrBuffers, chunkBuffers);
@@ -339,15 +339,15 @@ int LevelRenderer::render( Mob* player, int layer, float alpha )
allChanged();
}
int currentFogType = mc->options.getIntValue(OPTIONS_FOG_TYPE);
if (currentFogType != lastFogType) {
lastFogType = currentFogType;
if (level && level->dimension) {
level->dimension->FogType = currentFogType; // use new fog stuff
}
allChanged();
int currentFogType = mc->options.getIntValue(OPTIONS_FOG_TYPE);
if (currentFogType != lastFogType) {
lastFogType = currentFogType;
if (level && level->dimension) {
level->dimension->FogType = currentFogType; // use new fog stuff
}
allChanged();
}
bool SmoothLightState = mc->options.getBooleanValue(OPTIONS_AMBIENT_OCCLUSION);
if (SmoothLightState != mc->useAmbientOcclusion){
@@ -1073,56 +1073,56 @@ std::string LevelRenderer::gatherStats1() {
// int[] toRender = new int[50000];
// IntBuffer resultBuffer = MemoryTracker.createIntBuffer(64);
void LevelRenderer::generateStars() {
// ported from java beta again,
// converted the doubles into floats to be consistent, shouldnt affect much - shredder
Random random = Random(10842L);
Tesselator& t = Tesselator::instance;
t.begin();
starVertexCount = 0;
for (int i = 0; i < 1500; i++) {
float d = random.nextFloat() * 2.0F - 1.0F;
float e = random.nextFloat() * 2.0F - 1.0F;
float f = random.nextFloat() * 2.0F - 1.0F;
float g = 0.25F + random.nextFloat() * 0.25F;
float h = d * d + e * e + f * f;
if (h < 1.0 && h > 0.01) {
h = 1.0 / Mth::sqrt(h);
d *= h;
e *= h;
f *= h;
float j = d * 100.0;
float k = e * 100.0;
float l = f * 100.0;
float m = Mth::atan2(d, f);
float n = Mth::sin(m);
float o = Mth::cos(m);
float p = Mth::atan2(Mth::sqrt(d * d + f * f), e);
float q = Mth::sin(p);
float r = Mth::cos(p);
float s = random.nextDouble() * Mth::PI * 2.0;
float t2 = Mth::sin(s);
float u = Mth::cos(s);
for (int v = 0; v < 4; v++) {
float w = 0.0;
float x = ((v & 2) - 1) * g;
float y = ((v + 1 & 2) - 1) * g;
float aa = x * u - y * t2;
float ab = y * u + x * t2;
float ad = aa * q + w * r;
float ae = w * q - aa * r;
float af = ae * n - ab * o;
float ah = ab * n + ae * o;
t.vertex(j + af, k + ad, l + ah);
}
starVertexCount += 4;
}
}
t.end(true, starBuffer);
void LevelRenderer::generateStars() {
// ported from java beta again,
// converted the doubles into floats to be consistent, shouldnt affect much - shredder
Random random = Random(10842L);
Tesselator& t = Tesselator::instance;
t.begin();
starVertexCount = 0;
for (int i = 0; i < 1500; i++) {
float d = random.nextFloat() * 2.0F - 1.0F;
float e = random.nextFloat() * 2.0F - 1.0F;
float f = random.nextFloat() * 2.0F - 1.0F;
float g = 0.25F + random.nextFloat() * 0.25F;
float h = d * d + e * e + f * f;
if (h < 1.0 && h > 0.01) {
h = 1.0 / Mth::sqrt(h);
d *= h;
e *= h;
f *= h;
float j = d * 100.0;
float k = e * 100.0;
float l = f * 100.0;
float m = Mth::atan2(d, f);
float n = Mth::sin(m);
float o = Mth::cos(m);
float p = Mth::atan2(Mth::sqrt(d * d + f * f), e);
float q = Mth::sin(p);
float r = Mth::cos(p);
float s = random.nextDouble() * Mth::PI * 2.0;
float t2 = Mth::sin(s);
float u = Mth::cos(s);
for (int v = 0; v < 4; v++) {
float w = 0.0;
float x = ((v & 2) - 1) * g;
float y = ((v + 1 & 2) - 1) * g;
float aa = x * u - y * t2;
float ab = y * u + x * t2;
float ad = aa * q + w * r;
float ae = w * q - aa * r;
float af = ae * n - ab * o;
float ah = ab * n + ae * o;
t.vertex(j + af, k + ad, l + ah);
}
starVertexCount += 4;
}
}
t.end(true, starBuffer);
}
void LevelRenderer::renderSky(float alpha) {
if (mc->level->dimension->foggy) return;
@@ -1155,100 +1155,100 @@ void LevelRenderer::renderSky(float alpha) {
#ifdef OPENGL_ES
drawArrayVT(skyBuffer, skyVertexCount);
#endif
glDisable(GL_FOG);
glDisable(GL_ALPHA_TEST);
// re ported this again from beta 1.6.6, thanks to the mcpe 0.1 decomp team's code for some bit of help about the void layer - shredder
// Sunrise
if (mc->options.getBooleanValue(OPTIONS_BEAUTIFUL_SKY)) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Lighting::turnOff();
float* c = level->dimension->getSunriseColor(level->getTimeOfDay(alpha), alpha);
if (c != nullptr)
{
glDisable(GL_TEXTURE_2D);
// glShadeModel(GL_SMOOTH); //
glPushMatrix();
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
glRotatef(level->getTimeOfDay(alpha) > 0.5f ? 180 : 0, 0.0f, 0.0f, 1.0f);
t.begin(GL_TRIANGLE_FAN);
t.color(c[0], c[1], c[2], c[3]);
t.vertex(0.0f, 100.0f, 0.0f);
t.color(c[0], c[1], c[2], 0.0f);
int steps = 16;
for (int i = 0; i <= steps; i++)
{
float a = i * 3.1415927f * 2.0f / steps;
float sin = Mth::sin(a);
float cos = Mth::cos(a);
t.vertex((sin * 120.0f), (cos * 120.0f), (-cos * 40.0f * c[3]));
}
t.draw();
glPopMatrix();
// glShadeModel(GL_FLAT); //
}
// gets the time of day and rotates the sun and moon png based on the time
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDisable(GL_FOG);
glDisable(GL_ALPHA_TEST);
// re ported this again from beta 1.6.6, thanks to the mcpe 0.1 decomp team's code for some bit of help about the void layer - shredder
// Sunrise
if (mc->options.getBooleanValue(OPTIONS_BEAUTIFUL_SKY)) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Lighting::turnOff();
float* c = level->dimension->getSunriseColor(level->getTimeOfDay(alpha), alpha);
if (c != nullptr)
{
glDisable(GL_TEXTURE_2D);
// glShadeModel(GL_SMOOTH); //
glPushMatrix();
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
glRotatef(level->getTimeOfDay(alpha) > 0.5f ? 180 : 0, 0.0f, 0.0f, 1.0f);
t.begin(GL_TRIANGLE_FAN);
t.color(c[0], c[1], c[2], c[3]);
t.vertex(0.0f, 100.0f, 0.0f);
t.color(c[0], c[1], c[2], 0.0f);
int steps = 16;
for (int i = 0; i <= steps; i++)
{
float a = i * 3.1415927f * 2.0f / steps;
float sin = Mth::sin(a);
float cos = Mth::cos(a);
t.vertex((sin * 120.0f), (cos * 120.0f), (-cos * 40.0f * c[3]));
}
t.draw();
glPopMatrix();
// glShadeModel(GL_FLAT); //
}
// gets the time of day and rotates the sun and moon png based on the time
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glPushMatrix();
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glTranslatef(sc.x, sc.y, sc.z);
glRotatef(0.0f, 0.0f, 0.0f, 1.0f);
glRotatef(level->getTimeOfDay(alpha) * 360.0f, 1.0f, 0.0f, 0.0f);
float ss = 30.0f;
textures->loadAndBindTexture("terrain/sun.png");
t.begin();
t.vertexUV(-ss, 100.0f, -ss, 0.0f, 0.0f);
t.vertexUV(ss, 100.0f, -ss, 1.0f, 0.0f);
t.vertexUV(ss, 100.0f, ss, 1.0f, 1.0f);
t.vertexUV(-ss, 100.0f, ss, 0.0f, 1.0f);
t.draw();
ss = 20.0f;
textures->loadAndBindTexture("terrain/moon.png");
t.begin();
t.vertexUV(-ss, -100.0f, ss, 1.0f, 1.0f);
t.vertexUV(ss, -100.0f, ss, 0.0f, 1.0f);
t.vertexUV(ss, -100.0f, -ss, 0.0f, 0.0f);
t.vertexUV(-ss, -100.0f, -ss, 1.0f, 0.0f);
t.draw();
glDisable(GL_TEXTURE_2D);
float a = level->getStarBrightness(alpha);
if (a > 0.0f)
{
glColor4f(a, a, a, a);
drawArrayVT(starBuffer, starVertexCount);
}
}
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glDisable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glEnable(GL_FOG);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glTranslatef(sc.x, sc.y, sc.z);
glRotatef(0.0f, 0.0f, 0.0f, 1.0f);
glRotatef(level->getTimeOfDay(alpha) * 360.0f, 1.0f, 0.0f, 0.0f);
float ss = 30.0f;
textures->loadAndBindTexture("terrain/sun.png");
t.begin();
t.vertexUV(-ss, 100.0f, -ss, 0.0f, 0.0f);
t.vertexUV(ss, 100.0f, -ss, 1.0f, 0.0f);
t.vertexUV(ss, 100.0f, ss, 1.0f, 1.0f);
t.vertexUV(-ss, 100.0f, ss, 0.0f, 1.0f);
t.draw();
ss = 20.0f;
textures->loadAndBindTexture("terrain/moon.png");
t.begin();
t.vertexUV(-ss, -100.0f, ss, 1.0f, 1.0f);
t.vertexUV(ss, -100.0f, ss, 0.0f, 1.0f);
t.vertexUV(ss, -100.0f, -ss, 0.0f, 0.0f);
t.vertexUV(-ss, -100.0f, -ss, 1.0f, 0.0f);
t.draw();
glDisable(GL_TEXTURE_2D);
float a = level->getStarBrightness(alpha);
if (a > 0.0f)
{
glColor4f(a, a, a, a);
drawArrayVT(starBuffer, starVertexCount);
}
}
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glDisable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glEnable(GL_FOG);
glPopMatrix();
// ported over void plane (the blue bottom plane seen in java) because pocket edition lacks it @TODO test if it's buggy - shredder
// glColor3f(sc.x * 0.2f + 0.04f, sc.y * 0.2f + 0.04f, sc.z * 0.6f + 0.1f);
glColor4f(sc.x * 0.2f + 0.04f, sc.y * 0.2f + 0.04f, sc.z * 0.6f + 0.1f, 1.0f);
glDisable(GL_TEXTURE_2D);
if(mc->options.getBooleanValue(OPTIONS_BETA_SKY)){
drawArrayVT(voidBuffer, voidVertexCount);
}
// glColor3f(sc.x * 0.2f + 0.04f, sc.y * 0.2f + 0.04f, sc.z * 0.6f + 0.1f);
glColor4f(sc.x * 0.2f + 0.04f, sc.y * 0.2f + 0.04f, sc.z * 0.6f + 0.1f, 1.0f);
glDisable(GL_TEXTURE_2D);
if(mc->options.getBooleanValue(OPTIONS_BETA_SKY)){
drawArrayVT(voidBuffer, voidVertexCount);
}
glEnable(GL_TEXTURE_2D);
// @TODO shredder - should not enable or disable depth mask if using legacy sky because mcpe sky rendering is awful and will render clouds above terrain
@@ -1311,194 +1311,195 @@ void LevelRenderer::renderClouds( float alpha ) {
glEnable(GL_CULL_FACE);
}
void LevelRenderer::renderAdvancedClouds(float alpha) {
// ported from java beta, tesselation code for the 3d clouds, renders broken if mcpe sky rendering option is used - shredder
glDisable(GL_CULL_FACE);
float px = mc->player->xOld + (mc->player->x - mc->player->xOld) * alpha;
float py = mc->player->yOld + (mc->player->y - mc->player->yOld) * alpha;
float pz = mc->player->zOld + (mc->player->z - mc->player->zOld) * alpha;
Tesselator& t = Tesselator::instance;
float ss = 12.0f;
float h = 4.0f;
float cloudTime = (float)ticks + alpha;
float xo = (px + cloudTime * 0.03f) / ss;
float zo = pz / ss + 0.33f;
float yy = 108.0f - py + 0.33f;
int xWraps = Mth::floor(xo / 2048.0);
int zWraps = Mth::floor(zo / 2048.0);
xo -= xWraps * 2048;
zo -= zWraps * 2048;
textures->loadAndBindTexture("environment/clouds.png");
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Vec3 cc = level->getCloudColor(alpha);
float cr = cc.x;
float cg = cc.y;
float cb = cc.z;
float uvScale = 1.0f / 256.0f;
float uo = (float)Mth::floor(xo) * uvScale;
float vo = (float)Mth::floor(zo) * uvScale;
float xOffs = (float)(xo - Mth::floor(xo));
float zOffs = (float)(zo - Mth::floor(zo));
int D = 8;
int radius = 3;
float e = 1.0f / 1024.0f;
glPushMatrix();
glScalef(ss, 1.0f, ss);
for (int pass = 0; pass < 2; pass++) {
if (pass == 0) glColorMask(false, false, false, false);
else glColorMask(true, true, true, true);
for (int xPos = -radius + 1; xPos <= radius; xPos++) {
for (int zPos = -radius + 1; zPos <= radius; zPos++) {
t.begin();
float xx = (float)(xPos * D);
float zz = (float)(zPos * D);
float xp = xx - xOffs;
float zp = zz - zOffs;
if (yy > -h - 1.0f) {
t.color(cr * 0.7f, cg * 0.7f, cb * 0.7f, 0.8f);
t.normal(0.0f, -1.0f, 0.0f);
t.vertexUV(xp + 0, yy + 0, zp + D, (xx + 0) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + D, yy + 0, zp + D, (xx + D) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + D, yy + 0, zp + 0, (xx + D) * uvScale + uo, (zz + 0) * uvScale + vo);
t.vertexUV(xp + 0, yy + 0, zp + 0, (xx + 0) * uvScale + uo, (zz + 0) * uvScale + vo);
}
if (yy <= h + 1.0f) {
t.color(cr, cg, cb, 0.8f);
t.normal(0.0f, 1.0f, 0.0f);
t.vertexUV(xp + 0, yy + h - e, zp + D, (xx + 0) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + D, yy + h - e, zp + D, (xx + D) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + D, yy + h - e, zp + 0, (xx + D) * uvScale + uo, (zz + 0) * uvScale + vo);
t.vertexUV(xp + 0, yy + h - e, zp + 0, (xx + 0) * uvScale + uo, (zz + 0) * uvScale + vo);
}
t.color(cr * 0.9f, cg * 0.9f, cb * 0.9f, 0.8f);
if (xPos > -1) {
t.normal(-1.0f, 0.0f, 0.0f);
for (int i = 0; i < D; i++) {
t.vertexUV(xp + i + 0, yy + 0, zp + D, (xx + i + 0.5f) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + i + 0, yy + h, zp + D, (xx + i + 0.5f) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + i + 0, yy + h, zp + 0, (xx + i + 0.5f) * uvScale + uo, (zz + 0) * uvScale + vo);
t.vertexUV(xp + i + 0, yy + 0, zp + 0, (xx + i + 0.5f) * uvScale + uo, (zz + 0) * uvScale + vo);
}
}
if (xPos <= 1) {
t.normal(1.0f, 0.0f, 0.0f);
for (int i = 0; i < D; i++) {
t.vertexUV(xp + i + 1 - e, yy + 0, zp + D, (xx + i + 0.5f) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + i + 1 - e, yy + h, zp + D, (xx + i + 0.5f) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + i + 1 - e, yy + h, zp + 0, (xx + i + 0.5f) * uvScale + uo, (zz + 0) * uvScale + vo);
t.vertexUV(xp + i + 1 - e, yy + 0, zp + 0, (xx + i + 0.5f) * uvScale + uo, (zz + 0) * uvScale + vo);
}
}
t.color(cr * 0.8f, cg * 0.8f, cb * 0.8f, 0.8f);
if (zPos > -1) {
t.normal(0.0f, 0.0f, -1.0f);
for (int i = 0; i < D; i++) {
t.vertexUV(xp + 0, yy + h, zp + i + 0, (xx + 0) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + D, yy + h, zp + i + 0, (xx + D) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + D, yy + 0, zp + i + 0, (xx + D) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + 0, yy + 0, zp + i + 0, (xx + 0) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
}
}
if (zPos <= 1) {
t.normal(0.0f, 0.0f, 1.0f);
for (int i = 0; i < D; i++) {
t.vertexUV(xp + 0, yy + h, zp + i + 1 - e, (xx + 0) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + D, yy + h, zp + i + 1 - e, (xx + D) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + D, yy + 0, zp + i + 1 - e, (xx + D) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + 0, yy + 0, zp + i + 1 - e, (xx + 0) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
}
}
t.endOverrideAndDraw();
}
}
}
glPopMatrix();
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
void LevelRenderer::renderAdvancedClouds(float alpha) {
// ported from java beta, tesselation code for the 3d clouds, renders broken if mcpe sky rendering option is used - shredder
glDisable(GL_CULL_FACE);
float px = mc->player->xOld + (mc->player->x - mc->player->xOld) * alpha;
float py = mc->player->yOld + (mc->player->y - mc->player->yOld) * alpha;
float pz = mc->player->zOld + (mc->player->z - mc->player->zOld) * alpha;
Tesselator& t = Tesselator::instance;
float ss = 12.0f;
float h = 4.0f;
float cloudTime = (float)ticks + alpha;
float xo = (px + cloudTime * 0.03f) / ss;
float zo = pz / ss + 0.33f;
float yy = 108.0f - py + 0.33f;
int xWraps = Mth::floor(xo / 2048.0);
int zWraps = Mth::floor(zo / 2048.0);
xo -= xWraps * 2048;
zo -= zWraps * 2048;
textures->loadAndBindTexture("environment/clouds.png");
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Vec3 cc = level->getCloudColor(alpha);
float cr = cc.x;
float cg = cc.y;
float cb = cc.z;
float uvScale = 1.0f / 256.0f;
float uo = (float)Mth::floor(xo) * uvScale;
float vo = (float)Mth::floor(zo) * uvScale;
float xOffs = (float)(xo - Mth::floor(xo));
float zOffs = (float)(zo - Mth::floor(zo));
int D = 8;
int radius = 3;
float e = 1.0f / 1024.0f;
glPushMatrix();
glScalef(ss, 1.0f, ss);
for (int pass = 0; pass < 2; pass++) {
if (pass == 0) glColorMask(false, false, false, false);
else glColorMask(true, true, true, true);
for (int xPos = -radius + 1; xPos <= radius; xPos++) {
for (int zPos = -radius + 1; zPos <= radius; zPos++) {
t.begin();
float xx = (float)(xPos * D);
float zz = (float)(zPos * D);
float xp = xx - xOffs;
float zp = zz - zOffs;
if (yy > -h - 1.0f) {
t.color(cr * 0.7f, cg * 0.7f, cb * 0.7f, 0.8f);
t.normal(0.0f, -1.0f, 0.0f);
t.vertexUV(xp + 0, yy + 0, zp + D, (xx + 0) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + D, yy + 0, zp + D, (xx + D) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + D, yy + 0, zp + 0, (xx + D) * uvScale + uo, (zz + 0) * uvScale + vo);
t.vertexUV(xp + 0, yy + 0, zp + 0, (xx + 0) * uvScale + uo, (zz + 0) * uvScale + vo);
}
if (yy <= h + 1.0f) {
t.color(cr, cg, cb, 0.8f);
t.normal(0.0f, 1.0f, 0.0f);
t.vertexUV(xp + 0, yy + h - e, zp + D, (xx + 0) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + D, yy + h - e, zp + D, (xx + D) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + D, yy + h - e, zp + 0, (xx + D) * uvScale + uo, (zz + 0) * uvScale + vo);
t.vertexUV(xp + 0, yy + h - e, zp + 0, (xx + 0) * uvScale + uo, (zz + 0) * uvScale + vo);
}
t.color(cr * 0.9f, cg * 0.9f, cb * 0.9f, 0.8f);
if (xPos > -1) {
t.normal(-1.0f, 0.0f, 0.0f);
for (int i = 0; i < D; i++) {
t.vertexUV(xp + i + 0, yy + 0, zp + D, (xx + i + 0.5f) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + i + 0, yy + h, zp + D, (xx + i + 0.5f) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + i + 0, yy + h, zp + 0, (xx + i + 0.5f) * uvScale + uo, (zz + 0) * uvScale + vo);
t.vertexUV(xp + i + 0, yy + 0, zp + 0, (xx + i + 0.5f) * uvScale + uo, (zz + 0) * uvScale + vo);
}
}
if (xPos <= 1) {
t.normal(1.0f, 0.0f, 0.0f);
for (int i = 0; i < D; i++) {
t.vertexUV(xp + i + 1 - e, yy + 0, zp + D, (xx + i + 0.5f) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + i + 1 - e, yy + h, zp + D, (xx + i + 0.5f) * uvScale + uo, (zz + D) * uvScale + vo);
t.vertexUV(xp + i + 1 - e, yy + h, zp + 0, (xx + i + 0.5f) * uvScale + uo, (zz + 0) * uvScale + vo);
t.vertexUV(xp + i + 1 - e, yy + 0, zp + 0, (xx + i + 0.5f) * uvScale + uo, (zz + 0) * uvScale + vo);
}
}
t.color(cr * 0.8f, cg * 0.8f, cb * 0.8f, 0.8f);
if (zPos > -1) {
t.normal(0.0f, 0.0f, -1.0f);
for (int i = 0; i < D; i++) {
t.vertexUV(xp + 0, yy + h, zp + i + 0, (xx + 0) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + D, yy + h, zp + i + 0, (xx + D) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + D, yy + 0, zp + i + 0, (xx + D) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + 0, yy + 0, zp + i + 0, (xx + 0) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
}
}
if (zPos <= 1) {
t.normal(0.0f, 0.0f, 1.0f);
for (int i = 0; i < D; i++) {
t.vertexUV(xp + 0, yy + h, zp + i + 1 - e, (xx + 0) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + D, yy + h, zp + i + 1 - e, (xx + D) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + D, yy + 0, zp + i + 1 - e, (xx + D) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
t.vertexUV(xp + 0, yy + 0, zp + i + 1 - e, (xx + 0) * uvScale + uo, (zz + i + 0.5f) * uvScale + vo);
}
}
t.endOverrideAndDraw();
}
}
}
glPopMatrix();
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
}
void LevelRenderer::playSound(const std::string& name, float x, float y, float z, float volume, float pitch) {
// @todo: deny sounds here if sound is off (rather than waiting 'til SoundEngine)
float dd = 16;
if (volume > 1) dd *= volume;
if (mc->cameraTargetPlayer->distanceToSqr(x, y, z) < dd * dd) {
mc->soundEngine->play(name, x, y, z, volume, pitch);
}
if (volume > 1) dd *= volume;
if (mc->cameraTargetPlayer != NULL && mc->cameraTargetPlayer->distanceToSqr(x, y, z) < dd * dd) {
mc->soundEngine->play(name, x, y, z, volume, pitch);
}
}
void LevelRenderer::addParticle(const std::string& name, float x, float y, float z, float xa, float ya, float za, int data) {
if (mc->cameraTargetPlayer != NULL) {
float xd = mc->cameraTargetPlayer->x - x;
float yd = mc->cameraTargetPlayer->y - y;
float zd = mc->cameraTargetPlayer->z - z;
float distanceSquared = xd * xd + yd * yd + zd * zd;
float xd = mc->cameraTargetPlayer->x - x;
float yd = mc->cameraTargetPlayer->y - y;
float zd = mc->cameraTargetPlayer->z - z;
float distanceSquared = xd * xd + yd * yd + zd * zd;
//Particle* p = NULL;
//if (name == "hugeexplosion") p = new HugeExplosionSeedParticle(level, x, y, z, xa, ya, za);
//else if (name == "largeexplode") p = new HugeExplosionParticle(textures, level, x, y, z, xa, ya, za);
//Particle* p = NULL;
//if (name == "hugeexplosion") p = new HugeExplosionSeedParticle(level, x, y, z, xa, ya, za);
//else if (name == "largeexplode") p = new HugeExplosionParticle(textures, level, x, y, z, xa, ya, za);
//if (p) {
// if (distanceSquared < 32 * 32) {
// mc->particleEngine->add(p);
// } else { delete p; }
// return;
//}
//if (p) {
// if (distanceSquared < 32 * 32) {
// mc->particleEngine->add(p);
// } else { delete p; }
// return;
//}
const float particleDistance = 16;
if (distanceSquared > particleDistance * particleDistance) return;
const float particleDistance = 16;
if (distanceSquared > particleDistance * particleDistance) return;
//static Stopwatch sw;
//sw.start();
//static Stopwatch sw;
//sw.start();
if (name == "bubble") mc->particleEngine->add(new BubbleParticle(level, x, y, z, xa, ya, za));
else if (name == "crit") mc->particleEngine->add(new CritParticle2(level, x, y, z, xa, ya, za));
else if (name == "smoke") mc->particleEngine->add(new SmokeParticle(level, x, y, z, xa, ya, za));
//else if (name == "note") mc->particleEngine->add(new NoteParticle(level, x, y, z, xa, ya, za));
else if (name == "explode") mc->particleEngine->add(new ExplodeParticle(level, x, y, z, xa, ya, za));
else if (name == "flame") mc->particleEngine->add(new FlameParticle(level, x, y, z, xa, ya, za));
else if (name == "lava") mc->particleEngine->add(new LavaParticle(level, x, y, z));
//else if (name == "splash") mc->particleEngine->add(new SplashParticle(level, x, y, z, xa, ya, za));
else if (name == "largesmoke") mc->particleEngine->add(new SmokeParticle(level, x, y, z, xa, ya, za, 2.5f));
else if (name == "reddust") mc->particleEngine->add(new RedDustParticle(level, x, y, z, xa, ya, za));
else if (name == "iconcrack") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, xa, ya, za, Item::items[data]));
else if (name == "snowballpoof") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::snowBall));
//else if (name == "snowballpoof") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::snowBall));
//else if (name == "slime") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::slimeBall));
//else if (name == "heart") mc->particleEngine->add(new HeartParticle(level, x, y, z, xa, ya, za));
if (name == "bubble") mc->particleEngine->add(new BubbleParticle(level, x, y, z, xa, ya, za));
else if (name == "crit") mc->particleEngine->add(new CritParticle2(level, x, y, z, xa, ya, za));
else if (name == "smoke") mc->particleEngine->add(new SmokeParticle(level, x, y, z, xa, ya, za));
//else if (name == "note") mc->particleEngine->add(new NoteParticle(level, x, y, z, xa, ya, za));
else if (name == "explode") mc->particleEngine->add(new ExplodeParticle(level, x, y, z, xa, ya, za));
else if (name == "flame") mc->particleEngine->add(new FlameParticle(level, x, y, z, xa, ya, za));
else if (name == "lava") mc->particleEngine->add(new LavaParticle(level, x, y, z));
//else if (name == "splash") mc->particleEngine->add(new SplashParticle(level, x, y, z, xa, ya, za));
else if (name == "largesmoke") mc->particleEngine->add(new SmokeParticle(level, x, y, z, xa, ya, za, 2.5f));
else if (name == "reddust") mc->particleEngine->add(new RedDustParticle(level, x, y, z, xa, ya, za));
else if (name == "iconcrack") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, xa, ya, za, Item::items[data]));
else if (name == "snowballpoof") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::snowBall));
//else if (name == "snowballpoof") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::snowBall));
//else if (name == "slime") mc->particleEngine->add(new BreakingItemParticle(level, x, y, z, Item::slimeBall));
//else if (name == "heart") mc->particleEngine->add(new HeartParticle(level, x, y, z, xa, ya, za));
//sw.stop();
//sw.printEvery(50, "add-particle-string");
//sw.stop();
//sw.printEvery(50, "add-particle-string");
}
}
/*

View File

@@ -133,6 +133,8 @@ void EntityRenderer::postRender(Entity* entity, float x, float y, float z, float
}
if (entity->isOnFire()) renderFlame(entity, x, y, z, a);
}
// duplicate renderflame below is the pre b1.6.6 way flame rendered on player and mobs, probs gonna make it an option. - shredder
/*
void EntityRenderer::renderFlame(Entity* e, float x, float y, float z, float a) {
glDisable(GL_LIGHTING);
int tex = ((Tile*)Tile::fire)->tex;
@@ -178,6 +180,75 @@ void EntityRenderer::renderFlame(Entity* e, float x, float y, float z, float a)
glPopMatrix2();
glEnable2(GL_LIGHTING);
}
*/
// new renderflame ported from b1.6.6, fixes player height offset and also uses the newer style - shredder
void EntityRenderer::renderFlame(Entity* e, float x, float y, float z, float a) {
glDisable(GL_LIGHTING);
int tex = ((Tile*)Tile::fire)->tex;
int xt = (tex & 0xf) << 4;
int yt = tex & 0xf0;
float u0 = (xt) / 256.0f;
float u1 = (xt + 15.99f) / 256.0f;
float v0 = (yt) / 256.0f;
float v1 = (yt + 15.99f) / 256.0f;
glPushMatrix2();
glTranslatef2((float) x, (float) y, (float) z);
float s = e->bbWidth * 1.4f;
glScalef2(s, s, s);
bindTexture("terrain.png");
Tesselator& t = Tesselator::instance;
float r = 0.5f;
float xo = 0.0f;
float h = e->bbHeight / s;
float yo = (float)(e->y - e->bb.y0) / s;
glRotatef2(-entityRenderDispatcher->playerRotY, 0, 1, 0);
glTranslatef2(0, 0, -0.3f + ((int) h) * 0.02f);
glColor4f2(1, 1, 1, 1);
float zo = 0.0f;
int cycle_counter = 0;
t.begin();
while (h > 0.0f) {
float current_u0 = u0;
float current_u1 = u1;
float current_v0 = v0;
float current_v1 = v1;
if (cycle_counter % 2 != 0) {
current_v0 = (yt + 16) / 256.0f;
current_v1 = (yt + 16 + 15.99f) / 256.0f;
}
if ((cycle_counter / 2) % 2 == 0) {
float tmp = current_u1;
current_u1 = current_u0;
current_u0 = tmp;
}
t.vertexUV(r - xo, 0.0f - yo, zo, current_u1, current_v1);
t.vertexUV(-r - xo, 0.0f - yo, zo, current_u0, current_v1);
t.vertexUV(-r - xo, 1.4f - yo, zo, current_u0, current_v0);
t.vertexUV(r - xo, 1.4f - yo, zo, current_u1, current_v0);
h -= 0.45f;
yo -= 0.45f;
r *= 0.9f;
zo += 0.03f;
cycle_counter++;
}
t.draw();
glPopMatrix2();
glEnable2(GL_LIGHTING);
}
void EntityRenderer::renderShadow(Entity* e, float x, float y, float z, float pow, float a) { //
glEnable2(GL_BLEND);
@@ -229,6 +300,8 @@ void EntityRenderer::renderShadow(Entity* e, float x, float y, float z, float po
glColor4f2(1, 1, 1, 1);
glDisable2(GL_BLEND);
glDepthMask(true);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
Level* EntityRenderer::getLevel() {

View File

@@ -218,6 +218,8 @@ void MobRenderer::renderNameTag(Mob* mob, const std::string& name, float x, floa
glScalef2(-s, -s, s);
glDisable(GL_LIGHTING);
glDepthMask(false);
glDisable2(GL_DEPTH_TEST);
glEnable2(GL_BLEND);
@@ -241,6 +243,7 @@ void MobRenderer::renderNameTag(Mob* mob, const std::string& name, float x, floa
glDepthMask(true);
font->draw(name, (float) fnameWidth, 0, 0xffffffff);
glEnable(GL_LIGHTING);
glDisable2(GL_BLEND);
glColor4f2(1, 1, 1, 1);
glPopMatrix2();

View File

@@ -77,10 +77,10 @@ void PlayerRenderer::render(Entity* mob_, float x, float y, float z, float rot,
model = desired;
humanoidModel = desired;
}
// LOGI("[PlayerRenderer] %s: skin=%s, modelTex=%dx%d, desired=%s\n", // don't log it always, only for debug - shredder
// ((Player*)mob)->name.c_str(), mob->getTexture().c_str(),
// humanoidModel->texWidth, humanoidModel->texHeight,
// (desired == playerModel64 ? "64" : "32"));
/* LOGI("[PlayerRenderer] %s: skin=%s, modelTex=%dx%d, desired=%s\n",
((Player*)mob)->name.c_str(), mob->getTexture().c_str(),
humanoidModel->texWidth, humanoidModel->texHeight,
(desired == playerModel64 ? "64" : "32")); */
HumanoidMobRenderer::render(mob_, x, y, z, rot, a);
}

View File

@@ -111,6 +111,7 @@
#include "data/eat1.pcm"
#include "data/eat2.pcm"
#include "data/eat3.pcm"
#include "data/burp1.pcm"
#include "data/fuse.pcm"
SoundDesc SA_cloth1((char*)PCM_cloth1);
@@ -221,6 +222,7 @@ SoundDesc SA_creeperdeath((char*)PCM_creeperdeath);
SoundDesc SA_eat1((char*)PCM_eat1);
SoundDesc SA_eat2((char*)PCM_eat2);
SoundDesc SA_eat3((char*)PCM_eat3);
SoundDesc SA_burp1((char*)PCM_burp1);
SoundDesc SA_fuse((char*)PCM_fuse);
#endif /*!PRE_ANDROID23 && !__APPLE__*/

View File

@@ -172,6 +172,7 @@ extern SoundDesc SA_creeperdeath;
extern SoundDesc SA_eat1;
extern SoundDesc SA_eat2;
extern SoundDesc SA_eat3;
extern SoundDesc SA_burp1;
extern SoundDesc SA_fuse;
#endif /*!PRE_ANDROID23 && !__APPLE__*/

View File

@@ -144,6 +144,7 @@ void SoundEngine::init( Minecraft* mc, Options* options )
sounds.add("random.eat", SA_eat1);
sounds.add("random.eat", SA_eat2);
sounds.add("random.eat", SA_eat3);
sounds.add("random.burp", SA_burp1);
sounds.add("random.fuse", SA_fuse);
#endif

View File

@@ -227,6 +227,7 @@ void SoundEngine::init( Minecraft* mc, Options* options )
sounds.add( "random.eat", _pp("eat1"));
sounds.add( "random.eat", _pp("eat2"));
sounds.add( "random.eat", _pp("eat3"));
sounds.add( "random.burp", _pp("burp1"));
sounds.add( "random.fuse", _pp("fuse"));
sounds.add( "step.cloth", _pp("cloth1"));

File diff suppressed because it is too large Load Diff

10
src/commands/Command.cpp Normal file
View File

@@ -0,0 +1,10 @@
#include "Command.hpp"
#include "world/level/Level.h"
#include <client/Minecraft.h>
bool Command::isPlayerOp(Minecraft& mc, Player& player) {
std::string nicknameLower = player.name;
std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
return mc.level->ops.find(nicknameLower) != mc.level->ops.end();
}

28
src/commands/Command.hpp Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include <string>
#include <vector>
enum CommandFlags {
COMMAND_FLAG_SINGLEPLAYER_ONLY = (1 << 1),
COMMAND_FLAG_NO_ARGS = (1 << 2),
};
class Minecraft;
class Player;
class Command {
public:
const std::string& getName() { return m_name; }
const CommandFlags getFlags() { return m_flags; }
bool isPlayerOp(Minecraft& mc, Player& player);
virtual std::string execute(Minecraft& mc, Player& player, const std::vector<std::string>& args) = 0;
virtual std::string help(Minecraft& mc) = 0;
protected:
Command(const std::string& name, CommandFlags flags = (CommandFlags)0) : m_name(name), m_flags(flags) {}
const std::string m_name;
const CommandFlags m_flags;
};

View File

@@ -0,0 +1,49 @@
#include "CommandBan.hpp"
#include "commands/Command.hpp"
#include "network/RakNetInstance.h"
#include "raknet/RakPeerInterface.h"
#include "world/level/Level.h"
#include <algorithm>
#include <client/Minecraft.h>
#include <network/packet/LoginStatusPacket.h>
CommandBan::CommandBan() : Command("ban") {}
std::string CommandBan::execute(Minecraft& mc, Player& player, const std::vector<std::string>& args) {
if (!isPlayerOp(mc, player)) {
return "You aren't enough priveleged to run this command";
}
if (args.empty()) {
return help(mc);
}
std::string nicknameLower = args[0];
std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [nicknameLower] (auto& it) -> bool {
std::string lower = it->name;
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
return lower == nicknameLower;
});
if (it != mc.level->players.end()) {
if (*it == (Player*)mc.player) {
return "banip: you can't ban urself lol";
}
} else {
for (auto& banned : mc.level->bannedPpl) {
if (nicknameLower == banned) {
return args[0] + " already banned!";
}
}
}
mc.level->bannedPpl.insert(nicknameLower);
return "ban: successfully banned player " + args[0];
}
std::string CommandBan::help(Minecraft& mc) {
return "Usage: /ban <player>";
}

View File

@@ -0,0 +1,9 @@
#include "Command.hpp"
class CommandBan : public Command {
public:
CommandBan();
std::string execute(Minecraft& mc, Player& player, const std::vector<std::string>& args);
std::string help(Minecraft& mc);
};

View File

@@ -0,0 +1,65 @@
#include "CommandBanIp.hpp"
#include "commands/Command.hpp"
#include "network/RakNetInstance.h"
#include "raknet/RakPeerInterface.h"
#include "world/level/Level.h"
#include <algorithm>
#include <client/Minecraft.h>
CommandBanIp::CommandBanIp() : Command("banip") {}
std::string CommandBanIp::execute(Minecraft& mc, Player& player, const std::vector<std::string>& args) {
if (!isPlayerOp(mc, player)) {
return "You aren't enough priveleged to run this command";
}
if (args.empty()) {
return help(mc);
}
std::string nicknameLower = args[0];
std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [nicknameLower] (auto& it) -> bool {
std::string lower = it->name;
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
return lower == nicknameLower;
});
std::string clientIp;
if (it != mc.level->players.end()) {
if (*it == (Player*)mc.player) {
return "banip: you can't ban urself lol";
}
RakNet::SystemAddress sysAddress = mc.raknetInstance->getPeer()->GetSystemAddressFromGuid((*it)->owner);
char ip[32];
sysAddress.ToString(false, ip);
clientIp = ip;
auto sourceId = (*it)->owner;
(*it)->reallyRemoveIfPlayer = true;
mc.level->removeEntity((*it));
mc.raknetInstance->getPeer()->CloseConnection(sourceId, true);
} else {
for (auto& banned : mc.level->bannedIps) {
if (clientIp == banned) {
return args[0] + " already banned!";
}
}
clientIp = args[0];
}
mc.level->bannedIps.insert(clientIp);
return "banip: successfully banned player by ip " + args[0];
}
std::string CommandBanIp::help(Minecraft& mc) {
return "Usage: /banip <player>";
}

View File

@@ -0,0 +1,9 @@
#include "Command.hpp"
class CommandBanIp : public Command {
public:
CommandBanIp();
std::string execute(Minecraft& mc, Player& player, const std::vector<std::string>& args);
std::string help(Minecraft& mc);
};

View File

@@ -0,0 +1,35 @@
#include "CommandHelp.hpp"
#include "commands/Command.hpp"
#include "CommandManager.hpp"
#include <client/Minecraft.h>
#include <sstream>
CommandHelp::CommandHelp() : Command("help") {}
std::string CommandHelp::execute(Minecraft& mc, Player& player, const std::vector<std::string>& args) {
if (args.empty()) {
auto cmds = mc.commandManager().getListAllCommands();
std::ostringstream output;
output << "List of all commands:" << std::endl;
for (auto& cmd : cmds) {
output << " - " + cmd << std::endl;;
}
return output.str();
}
Command* cmd = mc.commandManager().getCommand(args[0]);
if (cmd != nullptr) {
return cmd->help(mc);
}
return "help: command " + args[0] + " not found";
}
std::string CommandHelp::help(Minecraft& mc) {
return "Usage: /help <command>";
}

View File

@@ -0,0 +1,9 @@
#include "Command.hpp"
class CommandHelp : public Command {
public:
CommandHelp();
std::string execute(Minecraft& mc, Player& player, const std::vector<std::string>& args);
std::string help(Minecraft& mc);
};

View File

@@ -0,0 +1,48 @@
#include "CommandKick.hpp"
#include "commands/Command.hpp"
#include "network/RakNetInstance.h"
#include "raknet/RakPeerInterface.h"
#include "world/level/Level.h"
#include <algorithm>
#include <client/Minecraft.h>
CommandKick::CommandKick() : Command("kick") {}
std::string CommandKick::execute(Minecraft& mc, Player& player, const std::vector<std::string>& args) {
if (!isPlayerOp(mc, player)) {
return "You aren't enough priveleged to run this command";
}
if (args.empty()) {
return help(mc);
}
std::string nicknameLower = args[0];
std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
auto it = std::find_if(mc.level->players.begin(), mc.level->players.end(), [args, nicknameLower] (auto& it) -> bool {
std::string lower = it->name;
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
return lower == nicknameLower;
});
if (it == mc.level->players.end()) {
return "kick: can't find player with name " + args[0];
}
if (*it == (Player*)mc.player) {
return "kick: you can't kick urself lol";
}
auto sourceId = (*it)->owner;
(*it)->reallyRemoveIfPlayer = true;
mc.level->removeEntity((*it));
mc.raknetInstance->getPeer()->CloseConnection(sourceId, true);
return "kick: successfully kicked player " + args[0];
}
std::string CommandKick::help(Minecraft& mc) {
return "Usage: /kick <player>";
}

View File

@@ -0,0 +1,9 @@
#include "Command.hpp"
class CommandKick : public Command {
public:
CommandKick();
std::string execute(Minecraft& mc, Player& player, const std::vector<std::string>& args);
std::string help(Minecraft& mc);
};

View File

@@ -0,0 +1,79 @@
#include "CommandManager.hpp"
#include <algorithm>
#include <string>
#include <vector>
#include "client/Minecraft.h"
#include "commands/Command.hpp"
#include "commands/CommandHelp.hpp"
#include "commands/CommandKick.hpp"
#include "commands/CommandOp.hpp"
#include "commands/CommandBan.hpp"
#include "commands/CommandBanIp.hpp"
#include "commands/CommandPardon.hpp"
#include "network/packet/ChatPacket.h"
#include "network/RakNetInstance.h"
#include "world/level/Level.h"
CommandManager::CommandManager() {
registerAllCommands();
}
void CommandManager::registerAllCommands() {
m_commands.push_back(new CommandHelp());
m_commands.push_back(new CommandKick());
m_commands.push_back(new CommandOp());
m_commands.push_back(new CommandBan());
m_commands.push_back(new CommandBanIp());
m_commands.push_back(new CommandPardon());
}
std::vector<std::string> CommandManager::getListAllCommands() {
std::vector<std::string> ret;
for (auto& cmd : m_commands) {
ret.push_back(cmd->getName());
}
return ret;
}
std::string CommandManager::execute(Minecraft& mc, Player& player, const std::string& input) {
std::istringstream ss(input);
std::string cmd;
ss >> cmd;
auto it = std::find_if(m_commands.begin(), m_commands.end(), [cmd](auto& it) -> bool {
return it->getName() == cmd;
});
if (it == m_commands.end()) {
return "Command /" + cmd + " not found";
}
std::vector<std::string> args;
std::string tok;
while (ss >> tok) args.push_back(tok);
if (!mc.level->isClientSide || (*it)->getFlags() & CommandFlags::COMMAND_FLAG_SINGLEPLAYER_ONLY) {
return (*it)->execute(mc, player, args);
} else {
ChatPacket packet("/" + input);
mc.raknetInstance->send(packet);
}
return "";
}
Command* CommandManager::getCommand(const std::string& name) {
auto it = std::find_if(m_commands.begin(), m_commands.end(), [name](auto& it) -> bool {
return it->getName() == name;
});
if (it == m_commands.end()) {
return *it;
}
return nullptr;
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include <string>
#include <vector>
#include "Command.hpp"
class CommandManager {
public:
CommandManager();
std::vector<std::string> getListAllCommands();
std::string execute(Minecraft& mc, Player& player, const std::string& input);
Command* getCommand(const std::string& name);
private:
void registerAllCommands();
std::vector<Command*> m_commands;
};

View File

@@ -0,0 +1,31 @@
#include "CommandOp.hpp"
#include "commands/Command.hpp"
#include "world/level/Level.h"
#include <algorithm>
#include <client/Minecraft.h>
CommandOp::CommandOp() : Command("op") {}
std::string CommandOp::execute(Minecraft& mc, Player& player, const std::vector<std::string>& args) {
if (!isPlayerOp(mc, player)) {
return "You aren't enough priveleged to run this command";
}
if (args.empty()) {
return help(mc);
}
std::string nicknameLower = args[0];
std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
if (mc.level->ops.find(nicknameLower) != mc.level->ops.end()) {
return "op: player " + args[0] + " already opped";
}
mc.level->ops.emplace(nicknameLower);
return "op: successfully opped player " + args[0];
}
std::string CommandOp::help(Minecraft& mc) {
return "Usage: /op <player>";
}

View File

@@ -0,0 +1,9 @@
#include "Command.hpp"
class CommandOp : public Command {
public:
CommandOp();
std::string execute(Minecraft& mc, Player& player, const std::vector<std::string>& args);
std::string help(Minecraft& mc);
};

View File

@@ -0,0 +1,40 @@
#include "CommandPardon.hpp"
#include "commands/Command.hpp"
#include "network/RakNetInstance.h"
#include "raknet/RakPeerInterface.h"
#include "world/level/Level.h"
#include <algorithm>
#include <client/Minecraft.h>
CommandPardon::CommandPardon() : Command("pardon") {}
std::string CommandPardon::execute(Minecraft& mc, Player& player, const std::vector<std::string>& args) {
if (!isPlayerOp(mc, player)) {
return "You aren't enough priveleged to run this command";
}
if (args.empty()) {
return help(mc);
}
std::string nicknameLower = args[0];
std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
if (mc.level->bannedPpl.find(nicknameLower) != mc.level->bannedPpl.end()) {
mc.level->bannedPpl.erase(nicknameLower);
return "pardon: successfully unbanned player " + args[0];
}
if (mc.level->bannedIps.find(nicknameLower) != mc.level->bannedIps.end()) {
mc.level->bannedIps.erase(nicknameLower);
return "pardon: successfully unbanned ip " + args[0];
}
return "Player/Ip doesnt banned";
}
std::string CommandPardon::help(Minecraft& mc) {
return "Usage: /pardon <player>";
}

View File

@@ -0,0 +1,9 @@
#include "Command.hpp"
class CommandPardon : public Command {
public:
CommandPardon();
std::string execute(Minecraft& mc, Player& player, const std::vector<std::string>& args);
std::string help(Minecraft& mc);
};

View File

@@ -1,25 +1,30 @@
#include <fstream>
#include <iostream>
#include "NinecraftApp.h"
#include "AppPlatform.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#ifdef __linux__
#include <unistd.h>
#endif
#include "world/level/LevelSettings.h"
#include "world/level/Level.h"
#include "server/ArgumentsSettings.h"
#include "platform/time.h"
#include "SharedConstants.h"
#include "world/level/LevelConstants.h"
#include <plugins/PluginsManager.hpp>
#define MAIN_CLASS NinecraftApp
static App* g_app = 0;
static int g_exitCode = 0;
void signal_callback_handler(int signum) {
std::cout << "Signum caught: " << signum << std::endl;
if(signum == 2 || signum == 3){ // SIGINT || SIGQUIT
if(g_app != 0) {
if (signum == 2 || signum == 3) { // SIGINT || SIGQUIT
if (g_app != 0) {
g_app->quit();
} else {
exit(g_exitCode);
@@ -27,47 +32,242 @@ void signal_callback_handler(int signum) {
}
}
int main(int numArguments, char* pszArgs[]) {
ArgumentsSettings aSettings(numArguments, pszArgs);
if(aSettings.getShowHelp()) {
ArgumentsSettings defaultSettings(0, NULL);
printf("Minecraft Pockect Edition Server %s\n", Common::getGameVersionString("").c_str());
printf("-------------------------------------------------------\n");
printf("--cachepath - Path to where the server can store temp stuff (not sure if this is used) [default: \"%s\"]\n", defaultSettings.getCachePath().c_str());
printf("--externalpath - The path to the place where the server should store the levels. [default: \"%s\"]\n", defaultSettings.getExternalPath().c_str());
printf("--levelname - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelName().c_str());
printf("--leveldir - The name of the server [default: \"%s\"]\n", defaultSettings.getLevelDir().c_str());
printf("--help - Shows this message.\n");
printf("--port - The port to run the server on. [default: %d]\n", defaultSettings.getPort());
printf("--serverkey - The key that the server should use for API calls. [default: \"%s\"]\n", defaultSettings.getServerKey().c_str());
printf("-------------------------------------------------------\n");
return 0;
std::string findStringInConfig(std::string line, std::string config) {
auto valuePos = config.find(line);
if (line.empty()) {
throw std::runtime_error("Key cannot be empty");
}
if (valuePos == std::string::npos) {
throw std::runtime_error("Cannot find value");
}
std::string valueStr = "";
valuePos += 1 + line.size();
while (true) {
auto sym = config.at(valuePos);
if (sym == '\n') {
break;
}
if (valuePos == config.size()) {
throw std::runtime_error("Cannot find end of the line");
}
valueStr += sym;
valuePos++;
}
return valueStr;
}
int main(int numArguments, char* pszArgs[]) {
std::ifstream serverProperties("server.properties");
int port = 0;
int gamemode = 0;
int worldSize = 0;
std::string levelDir = "";
std::string cachePath = "";
std::string externalPath = "";
std::string levelName = "";
if (serverProperties.is_open()) {
std::string propString;
std::string line;
while (std::getline(serverProperties, line)) {
propString += line;
propString += "\n";
}
if (propString.empty()) {
throw std::runtime_error("Config cannot be empty");
}
port = std::stoi(findStringInConfig("port", propString));
worldSize = std::stoi(findStringInConfig("world-size", propString));
if (worldSize < 16 || worldSize > 32) {
throw std::runtime_error("Incorrect world size.");
}
LevelConstants::CHUNK_CACHE_WIDTH = worldSize;
LevelConstants::LEVEL_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH;
LevelConstants::LEVEL_DEPTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_DEPTH;
cachePath = findStringInConfig("level-cachepath", propString);
externalPath = findStringInConfig("level-externalpath", propString);
levelName = findStringInConfig("level-name", propString);
levelDir = findStringInConfig("level-dir", propString);
std::string gamemodeStr = findStringInConfig("gamemode", propString);
if (gamemodeStr == "survival") {
gamemode = GameType::Survival;
} else if (gamemodeStr == "creative") {
gamemode = GameType::Creative;
} else {
gamemode = GameType::Survival;
}
printf("%d %s %s %d %d\n", port, cachePath.c_str(), externalPath.c_str(), gamemode, LevelConstants::CHUNK_CACHE_WIDTH);
} else {
std::ofstream defaultProperties("server.properties");
if (defaultProperties.is_open()) {
ArgumentsSettings defaultSettings(0, NULL);
std::stringstream buffer;
buffer << "// MCPE Server properties" << std::endl;
buffer << "port=" << defaultSettings.getPort() << std::endl;
buffer << "level-dir=" << defaultSettings.getLevelDir() << std::endl;
buffer << "level-cachepath=" << defaultSettings.getCachePath() << std::endl;
buffer << "level-externalpath=" << defaultSettings.getExternalPath() << std::endl;
buffer << "gamemode=survival" << std::endl;
buffer << "level-name=" << defaultSettings.getLevelName() << std::endl;
buffer << "world-size=16" << std::endl;
defaultProperties << buffer.str();
printf("%s \n", buffer.str().c_str());
printf("Edit a config file first!\n");
defaultProperties.close();
exit(0);
} else {
throw std::runtime_error("Cannot create default config.");
}
}
printf("Level Name: %s\n", aSettings.getLevelName().c_str());
printf("Level Name: %s\n", levelName.c_str());
AppContext appContext;
appContext.platform = new AppPlatform();
App* app = new MAIN_CLASS();
signal(SIGINT, signal_callback_handler);
g_app = app;
((MAIN_CLASS*)g_app)->externalStoragePath = aSettings.getExternalPath();
((MAIN_CLASS*)g_app)->externalCacheStoragePath = aSettings.getCachePath();
((MAIN_CLASS*)g_app)->externalStoragePath = externalPath;
((MAIN_CLASS*)g_app)->externalCacheStoragePath = cachePath;
g_app->init(appContext);
LevelSettings settings(getEpochTimeS(), GameType::Creative);
LevelSettings settings(getEpochTimeS(), gamemode);
float startTime = getTimeS();
((MAIN_CLASS*)g_app)->selectLevel(aSettings.getLevelDir(), aSettings.getLevelName(), settings);
((MAIN_CLASS*)g_app)->hostMultiplayer(aSettings.getPort());
((MAIN_CLASS*)g_app)->selectLevel(levelDir, levelName, settings);
((MAIN_CLASS*)g_app)->hostMultiplayer(port);
PluginsManager::get().loadPlugins();
// Reading ops
std::ifstream ops("ops.txt");
if (ops.is_open()) {
std::string line;
while (std::getline(ops, line)) {
if (!line.empty()) {
((MAIN_CLASS*)g_app)->level->ops.insert(line);
}
}
} else {
std::ofstream opsDefault("ops.txt");
if (!opsDefault.is_open()) {
throw std::runtime_error("Cannot create ops list.");
}
}
// Reading banned ppl
std::ifstream banned("banned-players.txt");
if (banned.is_open()) {
std::string line;
while (std::getline(banned, line)) {
if (!line.empty()) {
((MAIN_CLASS*)g_app)->level->bannedPpl.insert(line);
}
}
} else {
std::ofstream bannedPpl("banned-players.txt");
if (!bannedPpl.is_open()) {
throw std::runtime_error("Cannot create banned players list.");
}
}
std::ifstream bannedIps("banned-ips.txt");
if (bannedIps.is_open()) {
std::string line;
while (std::getline(bannedIps, line)) {
if (!line.empty()) {
((MAIN_CLASS*)g_app)->level->bannedIps.insert(line);
}
}
} else {
std::ofstream bannedIp("banned-ips.txt");
if (!bannedIp.is_open()) {
throw std::runtime_error("Cannot create banned players list.");
}
}
std::cout << "Level has been generated in " << getTimeS() - startTime << std::endl;
((MAIN_CLASS*)g_app)->level->saveLevelData();
std::cout << "Level has been saved!" << std::endl;
PluginsManager::get().emit("ServerLoaded");
while(!app->wantToQuit()) {
app->update();
//pthread_yield();
sleepMs(20);
}
std::ofstream opsWrite("ops.txt");
if (opsWrite.is_open()) {
for (auto& op : ((MAIN_CLASS*)g_app)->level->ops) {
opsWrite << op << std::endl;
}
opsWrite.close();
} else {
throw std::runtime_error("Cannot open ops list.");
}
std::ofstream bannedWrite("banned-players.txt");
if (bannedWrite.is_open()) {
for (auto& banned : ((MAIN_CLASS*)g_app)->level->bannedPpl) {
bannedWrite << banned << std::endl;
}
bannedWrite.close();
} else {
throw std::runtime_error("Cannot open banned players list.");
}
std::ofstream bannedIpsWrite("banned-ips.txt");
if (bannedIpsWrite.is_open()) {
for (auto& banned : ((MAIN_CLASS*)g_app)->level->bannedIps) {
bannedIpsWrite << banned << std::endl;
}
bannedIpsWrite.close();
} else {
throw std::runtime_error("Cannot open banned players list.");
}
PluginsManager::get().emit("ServerShutdown");
((MAIN_CLASS*)g_app)->level->saveLevelData();
delete app;
appContext.platform->finish();
delete appContext.platform;

View File

@@ -1,6 +1,7 @@
#include "ClientSideNetworkHandler.h"
#include "client/Options.h"
#include "network/packet/LoginStatusPacket.h"
#include "packet/PacketInclude.h"
#include "RakNetInstance.h"
#include "../world/level/chunk/ChunkSource.h"
@@ -10,6 +11,9 @@
#include "../world/entity/player/Inventory.h"
#include "../client/Minecraft.h"
#include "../client/gamemode/GameMode.h"
#include "world/item/ItemInstance.h"
#include "world/level/LevelConstants.h"
#include <cstddef>
#ifndef STANDALONE_SERVER
#include "../client/gui/screens/DisconnectionScreen.h"
#endif
@@ -42,6 +46,9 @@ ClientSideNetworkHandler::ClientSideNetworkHandler(Minecraft* minecraft, IRakNet
requestNextChunkPosition(0),
requestNextChunkIndex(0)
{
NumRequestChunks = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH;
requestNextChunkIndexList.resize(NumRequestChunks);
chunksLoaded.resize(NumRequestChunks);
rakPeer = raknetInstance->getPeer();
}
@@ -59,7 +66,7 @@ void ClientSideNetworkHandler::requestNextChunk()
//LOGI("requesting chunks @ (%d, %d)\n", chunk.x, chunk.y);
//raknetInstance->send(new RequestChunkPacket(requestNextChunkPosition % CHUNK_CACHE_WIDTH, requestNextChunkPosition / CHUNK_CACHE_WIDTH));
//raknetInstance->send(new RequestChunkPacket(requestNextChunkPosition % LevelConstants::CHUNK_CACHE_WIDTH, requestNextChunkPosition / LevelConstants::CHUNK_CACHE_WIDTH));
requestNextChunkIndex++;
requestNextChunkPosition++;
}
@@ -67,16 +74,16 @@ void ClientSideNetworkHandler::requestNextChunk()
bool ClientSideNetworkHandler::areAllChunksLoaded()
{
return (requestNextChunkPosition >= (CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH));
return (requestNextChunkPosition >= (LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH));
}
bool ClientSideNetworkHandler::isChunkLoaded(int x, int z)
{
if (x < 0 || x >= CHUNK_CACHE_WIDTH || z < 0 || z >= CHUNK_CACHE_WIDTH) {
if (x < 0 || x >= LevelConstants::CHUNK_CACHE_WIDTH || z < 0 || z >= LevelConstants::CHUNK_CACHE_WIDTH) {
LOGE("Error: Tried to request chunk (%d, %d)\n", x, z);
return true;
}
return chunksLoaded[x * CHUNK_CACHE_WIDTH + z];
return chunksLoaded[x * LevelConstants::CHUNK_CACHE_WIDTH + z];
//return areAllChunksLoaded();
}
@@ -86,7 +93,7 @@ void ClientSideNetworkHandler::onConnect(const RakNet::RakNetGUID& hostGuid)
serverGuid = hostGuid;
clearChunksLoaded();
LoginPacket packet(minecraft->options.getStringValue(OPTIONS_USERNAME).c_str(), SharedConstants::NetworkProtocolVersion);
LoginPacket packet(minecraft->options.getStringValue(OPTIONS_USERNAME).c_str(), SharedConstants::NetworkProtocolVersion, true);
raknetInstance->send(packet);
}
@@ -97,6 +104,11 @@ void ClientSideNetworkHandler::onUnableToConnect()
void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid)
{
LevelConstants::CHUNK_CACHE_WIDTH = 16;
LevelConstants::LEVEL_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH;
LevelConstants::LEVEL_DEPTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_DEPTH;
// TODO: Good disconnecting
LOGI("onDisconnect\n");
if (level)
{
@@ -109,9 +121,13 @@ void ClientSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid)
}
}
}
#ifndef STANDALONE_SERVER
minecraft->gui.addMessage("Disconnected from server");
#endif
minecraft->leaveGame();
// minecraft->setLevel(NULL);
// #ifndef STANDALONE_SERVER
// minecraft->gui.addMessage("Disconnected from server");
// // TODO: screen with error
// minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
// #endif
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginStatusPacket* packet) {
@@ -130,6 +146,18 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginSta
LOGI("Disconnect! Server is outdated!\n");
#ifndef STANDALONE_SERVER
minecraft->setScreen(new DisconnectionScreen("Could not connect: Outdated server!"));
#endif
}
if (packet->status == LoginStatus::Failed_TakenNickname) {
LOGI("Disconnect! Nickname is taken!\n");
#ifndef STANDALONE_SERVER
minecraft->setScreen(new DisconnectionScreen("Could not connect: Nickname is taken!"));
#endif
}
if (packet->status == LoginStatus::Failed_Banned) {
LOGI("Disconnect! You're banned from this server!\n");
#ifndef STANDALONE_SERVER
minecraft->setScreen(new DisconnectionScreen("Could not connect: You're banned from this server!"));
#endif
}
}
@@ -146,6 +174,19 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, StartGam
}
#endif
// @todo @note i think its trash
// we can put it directly to selectLevel?
if (packet->chunkCacheWidth != 0) {
printf("lol \n");
LevelConstants::CHUNK_CACHE_WIDTH = packet->chunkCacheWidth;
LevelConstants::LEVEL_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH;
LevelConstants::LEVEL_DEPTH = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_DEPTH;
LevelChunk::ChunkBlockCount = LevelConstants::CHUNK_BLOCK_COUNT;
}
NumRequestChunks = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH;
requestNextChunkIndexList.resize(NumRequestChunks);
chunksLoaded.resize(NumRequestChunks);
const std::string& levelId = LevelStorageSource::TempLevelId;
LevelStorageSource* storageSource = minecraft->getLevelSource();
storageSource->deleteLevel(levelId);
@@ -182,7 +223,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetTimeP
if (!level)
return;
LOGI("SetTimePacket\n");
// LOGI("SetTimePacket\n");
level->setTime(packet->time);
}
@@ -238,7 +279,7 @@ void ClientSideNetworkHandler::handle( const RakNet::RakNetGUID& source, AddPain
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AddMobPacket* packet)
{
LOGI("AddMobPacket (%p)\n", level);
// LOGI("AddMobPacket (%p)\n", level);
if (!level) {
LOGW("Trying to add a mob with no level!\n");
@@ -324,7 +365,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveEn
if (!level) return;
Entity* entity = level->getEntity(packet->entityId);
LOGI("RemoveEntityPacket %p %p, %d\n", entity, minecraft->player, entity?(int)(entity->isPlayer()): -1);
// LOGI("RemoveEntityPacket %p %p, %d\n", entity, minecraft->player, entity?(int)(entity->isPlayer()): -1);
if (!entity) return;
level->removeEntity(entity);
@@ -344,6 +385,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AddItemE
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, TakeItemEntityPacket* packet) {
// printf("TakeItemEntityPacket \n");
if (!level) return;
Entity* e = level->getEntity(packet->itemId);
@@ -386,6 +428,54 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SendInventoryPacket* packet) {
if (!level) return;
if (packet->entityId == minecraft->player->entityId) {
auto items = packet->items;
minecraft->player->inventory->replace(items);
for (int i = 0; i < packet->linkedSlot.size(); i++) {
minecraft->player->inventory->linkSlot(i, packet->linkedSlot[i].inventorySlot, true);
LOGI("%i -> %i\n", packet->linkedSlot[i].inventorySlot, i);
}
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, TakeItemPacket* packet) {
if (!level) return;
LOGI("TakeItemPacket\n");
ItemInstance* item = new ItemInstance();
item->count = packet->count;
item->id = packet->itemId;
item->setAuxValue(packet->auxValue);
// if (minecraft->player->entityId == packet->playerId) {
if (!minecraft->player->inventory->add(item)) {
minecraft->player->drop(new ItemInstance(*item), false);
}
// }
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveItemPacket* packet) {
// Idk how it works...
if (!level) return;
ItemInstance item;
item.count = packet->count;
item.id = packet->itemId;
item.setAuxValue(packet->auxValue);
// if (minecraft->player->entityId == packet->playerId) {
minecraft->player->inventory->removeResource(item);
// }
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MoveEntityPacket* packet)
{
if (!level)
@@ -475,19 +565,19 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDat
//unsigned char* blockIds = chunk->getBlockData();
DataLayer& blockData = chunk->data;
const int setSize = LEVEL_HEIGHT / 8;
const int setShift = 4; // power of LEVEL_HEIGHT / 8
const int setSize = LevelConstants::LEVEL_HEIGHT / 8;
const int setShift = 4; // power of LevelConstants::LEVEL_HEIGHT / 8
bool recalcHeight = false;
int x0 = 16, x1 = 0, z0 = 16, z1 = 0, y0 = LEVEL_HEIGHT, y1 = 0;
int x0 = 16, x1 = 0, z0 = 16, z1 = 0, y0 = LevelConstants::LEVEL_HEIGHT, y1 = 0;
int rx = packet->x << 4;
int rz = packet->z << 4;
unsigned char readBlockBuffer[setSize];
unsigned char readDataBuffer[setSize / 2];
unsigned char* readBlockBuffer = new unsigned char[setSize];
unsigned char* readDataBuffer = new unsigned char[setSize / 2];
for (int i = 0; i < CHUNK_COLUMNS; i++)
for (int i = 0; i < LevelConstants::CHUNK_COLUMNS; i++)
{
unsigned char updateBits = 0;
packet->chunkData.Read(updateBits);
@@ -496,8 +586,8 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDat
{
recalcHeight = true;
int colX = (i % CHUNK_WIDTH);
int colZ = (i / CHUNK_WIDTH);
int colX = (i % LevelConstants::CHUNK_WIDTH);
int colZ = (i / LevelConstants::CHUNK_WIDTH);
int colDataPosition = colX << 11 | colZ << 7;
for (int set = 0; set < 8; set++)
@@ -531,30 +621,33 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDat
{
y0 = ((1 << set) << setShift);
}
if (((1 << set) << setShift) + (LEVEL_HEIGHT / 8) - 1 > y1)
if (((1 << set) << setShift) + (LevelConstants::LEVEL_HEIGHT / 8) - 1 > y1)
{
y1 = ((1 << set) << setShift) + (LEVEL_HEIGHT / 8) - 1;
y1 = ((1 << set) << setShift) + (LevelConstants::LEVEL_HEIGHT / 8) - 1;
}
}
if ((i % CHUNK_WIDTH) < x0)
if ((i % LevelConstants::CHUNK_WIDTH) < x0)
{
x0 = (i % CHUNK_WIDTH);
x0 = (i % LevelConstants::CHUNK_WIDTH);
}
if ((i % CHUNK_WIDTH) > x1)
if ((i % LevelConstants::CHUNK_WIDTH) > x1)
{
x1 = (i % CHUNK_WIDTH);
x1 = (i % LevelConstants::CHUNK_WIDTH);
}
if ((i / CHUNK_WIDTH) < z0)
if ((i / LevelConstants::CHUNK_WIDTH) < z0)
{
z0 = (i / CHUNK_WIDTH);
z0 = (i / LevelConstants::CHUNK_WIDTH);
}
if ((i / CHUNK_WIDTH) > z1)
if ((i / LevelConstants::CHUNK_WIDTH) > z1)
{
z1 = (i / CHUNK_WIDTH);
z1 = (i / LevelConstants::CHUNK_WIDTH);
}
}
}
delete[] readBlockBuffer;
delete[] readDataBuffer;
if (recalcHeight)
{
// chunk->recalcHeightmap();
@@ -579,7 +672,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChunkDat
//chunk->terrainPopulated = true;
chunk->unsaved = false;
chunksLoaded[packet->x * CHUNK_CACHE_WIDTH + packet->z] = true;
chunksLoaded[packet->x * LevelConstants::CHUNK_CACHE_WIDTH + packet->z] = true;
if (areAllChunksLoaded())
{
@@ -627,18 +720,18 @@ void ClientSideNetworkHandler::arrangeRequestChunkOrder() {
clearChunksLoaded();
// Default sort is around center of the world
int cx = CHUNK_CACHE_WIDTH / 2;
int cz = CHUNK_CACHE_WIDTH / 2;
int cx = LevelConstants::CHUNK_CACHE_WIDTH / 2;
int cz = LevelConstants::CHUNK_CACHE_WIDTH / 2;
// If player exists, let's sort around him
Player* p = minecraft? minecraft->player : NULL;
if (p) {
cx = Mth::floor(p->x / (float)CHUNK_WIDTH);
cz = Mth::floor(p->z / (float)CHUNK_DEPTH);
cx = Mth::floor(p->x / (float)LevelConstants::CHUNK_WIDTH);
cz = Mth::floor(p->z / (float)LevelConstants::CHUNK_DEPTH);
}
_ChunkSorter sorter(cx, cz);
std::sort(requestNextChunkIndexList, requestNextChunkIndexList + NumRequestChunks, sorter);
std::sort(requestNextChunkIndexList.begin(), requestNextChunkIndexList.end(), sorter);
}
void ClientSideNetworkHandler::levelGenerated(Level* level)
@@ -728,7 +821,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetEntit
if (!level)
return;
LOGI("SetEntityDataPacket\n");
// LOGI("SetEntityDataPacket\n");
Entity* e = level->getEntity(packet->id);
if (e) {
@@ -782,6 +875,10 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AnimateP
}
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet)
{
}
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemPacket* packet)
{
}
@@ -791,6 +888,7 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, SetHealt
if (!level || !minecraft->player)
return;
printf("SetHealthPacket \n");
minecraft->player->hurtTo(packet->health);
}
@@ -886,7 +984,11 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe
void ClientSideNetworkHandler::handle( const RakNet::RakNetGUID& source, ChatPacket* packet )
{
#ifndef STANDALONE_SERVER
minecraft->gui.displayClientMessage(packet->message);
// minecraft->gui.displayClientMessage(packet->message);
std::istringstream iss(packet->message);
for (std::string line; std::getline(iss, line); ) {
minecraft->gui.addMessage(line);
}
#endif
}
@@ -919,8 +1021,8 @@ void ClientSideNetworkHandler::clearChunksLoaded()
{
// Init the chunk positions
for (int i = 0; i < NumRequestChunks; ++i) {
requestNextChunkIndexList[i].x = i/CHUNK_WIDTH;
requestNextChunkIndexList[i].y = i%CHUNK_WIDTH;
requestNextChunkIndexList[i].x = i / LevelConstants::CHUNK_WIDTH;
requestNextChunkIndexList[i].y = i % LevelConstants::CHUNK_WIDTH;
chunksLoaded[i] = false;
}
}

View File

@@ -77,6 +77,11 @@ public:
virtual void handle(const RakNet::RakNetGUID& source, ChatPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, AdventureSettingsPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SignUpdatePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, RemoveItemPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, TakeItemPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SendInventoryPacket* packet);
private:
void requestNextChunk();
@@ -97,11 +102,11 @@ private:
BlockUpdateList bufferedBlockUpdates;
int requestNextChunkPosition;
static const int NumRequestChunks = CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH;
int NumRequestChunks;
int requestNextChunkIndex;
IntPair requestNextChunkIndexList[NumRequestChunks];
bool chunksLoaded[NumRequestChunks];
std::vector<IntPair> requestNextChunkIndexList;
std::vector<bool> chunksLoaded;
};
#endif

View File

@@ -1,33 +0,0 @@
#include "NATPunchHandler.h"
#include "../raknet/TCPInterface.h"
#include "../raknet/HTTPConnection.h"
#include "PHPDirectoryServer2.h"
using namespace RakNet;
NATPuchHandler::NATPuchHandler() {
tcpInterface = new TCPInterface;
}
NATPuchHandler::~NATPuchHandler() {
delete tcpInterface;
}
void NATPuchHandler::initialize() {
tcpInterface->Start(0, 64);
}
void NATPuchHandler::registerToGameList(const RakNet::RakString& serverName, int port) {
HTTPConnection httpConnection;
httpConnection.Init(tcpInterface, "johanbernhardsson.se");
PHPDirectoryServer2 directoryServer;
directoryServer.Init(&httpConnection, "/DirectoryServer.php");
directoryServer.UploadTable("", serverName, port, true);
}
void NATPuchHandler::removeFromGameList() {
}
void NATPuchHandler::close() {
}

View File

@@ -1,24 +0,0 @@
#ifndef _MINECRAFT_NETWORK_NATPUNCHHANDLER_H_
#define _MINECRAFT_NETWORK_NATPUNCHHANDLER_H_
#include "../raknet/TCPInterface.h"
#include "../raknet/RakString.h"
class NATPuchHandler {
public:
enum NATPuchHandlerStatus {
NATPuchInitilized = 0,
NATPuchFetchingServerList = 1,
NATPuchConnecting = 2,
NATPuchConnected = 3,
NATPuchDissconnected = 4
};
NATPuchHandler();
~NATPuchHandler();
void initialize();
void registerToGameList(const RakNet::RakString& serverName, int port);
void removeFromGameList();
void close();
private:
RakNet::TCPInterface *tcpInterface;
};
#endif /* _MINECRAFT_NETWORK_NATPUNCHHANDLER_H_ */

View File

@@ -18,6 +18,8 @@ class RemovePlayerPacket;
class RemoveEntityPacket;
class MoveEntityPacket;
//class TeleportEntityPacket;
class RemoveItemPacket;
class TakeItemPacket;
class MovePlayerPacket;
class PlaceBlockPacket;
class RemoveBlockPacket;
@@ -48,6 +50,7 @@ class ContainerClosePacket;
class ContainerSetSlotPacket;
class ContainerSetDataPacket;
class ContainerSetContentPacket;
class WantCreatePacket;
class ChatPacket;
class SignUpdatePacket;
class Minecraft;
@@ -119,6 +122,9 @@ public:
virtual void handle(const RakNet::RakNetGUID& source, SignUpdatePacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, AdventureSettingsPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, AnimatePacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, RemoveItemPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, TakeItemPacket* packet) {}
virtual void handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet) {}
//
// Common implementation for Client and Server

View File

@@ -2,6 +2,7 @@
#include "Packet.h"
#include "../world/level/chunk/LevelChunk.h"
#include "network/packet/TakeItemPacket.h"
#include "packet/PacketInclude.h"
Packet::Packet()
@@ -41,10 +42,16 @@ Packet* MinecraftPackets::createPacket(int id)
case PACKET_ADDITEMENTITY:
packet = new AddItemEntityPacket();
break;
case PACKET_REMOVEITEM:
packet = new RemoveItemPacket();
break;
case PACKET_TAKEITEM:
packet = new TakeItemPacket();
break;
case PACKET_TAKEITEMENTITY:
packet = new TakeItemEntityPacket();
break;
case PACKET_ADDMOB:
case PACKET_ADDMOB:
packet = new AddMobPacket();
break;
case PACKET_ADDPLAYER:
@@ -68,6 +75,9 @@ Packet* MinecraftPackets::createPacket(int id)
case PACKET_RESPAWN:
packet = new RespawnPacket();
break;
case PACKET_WANTCREATEITEM:
packet = new WantCreatePacket();
break;
case PACKET_REMOVEENTITY:
packet = new RemoveEntityPacket();
break;

View File

@@ -33,7 +33,10 @@ enum MinecraftPacketIds
PACKET_REMOVEENTITY,
PACKET_ADDITEMENTITY,
PACKET_TAKEITEMENTITY,
PACKET_TAKEITEM,
PACKET_REMOVEITEM,
PACKET_WANTCREATEITEM,
PACKET_MOVEENTITY,
PACKET_MOVEENTITY_POS,
PACKET_MOVEENTITY_ROT,

View File

@@ -173,6 +173,7 @@ bool RakNetInstance::isMyLocalGuid(const RakNet::RakNetGUID& guid)
void RakNetInstance::runEvents(NetEventCallback* callback)
{
RakNet::Packet* currentEvent;
bool disconnect = false;
while ((currentEvent = rakPeer->Receive()) != NULL)
{
@@ -200,6 +201,7 @@ void RakNetInstance::runEvents(NetEventCallback* callback)
case ID_DISCONNECTION_NOTIFICATION:
case ID_CONNECTION_LOST:
callback->onDisconnect(currentEvent->guid);
disconnect = true;
break;
case ID_UNCONNECTED_PONG:
{
@@ -233,8 +235,9 @@ void RakNetInstance::runEvents(NetEventCallback* callback)
}
}
}
rakPeer->DeallocatePacket(currentEvent);
if (!disconnect) {
rakPeer->DeallocatePacket(currentEvent);
}
//delete activeBitStream;
}

View File

@@ -5,6 +5,16 @@
#include "../world/entity/player/Inventory.h"
#include "../world/Container.h"
#include "../world/inventory/BaseContainerMenu.h"
#include "network/packet/ChatPacket.h"
#include "network/packet/ContainerSetSlotPacket.h"
#include "network/packet/LoginStatusPacket.h"
#include "network/packet/MovePlayerPacket.h"
#include "network/packet/RemoveBlockPacket.h"
#include "network/packet/SendInventoryPacket.h"
#include "network/packet/UpdateBlockPacket.h"
#include "network/packet/RemoveItemPacket.h"
#include "network/packet/TakeItemPacket.h"
#include "network/packet/WantCreatePacket.h"
#include "packet/PacketInclude.h"
#include "RakNetInstance.h"
@@ -13,11 +23,24 @@
#include "../client/gamemode/GameMode.h"
#include "../raknet/RakPeerInterface.h"
#include "../raknet/PacketPriority.h"
#include "platform/log.h"
#include "util/Mth.h"
#include "util/StringUtils.h"
#include "world/item/ItemInstance.h"
#include "world/level/LevelConstants.h"
#include "world/level/storage/LevelStorage.h"
#include "world/phys/Vec3.h"
#include "world/item/crafting/Recipe.h"
#include "world/item/crafting/Recipes.h"
#include <cstddef>
#include <cstdio>
#ifndef STANDALONE_SERVER
#include "../client/sound/SoundEngine.h"
#endif
#include "../server/ServerPlayer.h"
#include "../world/entity/item/FallingTile.h"
#include <plugins/LuaPlayer.hpp>
#include <plugins/MessageEvent.hpp>
#define TIMES(x) for(int itc ## __LINE__ = 0; itc ## __LINE__ < x; ++ itc ## __LINE__)
@@ -53,11 +76,11 @@ void ServerSideNetworkHandler::tileChanged(int x, int y, int z)
Packet* ServerSideNetworkHandler::getAddPacketFromEntity( Entity* entity ) {
if (entity->isMob() && !entity->isPlayer()) { //@fix: This code is duplicated. See if it can be unified.
if (minecraft->player) {
// if (minecraft->player) {
// I guess this should always be true, but it crashed somewhere in this
// function once and I only see this one as a potential problem
return new AddMobPacket((Mob*)entity);
}
// }
}
else if (entity->isPlayer()) {
@@ -134,9 +157,62 @@ void ServerSideNetworkHandler::displayGameMessage(const std::string& message)
raknetInstance->send(packet);
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MessagePacket* packet)
{
auto player = getPlayer(source);
if (player == nullptr) return; // @todo maybe kick?
auto msg = std::string(packet->message.C_String());
MessageEvent event;
event.m_decline = false;
PluginsManager::get().emit("Message", LuaPlayer(source), msg, event);
if (!event.m_decline) {
if (packet->message[0] == '/') {
// This is a command
auto cmd = Util::stringTrim(msg.substr(1));
if (PluginsManager::get().emitCommands(cmd, source)) {
ChatPacket resp(minecraft->commandManager().execute(*minecraft, *player, cmd));
return sendPrivate(resp, source);
} else {
return;
}
}
displayGameMessage("<" + player->name + "> " + msg);
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChatPacket* packet)
{
displayGameMessage(packet->message);
auto player = getPlayer(source);
if (player == nullptr) return; // @todo maybe kick?
MessageEvent event;
event.m_decline = false;
PluginsManager::get().emit("Message", LuaPlayer(source), packet->message, event);
if (!event.m_decline) {
if (packet->message[0] == '/') {
// This is a command
auto cmd = Util::stringTrim(packet->message.substr(1));
if (PluginsManager::get().emitCommands(cmd, source)) {
ChatPacket resp(minecraft->commandManager().execute(*minecraft, *player, cmd));
return sendPrivate(resp, source);
} else {
return;
}
}
displayGameMessage("<" + player->name + "> " + packet->message);
}
}
void ServerSideNetworkHandler::onNewClient(const RakNet::RakNetGUID& clientGuid)
@@ -156,6 +232,9 @@ void ServerSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid)
if (player->owner == guid)
{
PluginsManager::get().emit("PlayerDisconnect", LuaPlayer(guid));
minecraft->level->getLevelStorage()->savePlayer(*player);
std::string message = player->name;
message += " disconnected from the game";
displayGameMessage(message);
@@ -179,15 +258,49 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac
if (!_allowIncoming) return;
LOGI("LoginPacket\n");
int loginStatus = LoginStatus::Success;
//
// Bad/incompatible client version
//
bool oldClient = packet->clientNetworkVersion < SharedConstants::NetworkProtocolLowestSupportedVersion;
bool oldServer = packet->clientNetworkLowestSupportedVersion > SharedConstants::NetworkProtocolVersion;
if (oldClient || oldServer)
loginStatus = oldClient? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld;
if (oldClient || oldServer || !packet->newProto)
loginStatus = oldClient || !packet->newProto? LoginStatus::Failed_ClientOld : LoginStatus::Failed_ServerOld;
std::string nicknameLower = packet->clientName.C_String();
std::transform(nicknameLower.begin(), nicknameLower.end(), nicknameLower.begin(), ::tolower);
RakNet::SystemAddress sysAddress = rakPeer->GetSystemAddressFromGuid(source);
char clientIp[32];
sysAddress.ToString(false, clientIp);
for (int i = 0; i < level->players.size(); i++) {
ServerPlayer* player = (ServerPlayer*) level->players.at(i);
std::string clientLower = player->name;
std::transform(clientLower.begin(), clientLower.end(), clientLower.begin(), ::tolower);
// @todo to lower case
if (nicknameLower == clientLower) {
loginStatus = packet->newProto ? LoginStatus::Failed_TakenNickname : LoginStatus::Failed_ClientOld;
break;
}
}
for (auto& banned : level->bannedPpl) {
if (nicknameLower == banned) {
loginStatus = packet->newProto ? LoginStatus::Failed_Banned : LoginStatus::Failed_ClientOld;
break;
}
}
for (auto& banned : level->bannedIps) {
if (clientIp == banned) {
loginStatus = packet->newProto ? LoginStatus::Failed_Banned : LoginStatus::Failed_ClientOld;
break;
}
}
RakNet::BitStream bitStream;
LoginStatusPacket(loginStatus).write(&bitStream);
@@ -199,13 +312,16 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac
//
// Valid client version
//
Player* newPlayer = new ServerPlayer(minecraft, level);
Player* newPlayer = new ServerPlayer(minecraft, level, packet->newProto);
minecraft->gameMode->initAbilities(newPlayer->abilities);
newPlayer->owner = source;
newPlayer->name = packet->clientName.C_String();
_pendingPlayers.push_back(newPlayer);
LOGI("Adding new player... isCreative: %i\n", minecraft->isCreativeMode());
// Reset the player so he doesn't spawn inside blocks
while (newPlayer->y > 0) {
newPlayer->setPos(newPlayer->x, newPlayer->y, newPlayer->z);
@@ -228,7 +344,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, LoginPac
level->getLevelData()->getGeneratorVersion(),
gameType,
newPlayer->entityId,
newPlayer->x, newPlayer->y - newPlayer->heightOffset, newPlayer->z
newPlayer->x, newPlayer->y - newPlayer->heightOffset, newPlayer->z,
LevelConstants::CHUNK_CACHE_WIDTH
).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
@@ -288,7 +405,6 @@ void ServerSideNetworkHandler::onReady_ClientGeneration(const RakNet::RakNetGUID
#else
LOGW("%s joined the game\n", newPlayer->name.c_str());
#endif
// Send all Entities to the new player
for (unsigned int i = 0; i < level->entities.size(); ++i) {
Entity* e = level->entities[i];
@@ -301,6 +417,36 @@ void ServerSideNetworkHandler::onReady_ClientGeneration(const RakNet::RakNetGUID
}
}
if (!minecraft->level->getLevelStorage()->loadPlayer(*newPlayer)) {
LOGW("Failed to load %s data\n", newPlayer->name.c_str());
}
// Credits to EpikIzCool
bitStream.Reset();
MovePlayerPacket mv(newPlayer->entityId, newPlayer->x, newPlayer->y - newPlayer->heightOffset,
newPlayer->z, newPlayer->xRot, newPlayer->yRot);
mv.write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
bitStream.Reset();
SetHealthPacket hp(newPlayer->health);
hp.write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
if (newPlayer->hasRespawnPosition()) {
bitStream.Reset();
SetSpawnPositionPacket sp(newPlayer->getRespawnPosition());
sp.write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
}
bitStream.Reset();
SendInventoryPacket(newPlayer, false).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
// Additional packets
// * set spawn
/*
@@ -314,6 +460,8 @@ void ServerSideNetworkHandler::onReady_ClientGeneration(const RakNet::RakNetGUID
bitStream.Reset();
AddPlayerPacket(newPlayer).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, true);
PluginsManager::get().emit("PlayerJoin", LuaPlayer(source));
}
//
@@ -338,19 +486,42 @@ void ServerSideNetworkHandler::onReady_RequestedChunks(const RakNet::RakNetGUID&
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlayerPacket* packet)
{
if (!level) return;
// LOGI("MovePlayerPacket\n");
if (Entity* entity = level->getEntity(packet->entityId)) {
ServerPlayer* player = (ServerPlayer*) getPlayer(source);
//LOGI("MovePlayerPacket\n");
if (Entity* entity = level->getEntity(packet->entityId))
{
entity->xd = entity->yd = entity->zd = 0;
// int timeElapsed = minecraft->getTicks() - player->getLastMoveTicks();
// if (timeElapsed > 0) {
// float dist = player->distanceTo(packet->x, player->y, packet->z);
// float speed = dist / (minecraft->getTicks() - player->getLastMoveTicks());
// player->setLastMoveTicks(minecraft->getTicks());
// float maxSpeed = (minecraft->isCreativeMode()) ? 1.65f : 1.f;
// if (speed > maxSpeed) {
// MovePlayerPacket refuse(player->entityId, player->x, player->y, player->z, player->xRot, player->yRot);
// return raknetInstance->send(refuse);
// }
// }
PluginsManager::get().emit(
"PlayerMovement",
LuaPlayer(source),
packet->x, packet->y, packet->z, packet->yRot, packet->xRot, // newPos
player->x, player->y, player->z, player->yRot, player->xRot // oldPos
);
entity->xd = entity->yd = entity->zd = 0;
entity->lerpTo(packet->x, packet->y, packet->z, packet->yRot, packet->xRot, 3);
// broadcast this packet to other clients
redistributePacket(packet, source);
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBlockPacket* packet){
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBlockPacket* packet) {
if (!level) return;
Player* player = getPlayer(source);
@@ -368,12 +539,31 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBl
if (oldTile != NULL && changed) {
level->playSound(x + 0.5f, y + 0.5f, z + 0.5f, oldTile->soundType->getBreakSound(), (oldTile->soundType->getVolume() + 1) / 2, oldTile->soundType->getPitch() * 0.8f);
if (minecraft->gameMode->isSurvivalType() && player->canDestroy(oldTile))
//oldTile->spawnResources(level, x, y, z, data, 1); //@todo
if (minecraft->gameMode->isSurvivalType() && player->canDestroy(oldTile)) {
// From SurvivalMode.cpp
// Why tf i have to copy this shit from SurvivalMode class
// Why SurvivalMode class locked to LOCAL MINECRAFT PLAYER :sob: :sob: :sob: :sob: :sob: :sob: :sob: :sob:
// @fix @warn @ahtung @alert
ItemInstance* item = player->inventory->getSelected();
if (item != NULL) {
item->mineBlock(oldTile->id, x, y, z);
if (item->count == 0) {
//item->snap(minecraft->player);
player->inventory->clearSlot(player->inventory->selected);
}
}
// oldTile->spawnResources(level, x, y, z, data, 1); //@todo
oldTile->playerDestroy(level, player, x, y, z, data);
}
oldTile->destroy(level, x, y, z, data);
// RemoveEntityPacket packet(e->entityId);
// redistributePacket(&packet, rakPeer->GetMyGUID());
}
LOGI("Remove block [%i, %i, %i]\n", packet->x, packet->y, packet->z);
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RequestChunkPacket* packet)
@@ -403,6 +593,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RequestC
raknetInstance->send(source, p);
}
}
// LOGI("Requested chunk [%i, %i]\n", packet->x, packet->z);
}
void ServerSideNetworkHandler::levelGenerated( Level* level )
@@ -429,23 +621,31 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerEq
if (!player) return;
if (rakPeer->GetMyGUID() == player->owner) return;
LOGI("Equip item: id %i aux %i\n", packet->itemId, packet->itemAuxValue);
// override the player's inventory
//int slot = player->inventory->getSlot(packet->itemId, packet->itemAuxValue);
int slot = Inventory::MAX_SELECTION_SIZE;
if (slot >= 0) {
if (packet->itemId == 0) {
player->inventory->clearSlot(slot);
} else {
// @note: 128 is an ugly hack for depletable items.
// @todo: fix
ItemInstance newItem(packet->itemId, 128, packet->itemAuxValue);
player->inventory->replaceSlot(slot, &newItem);
}
player->inventory->moveToSelectedSlot(slot, true);
redistributePacket(packet, source);
} else {
LOGW("Warning: Remote player doesn't have his thing, Odd!\n");
int slot = player->inventory->getSlot(packet->itemId, packet->itemAuxValue);
if (slot >= 0 && slot != packet->inventorySlot && packet->itemId != 0) {
LOGW("PlayerEquipmentPacket: Item in player inventory but slots doesn't match!");
packet->inventorySlot = slot;
}
if (slot < 0 && packet->itemId != 0) {
LOGW("PlayerEquipmentPacket: Remote player doesn't have his thing (or crafted it)!\n");
SendInventoryPacket newInventory (player, false);
raknetInstance->send(newInventory);
return;
}
player->inventory->selectSlot(packet->selectedSlot);
player->inventory->linkSlot(packet->selectedSlot, packet->inventorySlot, true);
player->inventory->print();
redistributePacket(packet, source);
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerArmorEquipmentPacket* packet) {
@@ -455,6 +655,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, PlayerAr
if (!player) return;
if (rakPeer->GetMyGUID() == player->owner) return;
// LOGI("Equip armor: %i %i %i %i\n", packet->head, packet->torso, packet->legs, packet->feet);
packet->fillIn(player);
redistributePacket(packet, source);
}
@@ -466,6 +668,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Interact
Entity* entity = level->getEntity(packet->targetId);
if (src && entity && src->isPlayer())
{
LOGI("Interact: source %i target %i\n", packet->sourceId, packet->targetId);
Player* player = (Player*) src;
if (InteractPacket::Attack == packet->action) {
player->swing();
@@ -506,14 +710,75 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, AnimateP
}
redistributePacket(packet, source);
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet) {
LOGI("WantCreatePacket\n");
Entity* entity = level->getEntity(packet->playerId);
if (entity && entity->isPlayer()) {
Player* p = (Player*)entity;
auto playerInv = p->inventory;
ItemInstance wantCreate;
wantCreate.id = packet->itemId;
wantCreate.count = packet->count;
wantCreate.setAuxValue(packet->auxValue);
Recipe* recipe = Recipes::getInstance()->getRecipeFor(wantCreate);
std::vector<ItemInstance> items = recipe->getItemPack().getItemInstances();
std::vector<int> checkForExists = {};
for (int i = Inventory::MAX_SELECTION_SIZE; i < p->inventory->getContainerSize(); ++i) {
auto itm = p->inventory->getItem(i);
if (itm != NULL) {
for (int y = 0; y < items.size(); y++) {
auto itmRecipe = items.at(y);
if (itmRecipe.id == itm->id && itm->count >= itmRecipe.count) {
checkForExists.push_back(itm->id);
}
}
}
}
if (checkForExists.empty()) {
return;
}
for (int i = 0; i < items.size(); i++) {
auto item = items.at(i);
auto it = std::find(checkForExists.begin(), checkForExists.end(), item.id);
if (it == checkForExists.end() && checkForExists.size() > 1) {
return;
}
}
for (int i = 0; i < items.size(); i++) {
p->inventory->removeResource(ItemInstance(items.at(i).id, items.at(i).count, items.at(i).getAuxValue()));
}
// TakeItemPacket itemAdd(p->entityId, wantCreate.count, wantCreate.getAuxValue(), wantCreate.id);
// raknetInstance->send(source, itemAdd);
p->inventory->add(new ItemInstance(wantCreate.id, wantCreate.count, wantCreate.getAuxValue()));
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemPacket* packet)
{
if (!level) return;
LOGI("UseItemPacket\n");
LOGI("UseItemPacket: id %i data %i\n", packet->itemId, packet->itemData);
Entity* entity = level->getEntity(packet->entityId);
if (entity && entity->isPlayer()) {
LOGI("%f %f %f \n", entity->x, entity->y, entity->z);
Player* player = (Player*) entity;
int x = packet->x, y = packet->y, z = packet->z;
Tile* t = Tile::tiles[level->getTile(x, y, z)];
@@ -522,7 +787,41 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemP
if (t && t->use(level, x, y, z, player)) return;
if (packet->item.isNull()) return;
ItemInstance* item = &packet->item;
ItemInstance* packetItem = &packet->item;
int slot = player->inventory->getSlot(packet->itemId, packet->itemData);
if (slot < 0) {
LOGW("UseItemPacket: Player doesn't have this item!\n");
auto pos = Vec3(packet->x, packet->y, packet->z);
if (ItemInstance::isBlock(packetItem)) {
LOGI("UseItemPacket: This is even block!!!\n");
pos.x += packet->clickX;
pos.y += packet->clickY;
pos.z += packet->clickZ;
}
UpdateBlockPacket refuse(pos.x, pos.y, pos.z, level->getTile(pos.x, pos.y, pos.z), level->getData(pos.x, pos.y, pos.z));
raknetInstance->send(refuse);
return;
}
ItemInstance* item = player->inventory->getItem(slot);
player->x = packet->playerX;
player->y = packet->playerY;
player->z = packet->playerZ;
player->bb.x0 = packet->playerX0;
player->bb.y0 = packet->playerY0;
player->bb.z0 = packet->playerZ0;
player->bb.x1 = packet->playerX1;
player->bb.y1 = packet->playerY1;
player->bb.z1 = packet->playerZ1;
if(packet->face == 255) {
// Special case: x,y,z means direction-of-action
@@ -533,6 +832,10 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemP
minecraft->gameMode->useItemOn(player, level, item, packet->x, packet->y, packet->z, packet->face,
Vec3(packet->clickX + packet->x, packet->clickY + packet->y, packet->clickZ + packet->z));
}
if (item && item->count <= 0) {
player->inventory->clearSlot(slot);
}
//LOGW("Use Item not working! Out of synch?\n");
@@ -544,6 +847,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, UseItemP
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, EntityEventPacket* packet) {
if (!level) return;
LOGI("EntityEventPacket: id %i\n", packet->eventId);
if (Entity* e = level->getEntity(packet->entityId))
e->handleEntityEvent(packet->eventId);
}
@@ -577,6 +882,11 @@ void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SendInv
{
if (!level) return;
LOGI("SendInventoryPacket:\n");
for (int i = 0; i < packet->numItems; i++) {
LOGI("\t %i: %s (%i)\n", i, packet->items.at(i).getName().c_str(), packet->items.at(i).count);
}
Entity* entity = level->getEntity(packet->entityId);
if (entity && entity->isPlayer()) {
Player* p = (Player*)entity;
@@ -592,15 +902,27 @@ void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, DropIte
{
if (!level) return;
LOGI("DropItemPacket\n");
Entity* entity = level->getEntity(packet->entityId);
if (entity && entity->isPlayer()) {
Player* p = (Player*)entity;
p->drop(new ItemInstance(packet->item), packet->dropType != 0);
// p->drop(new ItemInstance(packet->item), packet->dropType != 0);
int slot = p->inventory->getSlot(packet->item.id, packet->item.getAuxValue());
if (slot < 0) {
LOGW("DropItemPacket: player doesn't have these items!\n");
return;
}
p->inventory->dropSlot(slot, false, packet->dropType != 0);
}
}
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet) {
if (!level) return;
LOGI("ContainerClosePacket\n");
Player* p = findPlayer(level, &source);
if (!p) return;
@@ -612,6 +934,16 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ContainerSetSlotPacket* packet) {
if (!level) return;
const char* type = "unknown";
switch (packet->setType) {
case ContainerSetSlotPacket::SETTYPE_ADD: type = "add"; break;
case ContainerSetSlotPacket::SETTYPE_SET: type = "set"; break;
case ContainerSetSlotPacket::SETTYPE_TAKE: type = "take"; break;
};
LOGI("ContainerSetSlot: slot %i item %s type %s\n", packet->slot, packet->item.getName().c_str(), type);
Player* p = findPlayer(level, &source);
if (!p) return;
@@ -619,11 +951,79 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe
LOGW("User has no container!\n");
return;
}
if (p->containerMenu->containerId != packet->containerId)
{
if (p->containerMenu->containerId != packet->containerId) {
LOGW("Wrong container id: %d vs %d\n", p->containerMenu->containerId, packet->containerId);
return;
}
if (packet->item.count > 64) {
LOGW("ContainerSetSlotPacket: player tried to put more than 64");
return;
}
auto contItems = p->containerMenu->getItems();
// find same item in player inventory (used not in all cases)
int invSlot = p->inventory->getSlot(packet->item.id, packet->item.getAuxValue());
auto invItem = p->inventory->getItem(invSlot);
if (contItems.at(packet->slot).id == 0 && packet->item.id != 0) {
LOGI("ContainerSetSlotPacket: player tried to put items to slot %i\n", packet->slot);
if (invSlot < 0) {
LOGW("ContainerSetSlotPacket: player doesn't have this item\n");
return;
}
if (invItem->count < packet->item.count) {
LOGW("ContainerSetSlotPacket: player tried to put more than he have\n");
packet->item.count = invItem->count;
}
invItem->count -= packet->item.count;
if (invItem->count <= 0) {
p->inventory->removeItem(invItem);
}
} else if(contItems.at(packet->slot).id == packet->item.id) {
int deltaItem = packet->item.count - contItems.at(packet->slot).count;
if (deltaItem > 0) {
LOGI("ContainerSetSlotPacket: player tried to add %i items to slot %i\n", deltaItem, packet->slot);
auto invItem = p->inventory->getItem(invSlot);
if (invSlot < 0) {
LOGW("ContainerSetSlotPacket: player doesn't have this item\n");
return;
}
if (invItem->count < deltaItem) {
LOGW("ContainerSetSlotPacket: player tried to put more than he have");
packet->item.count -= (deltaItem - invItem->count);
deltaItem = invItem->count;
}
invItem->count -= deltaItem;
if (invItem->count <= 0) {
p->inventory->removeItem(invItem);
}
} else if (deltaItem < 0) {
LOGW("ContainerSetSlotPacket: player tried to take %i items from slot %i\n", -deltaItem, packet->slot);
p->inventory->add(new ItemInstance(packet->item.getItem(), -deltaItem, contItems.at(packet->slot).getAuxValue()));
}
} else if(contItems.at(packet->slot).id && !packet->item.id) {
LOGI("ContainerSetSlotPacket: player tried to take all items from slot %i\n", packet->slot);
packet->item.count = 0;
packet->item.setAuxValue(0);
p->inventory->add(new ItemInstance(contItems.at(packet->slot).getItem(), contItems.at(packet->slot).count, contItems.at(packet->slot).getAuxValue()));
} else {
LOGW("ContainerSetSlotPacket: illegal container operation in slot %i\n", packet->slot);
return;
}
if (ContainerType::FURNACE == p->containerMenu->containerType) {
//LOGI("Server:Setting slot %d: %s\n", packet->slot, packet->item.toString().c_str());
@@ -635,6 +1035,8 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, Containe
p->containerMenu->setSlot(packet->slot, &packet->item);
//p->containerMenu->setSlot(packet->slot, packet->item.isNull()? NULL : &packet->item);
}
p->inventory->print();
}
void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SetHealthPacket* packet )
@@ -657,6 +1059,8 @@ void ServerSideNetworkHandler::handle( const RakNet::RakNetGUID& source, SignUpd
if (!level)
return;
LOGI("SignUpdate: [%i, %i, %i]\n", packet->x, packet->y, packet->z);
TileEntity* te = level->getTileEntity(packet->x, packet->y, packet->z);
if (TileEntity::isType(te, TileEntityType::Sign)) {
SignTileEntity* ste = (SignTileEntity*) te;
@@ -713,3 +1117,9 @@ Player* ServerSideNetworkHandler::getPlayer( const RakNet::RakNetGUID& source )
if (source == level->players[i]->owner) return level->players[i];
return NULL;
}
void ServerSideNetworkHandler::sendPrivate(Packet& packet, const RakNet::RakNetGUID& source) {
RakNet::BitStream bitStream;
packet.write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
}

View File

@@ -58,19 +58,29 @@ public:
virtual void handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SignUpdatePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ChatPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, MessagePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, WantCreatePacket* packet);
bool allowsIncomingConnections() { return _allowIncoming; }
void allowIncomingConnections(bool doAllow);
Player* popPendingPlayer(const RakNet::RakNetGUID& source);
void displayGameMessage(const std::string& message);
private:
/**
* @brief Send packet to all players
*/
void redistributePacket(Packet* packet, const RakNet::RakNetGUID& fromPlayer);
/**
* @brief Send packer private with GUID
*/
void sendPrivate(Packet& packet, const RakNet::RakNetGUID& source);
Player* getPlayer(const RakNet::RakNetGUID& source);
private:
Minecraft* minecraft;
Level* level;

View File

@@ -236,9 +236,9 @@ std::string CommandServer::parse(ConnectedClient& client, const std::string& s)
if (x0 < 0) x0 = 0;
if (y0 < 0) y0 = 0;
if (z0 < 0) z0 = 0;
if (x1 >= LEVEL_WIDTH ) x1 = LEVEL_WIDTH - 1;
if (y1 >= LEVEL_HEIGHT) y1 = LEVEL_HEIGHT - 1;
if (z1 >= LEVEL_DEPTH ) z1 = LEVEL_DEPTH - 1;
if (x1 >= LevelConstants::LEVEL_WIDTH ) x1 = LevelConstants::LEVEL_WIDTH - 1;
if (y1 >= LevelConstants::LEVEL_HEIGHT) y1 = LevelConstants::LEVEL_HEIGHT - 1;
if (z1 >= LevelConstants::LEVEL_DEPTH ) z1 = LevelConstants::LEVEL_DEPTH - 1;
for (int y = y0; y <= y1; ++y)
for (int z = z0; z <= z1; ++z)
@@ -456,7 +456,7 @@ std::string CommandServer::parse(ConnectedClient& client, const std::string& s)
sw.start();
// Save a cuboid around the player
const int CSize = CHUNK_CACHE_WIDTH;
const int CSize = LevelConstants::CHUNK_CACHE_WIDTH;
int cx = (int)e->x / CSize;
int cz = (int)e->z / CSize;
@@ -504,7 +504,7 @@ bool CommandServer::handleCheckpoint(bool doRestore ) {
const int cz = restorePos.z;
const int y0 = restorePos.y;
const int y1 = y0 + RestoreHeight;
const int CSize = CHUNK_CACHE_WIDTH;
const int CSize = LevelConstants::CHUNK_CACHE_WIDTH;
const int numChunkBytes = RestoreHeight * CSize * CSize * 20 / 8;
if (!restoreBuffer) {

View File

@@ -33,18 +33,18 @@ public:
unsigned char* blockIds = chunk->getBlockData();
DataLayer& blockData = chunk->data;
const int setSize = LEVEL_HEIGHT / 8;
const int setShift = 4; // power of LEVEL_HEIGHT / 8
const int setSize = LevelConstants::LEVEL_HEIGHT / 8;
const int setShift = 4; // power of LevelConstants::LEVEL_HEIGHT / 8
chunkData.Reset();
for (int i = 0; i < CHUNK_COLUMNS; i++)
for (int i = 0; i < LevelConstants::CHUNK_COLUMNS; i++)
{
unsigned char updateBits = chunk->updateMap[i];
chunkData.Write(updateBits);
if (updateBits > 0)
{
int colDataPosition = (i % CHUNK_WIDTH) << 11 | (i / CHUNK_WIDTH) << 7;
int colDataPosition = (i % LevelConstants::CHUNK_WIDTH) << 11 | (i / LevelConstants::CHUNK_WIDTH) << 7;
for (int set = 0; set < 8; set++)
{

View File

@@ -9,17 +9,20 @@ public:
RakNet::RakString clientName;
int clientNetworkVersion;
int clientNetworkLowestSupportedVersion;
bool newProto;
LoginPacket()
: clientNetworkVersion(-1),
clientNetworkLowestSupportedVersion(-1)
clientNetworkLowestSupportedVersion(-1),
newProto(false)
{
}
LoginPacket(const RakNet::RakString& clientName, int clientVersion)
LoginPacket(const RakNet::RakString& clientName, int clientVersion, bool newProto)
: clientName(clientName),
clientNetworkVersion(clientVersion),
clientNetworkLowestSupportedVersion(clientVersion)
clientNetworkLowestSupportedVersion(clientVersion),
newProto(newProto)
{
}
@@ -29,6 +32,7 @@ public:
bitStream->Write(clientName);
bitStream->Write(clientNetworkVersion);
bitStream->Write(clientNetworkLowestSupportedVersion);
bitStream->Write(newProto);
}
void read(RakNet::BitStream* bitStream)
@@ -39,6 +43,11 @@ public:
if (bitStream->GetNumberOfUnreadBits() > 0) {
bitStream->Read(clientNetworkVersion);
bitStream->Read(clientNetworkLowestSupportedVersion);
// Checking for new proto
if (bitStream->GetNumberOfUnreadBits() > 0) {
bitStream->Read(newProto);
}
}
}

View File

@@ -3,10 +3,13 @@
#include "../Packet.h"
// wtf why not enum
namespace LoginStatus {
const int Success = 0;
const int Failed_ClientOld = 1;
const int Failed_ServerOld = 2;
const int Failed_TakenNickname = 3;
const int Failed_Banned = 4;
}
class LoginStatusPacket : public Packet {

View File

@@ -50,5 +50,7 @@
#include "TileEventPacket.h"
#include "UpdateBlockPacket.h"
#include "UseItemPacket.h"
#include "RemoveItemPacket.h"
#include "WantCreatePacket.h"
#include "TakeItemPacket.h"
#endif /*NET_MINECRAFT_NETWORK_PACKET__PacketInclude_H__*/

View File

@@ -9,15 +9,19 @@ public:
int entityId;
unsigned short itemId;
unsigned short itemAuxValue;
unsigned char selectedSlot;
unsigned char inventorySlot;
PlayerEquipmentPacket()
{
}
PlayerEquipmentPacket(int entityId, int itemId, int data)
PlayerEquipmentPacket(int entityId, int itemId, int data, int selSlot, int invSlot)
: entityId(entityId),
itemId(itemId),
itemAuxValue(data)
itemAuxValue(data),
selectedSlot(selSlot),
inventorySlot(invSlot)
{
}
@@ -28,6 +32,8 @@ public:
bitStream->Write(entityId);
bitStream->Write(itemId);
bitStream->Write(itemAuxValue);
bitStream->Write(selectedSlot);
bitStream->Write(inventorySlot);
}
void read(RakNet::BitStream* bitStream)
@@ -35,6 +41,8 @@ public:
bitStream->Read(entityId);
bitStream->Read(itemId);
bitStream->Read(itemAuxValue);
bitStream->Read(selectedSlot);
bitStream->Read(inventorySlot);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)

View File

@@ -0,0 +1,54 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__RemoveItemPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__RemoveItemPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class RemoveItemPacket: public Packet
{
public:
RemoveItemPacket() {
}
RemoveItemPacket(int playerId, int count, int auxValue, int itemId)
:
playerId(playerId),
count(count),
auxValue(auxValue),
itemId(itemId)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_REMOVEITEM));
bitStream->Write(itemId);
bitStream->Write(count);
bitStream->Write(auxValue);
bitStream->Write(playerId);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(itemId);
bitStream->Read(count);
bitStream->Read(auxValue);
bitStream->Read(playerId);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (RemoveItemPacket*)this);
}
int playerId;
int itemId;
int count;
int auxValue;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__RemoveItemPacket_H__*/

View File

@@ -2,13 +2,14 @@
#define NET_MINECRAFT_NETWORK_PACKET__SendInventoryPacket_H__
#include "../Packet.h"
#include "world/entity/player/Inventory.h"
#include "world/inventory/FillingContainer.h"
#include <array>
class SendInventoryPacket: public Packet
{
public:
SendInventoryPacket()
{
}
SendInventoryPacket() {}
SendInventoryPacket(Player* player, bool dropItems)
: entityId(player->entityId),
@@ -21,10 +22,15 @@ public:
ItemInstance* item = inv->getItem(i);
items.push_back(item? *item : ItemInstance());
}
for (int i = 0; i < NumArmorItems; ++i) {
ItemInstance* item = player->getArmor(i);
items.push_back(item? *item : ItemInstance());
}
for (int i = 0; i < inv->numLinkedSlots; ++i) {
linkedSlot[i] = inv->linkedSlots[i];
}
}
void write(RakNet::BitStream* bitStream)
@@ -39,6 +45,13 @@ public:
// Armor
for (int i = 0; i < NumArmorItems; ++i)
PacketUtil::writeItemInstance(items[i + numItems], bitStream);
int lSlots = Inventory::MAX_SELECTION_SIZE;
// Linked slots
bitStream->Write(lSlots);
for (int i = 0; i < lSlots; ++i)
bitStream->Write(linkedSlot[i]);
}
void read(RakNet::BitStream* bitStream)
@@ -50,6 +63,12 @@ public:
// Inventory, Armor
for (int i = 0; i < numItems + NumArmorItems; ++i)
items.push_back(PacketUtil::readItemInstance(bitStream));
// Linked slots
int lSlots = 0;
bitStream->Read(lSlots);
for (int i = 0; i < lSlots; ++i)
bitStream->Read(linkedSlot[i]);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
@@ -62,6 +81,8 @@ public:
short numItems;
unsigned char extra;
std::array<FillingContainer::LinkedSlot, Inventory::MAX_SELECTION_SIZE> linkedSlot;
static const int ExtraDrop = 1;
static const int NumArmorItems = 4;
};

View File

@@ -2,6 +2,7 @@
#define NET_MINECRAFT_NETWORK_PACKET__StartGamePacket_H__
#include "../Packet.h"
#include "world/level/LevelConstants.h"
#include <cstdint>
class StartGamePacket : public Packet
@@ -14,18 +15,20 @@ public:
int entityId;
float x, y, z;
int chunkCacheWidth = 0;
StartGamePacket()
{
}
StartGamePacket(long seed, int levelGeneratorVersion, int gameType, int entityId, float x, float y, float z)
StartGamePacket(long seed, int levelGeneratorVersion, int gameType, int entityId, float x, float y, float z, int chunkCacheWidth)
: levelSeed((int32_t)seed),
levelGeneratorVersion(levelGeneratorVersion),
gameType(gameType),
entityId(entityId),
x(x),
y(y),
z(z)
z(z),
chunkCacheWidth(chunkCacheWidth)
{
}
@@ -40,6 +43,7 @@ public:
bitStream->Write(x);
bitStream->Write(y);
bitStream->Write(z);
bitStream->Write(LevelConstants::CHUNK_CACHE_WIDTH);
}
void read(RakNet::BitStream* bitStream)
@@ -51,6 +55,10 @@ public:
bitStream->Read(x);
bitStream->Read(y);
bitStream->Read(z);
if (bitStream->GetNumberOfUnreadBits() > 0) {
bitStream->Read(chunkCacheWidth);
}
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)

View File

@@ -0,0 +1,54 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__TakeItemPacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__TakeItemPacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class TakeItemPacket: public Packet
{
public:
TakeItemPacket() {
}
TakeItemPacket(int playerId, int count, int auxValue, int itemId)
:
playerId(playerId),
count(count),
auxValue(auxValue),
itemId(itemId)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_TAKEITEM));
bitStream->Write(itemId);
bitStream->Write(count);
bitStream->Write(auxValue);
bitStream->Write(playerId);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(itemId);
bitStream->Read(count);
bitStream->Read(auxValue);
bitStream->Read(playerId);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (TakeItemPacket*)this);
}
int playerId;
int itemId;
int count;
int auxValue;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__TakeItemPacket_H__*/

View File

@@ -16,10 +16,14 @@ public:
short itemId;
unsigned char itemData;
ItemInstance item;
float playerX, playerY, playerZ;
float playerX0, playerY0, playerZ0;
float playerX1, playerY1, playerZ1;
UseItemPacket() {}
UseItemPacket(int x, int y, int z, int face, const ItemInstance* item, int entityId, float clickX, float clickY, float clickZ)
UseItemPacket(int x, int y, int z, int face, const ItemInstance* item, int entityId, float clickX, float clickY, float clickZ,
float plrX, float plrY, float plrZ, float plrX0, float plrY0, float plrZ0, float plrX1, float plrY1, float plrZ1)
: x(x),
y(y),
z(z),
@@ -29,17 +33,36 @@ public:
entityId(entityId),
clickX(clickX),
clickY(clickY),
clickZ(clickZ)
clickZ(clickZ),
playerX(plrX),
playerY(plrY),
playerZ(plrZ),
playerX0(plrX0),
playerY0(plrY0),
playerZ0(plrZ0),
playerX1(plrX1),
playerY1(plrY1),
playerZ1(plrZ1)
{}
UseItemPacket(const ItemInstance* item, int entityId, const Vec3& aim)
UseItemPacket(const ItemInstance* item, int entityId, const Vec3& aim, float plrX, float plrY, float plrZ,
float plrX0, float plrY0, float plrZ0, float plrX1, float plrY1, float plrZ1)
: face(255),
itemId(item? item->id : 0),
itemData(item? item->getAuxValue() : 0),
entityId(entityId),
x((int)(aim.x * 32768.0f)),
y((int)(aim.y * 32768.0f)),
z((int)(aim.z * 32768.0f))
z((int)(aim.z * 32768.0f)),
playerX(plrX),
playerY(plrY),
playerZ(plrZ),
playerX0(plrX0),
playerY0(plrY0),
playerZ0(plrZ0),
playerX1(plrX1),
playerY1(plrY1),
playerZ1(plrZ1)
{
}
@@ -57,6 +80,15 @@ public:
bitStream->Write(clickX);
bitStream->Write(clickY);
bitStream->Write(clickZ);
bitStream->Write(playerX);
bitStream->Write(playerY);
bitStream->Write(playerZ);
bitStream->Write(playerX0);
bitStream->Write(playerY0);
bitStream->Write(playerZ0);
bitStream->Write(playerX1);
bitStream->Write(playerY1);
bitStream->Write(playerZ1);
}
void read(RakNet::BitStream* bitStream)
@@ -74,7 +106,15 @@ public:
item.id = itemId;
item.setAuxValue(itemData);
item.count = (itemId == 0 && itemData == 0)? 0 : 1;
bitStream->Read(playerX);
bitStream->Read(playerY);
bitStream->Read(playerZ);
bitStream->Read(playerX0);
bitStream->Read(playerY0);
bitStream->Read(playerZ0);
bitStream->Read(playerX1);
bitStream->Read(playerY1);
bitStream->Read(playerZ1);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)

View File

@@ -0,0 +1,54 @@
#ifndef NET_MINECRAFT_NETWORK_PACKET__WantCreatePacket_H__
#define NET_MINECRAFT_NETWORK_PACKET__WantCreatePacket_H__
//package net.minecraft.network.packet;
#include "../Packet.h"
class WantCreatePacket: public Packet
{
public:
WantCreatePacket() {
}
WantCreatePacket(int playerId, int count, int auxValue, int itemId)
:
playerId(playerId),
count(count),
auxValue(auxValue),
itemId(itemId)
{
}
void write(RakNet::BitStream* bitStream)
{
bitStream->Write((RakNet::MessageID)(ID_USER_PACKET_ENUM + PACKET_WANTCREATEITEM));
bitStream->Write(itemId);
bitStream->Write(count);
bitStream->Write(auxValue);
bitStream->Write(playerId);
}
void read(RakNet::BitStream* bitStream)
{
bitStream->Read(itemId);
bitStream->Read(count);
bitStream->Read(auxValue);
bitStream->Read(playerId);
}
void handle(const RakNet::RakNetGUID& source, NetEventCallback* callback)
{
callback->handle(source, (WantCreatePacket*)this);
}
int playerId;
int itemId;
int count;
int auxValue;
};
#endif /*NET_MINECRAFT_NETWORK_PACKET__WantCreatePacket_H__*/

160
src/plugins/LuaPlayer.hpp Normal file
View File

@@ -0,0 +1,160 @@
#pragma once
#include <cstdint>
#include <raknet/RakNetTypes.h>
#include <plugins/PluginsManager.hpp>
#include <network/ServerSideNetworkHandler.h>
#include <world/entity/player/Player.h>
#include <client/Minecraft.h>
#include <network/packet/ChatPacket.h>
#include <network/packet/MovePlayerPacket.h>
#include <network/packet/RemoveItemPacket.h>
#include <network/packet/SetHealthPacket.h>
#include <network/packet/TakeItemPacket.h>
#include <world/entity/player/Inventory.h>
// TODO: Optimize includes
class LuaPlayer {
public:
LuaPlayer(const RakNet::RakNetGUID source) : m_source(source) {}
Player* getPlayer() {
auto mc = PluginsManager::get().getMinecraft();
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback;
auto plr = ss->getPlayer(m_source);
return plr;
}
std::string getNickname() {
auto plr = getPlayer();
if (plr != nullptr) return plr->name;
return "";
}
std::tuple<float, float, float, float, float> getPos() {
auto plr = getPlayer();
if (plr != nullptr) return {plr->x, plr->y, plr->z, plr->yRot, plr->xRot};
return {0, 0, 0, 0, 0};
}
void setPos(float x, float y, float z, float yRot, float xRot) {
auto plr = getPlayer();
if (plr == nullptr) return;
auto mc = PluginsManager::get().getMinecraft();
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback;
// plr->x = x;
// plr->y = y;
// plr->z = z;
// plr->yRot = yRot;
// plr->xRot = xRot;
plr->xd = plr->yd = plr->zd = 0;
plr->lerpTo(x, y, z, yRot, xRot, 3);
MovePlayerPacket move(plr->entityId, x, y, z, yRot, xRot);
ss->sendPrivate(move, m_source);
}
void sendMessage(std::string msg) {
auto mc = PluginsManager::get().getMinecraft();
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback;
ChatPacket packet(msg);
ss->sendPrivate(packet, m_source);
}
void addItem(int id, int count, int auxValue) {
auto plr = getPlayer();
if (plr == nullptr) return;
auto mc = PluginsManager::get().getMinecraft();
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback;
auto item = new ItemInstance(id, count, auxValue);
if (!plr->inventory->add(item)) {
plr->inventory->add(item);
}
TakeItemPacket itemAdd(plr->entityId, count, auxValue, id);
ss->sendPrivate(itemAdd, m_source);
}
std::tuple<int, int, int> getItem(int index) {
auto plr = getPlayer();
if (plr == nullptr) return {0, 0, 0};
auto item = plr->inventory->getItem(index);
if (item != nullptr) {
return {item->id, item->count, item->getAuxValue()};
} else {
return {0, 0, 0};
}
}
void clearInventory() {
auto plr = getPlayer();
if (plr == nullptr) return;
auto mc = PluginsManager::get().getMinecraft();
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback;
for (int i = Inventory::MAX_SELECTION_SIZE; i < plr->inventory->getContainerSize(); i++) {
auto itm = plr->inventory->getItem(i);
if (itm != NULL) {
printf("remove %d \n", plr->inventory->removeResource(ItemInstance(itm->id, itm->count, itm->getAuxValue())));
RemoveItemPacket itemAdd(plr->entityId, itm->count, itm->getAuxValue(), itm->id);
ss->sendPrivate(itemAdd, m_source);
}
}
}
sol::table getInventory() {
auto plr = getPlayer();
if (plr == nullptr) return {};
sol::table inv = PluginsManager::get().getLua().create_table();
for (int i = Inventory::MAX_SELECTION_SIZE; i < plr->inventory->getContainerSize(); i++) {
auto itm = plr->inventory->getItem(i);
if (itm != NULL) {
inv[i - 8] = {itm->id, itm->count, itm->getAuxValue()};
} else {
inv[i - 8] = sol::lua_nil;
}
}
return inv;
}
int getHp() {
auto plr = getPlayer();
if (plr == nullptr) return -1;
return plr->health;
}
void setHp(int hp) {
auto plr = getPlayer();
if (plr == nullptr) return;
plr->health = hp;
auto mc = PluginsManager::get().getMinecraft();
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback;
SetHealthPacket hpPacket(plr->health);
ss->sendPrivate(hpPacket, m_source);
}
private:
const RakNet::RakNetGUID m_source;
};

11
src/plugins/LuaServer.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include <plugins/LuaServer.hpp>
#include <plugins/PluginsManager.hpp>
#include <network/ServerSideNetworkHandler.h>
#include <client/Minecraft.h>
void LuaServer::sendServerMessage(std::string msg) {
auto mc = PluginsManager::get().getMinecraft();
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback;
ss->displayGameMessage(msg);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include <string>
class LuaServer {
public:
void sendServerMessage(std::string msg);
};

View File

@@ -0,0 +1,9 @@
#pragma once
class MessageEvent {
public:
bool m_decline;
void setDecline(bool decline) { m_decline = decline; }
private:
};

View File

@@ -0,0 +1,103 @@
#include <plugins/PluginsManager.hpp>
#include <plugins/LuaPlayer.hpp>
#include <plugins/LuaServer.hpp>
#include <client/Minecraft.h>
#include <filesystem>
#include "MessageEvent.hpp"
namespace fs = std::filesystem;
int PluginsManager::emitCommands(std::string command, const RakNet::RakNetGUID& source) {
std::vector<std::string> args;
std::string cmd;
int i = 0;
std::string word;
std::stringstream ss(command);
while (ss >> word) {
if (i == 0) {
cmd = word;
} else {
args.push_back(word);
}
i++;
}
auto it = m_luaCommands.find(cmd);
if (it == m_luaCommands.end()) return 1;
for (auto& callback : it->second) {
sol::protected_function_result result = callback(LuaPlayer(source), sol::as_table(args));
if (!result.valid()) {
sol::error err = result;
std::cout << err.what() << std::endl;
}
}
return 0;
}
void PluginsManager::init(Minecraft& minecraft) {
m_lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::io);
registerTypes();
m_minecraft = &minecraft;
}
void PluginsManager::registerTypes() {
// @note you cant just do that, because lua doesnt have access to the class in this case
// m_lua.set_function("subscribe", &PluginsManager::subscribe);
m_lua.set_function("subscribe", [this](std::string event, sol::protected_function func) {
m_callbacks[event].push_back(func);
});
m_lua.set_function("addCommand", [this](std::string commandName, sol::function func) {
m_luaCommands[commandName].push_back(func);
});
m_lua.new_usertype<LuaServer>(
"Server",
"sendMessage", &LuaServer::sendServerMessage
);
m_lua.new_usertype<LuaPlayer>(
"Player",
"getNickname", &LuaPlayer::getNickname,
"getPos", &LuaPlayer::getPos,
"setPos", &LuaPlayer::setPos,
"sendMessage", &LuaPlayer::sendMessage,
"getInventory", &LuaPlayer::getInventory,
"addItem", &LuaPlayer::addItem,
"getItem", &LuaPlayer::getItem,
"clearInventory", &LuaPlayer::clearInventory,
"getHp", &LuaPlayer::getHp,
"setHp", &LuaPlayer::setHp
);
m_lua.new_usertype<MessageEvent>(
"MessageEvent",
"setDecline", &MessageEvent::setDecline
);
m_lua["Server"] = &m_srv;
}
void PluginsManager::loadPlugins() {
std::string path = "plugins/";
if (fs::exists(path)) {
for (const auto& entry : fs::directory_iterator(path)) {
if (!fs::is_directory(entry.path().string())) {
m_lua.script_file(entry.path().string());
}
}
} else {
std::filesystem::create_directory(path);
}
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include <unordered_map>
#include <sol/sol.hpp>
#include <vector>
#include <iostream>
#include <plugins/LuaServer.hpp>
#include <raknet/RakNetTypes.h>
class Minecraft;
class PluginsManager {
public:
static inline PluginsManager& get() {
static PluginsManager inst;
return inst;
}
void init(Minecraft& minecraft);
void registerTypes();
void loadPlugins();
sol::state& getLua() { return m_lua; }
// @ai @note maybe we should rewrite it...
// problem that i dont know how to pass args in sol::function dynamically
// so i used ai
// sry :(
template<typename... Args>
void emit(std::string event, Args&&... args) {
auto it = m_callbacks.find(event);
if (it == m_callbacks.end()) return;
for (auto& callback : it->second) {
sol::protected_function_result result = callback(std::forward<Args>(args)...);
if (!result.valid()) {
sol::error err = result;
std::cout << err.what() << std::endl;
}
}
}
int emitCommands(std::string command, const RakNet::RakNetGUID& source);
Minecraft* getMinecraft() { return m_minecraft; }
private:
std::unordered_map<std::string, std::vector<sol::function>> m_callbacks;
std::unordered_map<std::string, std::vector<sol::function>> m_luaCommands;
LuaServer m_srv;
sol::state m_lua;
Minecraft* m_minecraft;
};

View File

@@ -142,8 +142,8 @@ void seedMT( unsigned int seed, unsigned int *state, unsigned int *&next, int &l
// so-- that's why the only change I made is to restrict to odd seeds.
//
register unsigned int x = ( seed | 1U ) & 0xFFFFFFFFU, *s = state;
register int j;
unsigned int x = ( seed | 1U ) & 0xFFFFFFFFU, *s = state;
int j;
for ( left = 0, *s++ = x, j = N; --j;
*s++ = ( x *= 69069U ) & 0xFFFFFFFFU )
@@ -154,8 +154,8 @@ void seedMT( unsigned int seed, unsigned int *state, unsigned int *&next, int &l
unsigned int reloadMT( unsigned int *state, unsigned int *&next, int &left )
{
register unsigned int * p0 = state, *p2 = state + 2, *pM = state + M, s0, s1;
register int j;
unsigned int * p0 = state, *p2 = state + 2, *pM = state + M, s0, s1;
int j;
if ( left < -1 )
seedMT( 4357U );

View File

@@ -17,6 +17,11 @@ ArgumentsSettings::ArgumentsSettings(int numArguments, char** arguments)
levelName = std::string(arguments[a+1]);
a++; // Skip the next argument since it's part of this one.
}
} else if(strcmp(arguments[a], "--gamemode") == 0) {
if(a + 1 < numArguments) {
gamemode = std::string(arguments[a+1]);
a++; // Skip the next argument since it's part of this one.
}
} else if(strcmp(arguments[a], "--leveldir") == 0) {
if(a + 1 < numArguments) {
levelDir = std::string(arguments[a+1]);
@@ -51,6 +56,9 @@ std::string ArgumentsSettings::getServerKey() {
std::string ArgumentsSettings::getCachePath() {
return cachePath;
}
std::string ArgumentsSettings::getGamemode() {
return gamemode;
}
std::string ArgumentsSettings::getLevelDir() {
return levelDir;
}

View File

@@ -4,20 +4,27 @@
class ArgumentsSettings {
public:
ArgumentsSettings(int numArguments, char** arguments);
std::string getExternalPath();
std::string getLevelName();
std::string getServerKey();
std::string getCachePath();
std::string getLevelDir();
std::string getGamemode();
bool getShowHelp();
int getPort();
private:
std::string cachePath;
std::string externalPath;
std::string levelName;
std::string gamemode;
std::string levelDir;
std::string serverKey;
bool showHelp;
int port;
};

View File

@@ -12,16 +12,19 @@ ServerLevel::ServerLevel(LevelStorage* levelStorage, const std::string& levelNam
void ServerLevel::updateSleepingPlayerList() {
bool allPlayersWasSleeping = allPlayersAreSleeping;
allPlayersAreSleeping = !players.empty();
for(PlayerList::iterator it = players.begin(); it != players.end(); ++it) {
for (PlayerList::iterator it = players.begin(); it != players.end(); ++it) {
Player* player = *it;
if(!player->isSleeping()) {
if (!player->isSleeping()) {
allPlayersAreSleeping = false;
break;
}
}
if(!allPlayersWasSleeping && allPlayersAreSleeping) {
if (!allPlayersWasSleeping && allPlayersAreSleeping) {
levelEvent(NULL, LevelEvent::ALL_PLAYERS_SLEEPING, 0, 0, 0, 0);
for(PlayerList::iterator it = players.begin(); it != players.end(); ++it) {
for (PlayerList::iterator it = players.begin(); it != players.end(); ++it) {
(*it)->setAllPlayersSleeping();
}
}
@@ -29,23 +32,26 @@ void ServerLevel::updateSleepingPlayerList() {
void ServerLevel::awakenAllPlayers() {
allPlayersAreSleeping = false;
for(PlayerList::iterator it = players.begin(); it != players.end(); ++it) {
for (PlayerList::iterator it = players.begin(); it != players.end(); ++it) {
Player* player = *it;
if(player->isSleeping()) {
if (player->isSleeping()) {
player->stopSleepInBed(false, false, true);
player->health = Player::MAX_HEALTH;
player->lastHealth = Player::MAX_HEALTH;
}
}
SetHealthPacket packet(Player::MAX_HEALTH);
raknetInstance->send(packet);
}
bool ServerLevel::allPlayersSleeping() {
if(allPlayersAreSleeping && !isClientSide) {
if (allPlayersAreSleeping && !isClientSide) {
// all players are sleeping, but have they slept long enough?
for(PlayerList::iterator it = players.begin(); it != players.end(); ++it) {
if(!(*it)->isSleepingLongEnough()) {
for (PlayerList::iterator it = players.begin(); it != players.end(); ++it) {
if (!(*it)->isSleepingLongEnough()) {
return false;
}
}
@@ -55,13 +61,17 @@ bool ServerLevel::allPlayersSleeping() {
return false;
}
void ServerLevel::tick(){
void ServerLevel::tick() {
super::tick();
if(allPlayersSleeping()) {
if (allPlayersSleeping()) {
long newTime = levelData.getTime() + TICKS_PER_DAY;
levelData.setTime(newTime - (newTime % TICKS_PER_DAY));
SetTimePacket packet(levelData.getTime());
raknetInstance->send(packet);
awakenAllPlayers();
}
}

View File

@@ -19,14 +19,17 @@
#include "../network/packet/AnimatePacket.h"
#include "../world/level/tile/entity/ChestTileEntity.h"
#include "../network/packet/HurtArmorPacket.h"
#include "network/packet/SendInventoryPacket.h"
#include "world/entity/player/Inventory.h"
ServerPlayer::ServerPlayer( Minecraft* minecraft, Level* level )
ServerPlayer::ServerPlayer( Minecraft* minecraft, Level* level, bool proto)
: super(level, minecraft->isCreativeMode()),
_mc(minecraft),
_prevHealth(-999),
_containerCounter(0)
_containerCounter(0),
isNewProto(proto)
{
hasFakeInventory = true;
// hasFakeInventory = true;
footSize = 0;
}
@@ -67,7 +70,16 @@ void ServerPlayer::tick() {
void ServerPlayer::take( Entity* e, int orgCount ) {
TakeItemEntityPacket packet(e->entityId, entityId);
// SendInventoryPacket packet(this, false);
_mc->raknetInstance->send(packet);
printf("TakeItemEntityPacket \n");
LOGI("Inventory:\n");
for (int i = 0; i < inventory->numLinkedSlots; i++) {
auto item = inventory->getItem(i);
if (item)
LOGI("\t %i: %s (%i)\n", i, item->getName().c_str(), item->count);
}
super::take(e, orgCount);
}
@@ -118,20 +130,20 @@ bool ServerPlayer::hasResource( int id ) {
void ServerPlayer::setContainerData( BaseContainerMenu* menu, int id, int value ) {
ContainerSetDataPacket p(menu->containerId, id, value);
_mc->raknetInstance->send(owner, p);
//LOGI("Setting container data for id %d: %d\n", id, value);
LOGI("Setting container data for id %d: %d\n", id, value);
}
void ServerPlayer::slotChanged( BaseContainerMenu* menu, int slot, const ItemInstance& item, bool isResultSlot ) {
if (isResultSlot) return;
ContainerSetSlotPacket p(menu->containerId, slot, item);
_mc->raknetInstance->send(owner, p);
//LOGI("Slot %d changed\n", slot);
LOGI("Slot %d changed\n", slot);
}
void ServerPlayer::refreshContainer( BaseContainerMenu* menu, const std::vector<ItemInstance>& items ) {
ContainerSetContentPacket p(menu->containerId, menu->getItems());
_mc->raknetInstance->send(owner, p);
//LOGI("Refreshing container with %d items\n", items.size());
LOGI("Refreshing container with %zu items\n", items.size());
}
void ServerPlayer::nextContainerCounter() {
@@ -163,3 +175,12 @@ void ServerPlayer::displayClientMessage( const std::string& messageId ) {
ChatPacket package(messageId);
_mc->raknetInstance->send(owner, package);
}
void ServerPlayer::causeFallDamage(float distance) {
int dmg = (int) ceil((distance - 3));
if (dmg > 0) {
SetHealthPacket packet(SetHealthPacket::HEALTH_MODIFY_OFFSET + dmg);
_mc->raknetInstance->send(owner, packet);
}
super::causeFallDamage(distance);
}

View File

@@ -15,7 +15,7 @@ class ServerPlayer: public Player,
{
typedef Player super;
public:
ServerPlayer(Minecraft* minecraft, Level* level);
ServerPlayer(Minecraft* minecraft, Level* level, bool proto);
~ServerPlayer();
@@ -43,6 +43,17 @@ public:
virtual void stopSleepInBed(bool forcefulWakeUp, bool updateLevelList, bool saveRespawnPoint);
void completeUsingItem();
void setLastMoveTicks(int lastMoveTicks) { this->lastMoveTicks = lastMoveTicks; }
int getLastMoveTicks() { return lastMoveTicks; }
void setTicksInAir(int ticksInAir) { this->ticksInAir = ticksInAir; }
int getTicksInAir() { return ticksInAir; }
void setNewProto(bool proto) { isNewProto = proto; }
bool getProto() { return isNewProto; }
virtual void causeFallDamage(float distance);
private:
void nextContainerCounter();
void setContainerMenu( BaseContainerMenu* menu );
@@ -50,6 +61,11 @@ private:
Minecraft* _mc;
int _prevHealth;
int _containerCounter;
int lastMoveTicks = 0;
int ticksInAir = 0;
bool isNewProto = false;
};
#endif /*ServerPlayer_H__*/

View File

@@ -465,6 +465,15 @@ void Entity::tick()
baseTick();
}
void Entity::setOnFire(int numberOfSeconds)
{
int newValue = numberOfSeconds * 20;
if (onFire < newValue)
{
onFire = newValue;
}
}
void Entity::baseTick()
{
TIMER_PUSH("entityBaseTick");
@@ -871,8 +880,8 @@ bool Entity::load( CompoundTag* tag )
// Add a small padding if standing next to the world edges
const float padding = bbWidth * 0.5f + 0.001f;
xx = Mth::clamp(xx, padding, (float)LEVEL_WIDTH - padding);
zz = Mth::clamp(zz, padding, (float)LEVEL_DEPTH - padding);
xx = Mth::clamp(xx, padding, (float)LevelConstants::LEVEL_WIDTH - padding);
zz = Mth::clamp(zz, padding, (float)LevelConstants::LEVEL_DEPTH - padding);
xo = xOld = x = xx;
yo = yOld = y = yy;

View File

@@ -89,6 +89,8 @@ public:
virtual bool isAlive();
virtual bool isOnFire();
virtual void setOnFire(int numberOfSeconds);
virtual bool isPlayer();
virtual bool isCreativeModeAllowed();
@@ -129,6 +131,7 @@ public:
virtual bool isHangingEntity();
virtual int getAuxData();
virtual void checkFallDamage(float ya, bool onGround);
protected:
virtual void setRot(float yRot, float xRot);
@@ -137,7 +140,6 @@ protected:
virtual void resetPos(bool clearMore);
virtual void outOfWorld();
virtual void checkFallDamage(float ya, bool onGround);
virtual void causeFallDamage(float fallDamage2);
virtual void markHurt();

View File

@@ -169,7 +169,9 @@ void Mob::playAmbientSound()
level->playSound(this, ambient, getSoundVolume(), getVoicePitch());
}
}
bool Mob::isOnFire() {
return onFire > 0 || getSharedFlag(SharedFlagsInformation::FLAG_ONFIRE);
}
void Mob::baseTick()
{
oAttackAnim = attackAnim;
@@ -177,6 +179,18 @@ void Mob::baseTick()
TIMER_PUSH("mobBaseTick");
// @TODO - check if this section i added to make fire render in mp doesnt break crap - shredder
if (!level->isClientSide) {
// Server side: Tell the client if this mob/player is still burning
setSharedFlag(SharedFlagsInformation::FLAG_ONFIRE, onFire > 0);
} else {
// Client side: If the server flag says we aren't on fire, extinguish local visual timer
if (!getSharedFlag(SharedFlagsInformation::FLAG_ONFIRE)) {
onFire = 0;
}
}
// todo ends here
if (((ambientSoundTime++ & 15) == 0) && random.nextInt(2000) < ambientSoundTime) {
ambientSoundTime = -getAmbientSoundInterval();
playAmbientSound();
@@ -729,7 +743,6 @@ bool Mob::isWaterMob()
void Mob::aiStep()
{
//@todo? 30 lines of code here in java version
TIMER_PUSH("ai");
if (isImmobile()) {
jumping = false;

View File

@@ -52,6 +52,7 @@ public:
virtual bool isPickable();
virtual bool isPushable();
virtual bool isOnFire();
virtual bool isShootable();
MoveControl* getMoveControl();
@@ -223,6 +224,9 @@ protected:
double xc, yc, zc;
public:
void setxxa(float xxa) { this->xxa = xxa; }
void setyya(float yya) { this->yya = yya; }
// Cape position accessors (for renderers)
double getCapeX() const { return xCape; }
double getCapeY() const { return yCape; }

View File

@@ -19,7 +19,7 @@ void Skeleton::aiStep() {
float br = getBrightness(1);
if (br > 0.5f) {
if (level->canSeeSky(Mth::floor(x), Mth::floor(y), Mth::floor(z)) && random.nextFloat() * 3.5f < (br - 0.4f)) {
hurt(NULL, 1);
// hurt(NULL, 1); // no use anymore since i restored setOnFire - shredder
for (int i = 0; i < 5; ++i) {
float xa = (2.0f * random.nextFloat() - 1.0f) * (2.0f * random.nextFloat() - 1.0f) * 0.02f;
@@ -27,7 +27,7 @@ void Skeleton::aiStep() {
float za = (2.0f * random.nextFloat() - 1.0f) * (2.0f * random.nextFloat() - 1.0f) * 0.02f;
level->addParticle(PARTICLETYPE(explode), x + random.nextFloat() * bbWidth * 2 - bbWidth, y + random.nextFloat() * bbHeight, z + random.nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za);
}
//setOnFire(8); //@todo
setOnFire(8); //@todo
}
}
}

View File

@@ -55,7 +55,7 @@ void Zombie::aiStep() {
float br = getBrightness(1);
if (br > 0.5f) {
if (level->canSeeSky(Mth::floor(x), Mth::floor(y), Mth::floor(z)) && random.nextFloat() * 3.5f < (br - 0.4f)) {
hurt(NULL, 1);
// hurt(NULL, 1); // no use anymore since i restored setOnFire - shredder
for (int i = 0; i < 5; ++i) {
float xa = (2.0f * random.nextFloat() - 1.0f) * (2.0f * random.nextFloat() - 1.0f) * 0.02f;
@@ -63,7 +63,7 @@ void Zombie::aiStep() {
float za = (2.0f * random.nextFloat() - 1.0f) * (2.0f * random.nextFloat() - 1.0f) * 0.02f;
level->addParticle(PARTICLETYPE(explode), x + random.nextFloat() * bbWidth * 2 - bbWidth, y + random.nextFloat() * bbHeight, z + random.nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za);
}
//setOnFire(8); //@todo
setOnFire(8); //@todo
}
}
}

View File

@@ -358,3 +358,12 @@ bool Inventory::removeItem( const ItemInstance* samePtr ) {
}
return false;
}
void Inventory::print() {
LOGI("%s's Inventory:\n", player->name.c_str());
for (int i = 0; i < numTotalSlots; i++) {
auto item = getItem(i);
if (item) LOGI("\t %i: %s (%i) %s\n", i, item->getName().c_str(), item->count, (player->inventory->getLinked(i))? "(Linked)" : "");
}
}

View File

@@ -45,6 +45,8 @@ public:
int getAttackDamage(Entity* entity);
float getDestroySpeed(Tile* tile);
bool canDestroy(Tile* tile);
void print();
private:
void setupDefault();
public:

View File

@@ -216,6 +216,7 @@ bool Player::checkBed() {
return (level->getTile(bedPosition.x, bedPosition.y, bedPosition.z) == Tile::bed->id);
}
void Player::tick() {
bool shouldSleep = entityData.getFlag<SharedFlagsInformation::SharedFlagsInformationType>(DATA_PLAYER_FLAGS_ID, PLAYER_SLEEP_FLAG);
if(shouldSleep != isSleeping()) {
@@ -246,11 +247,24 @@ void Player::tick() {
}
super::tick();
if (!level->isClientSide) {
// @TODO - Awful Hack Start, MCPE 0.6 doesn't deal damage with fire to players for some reason on mp, so we force it here to do it, need a better way honestly - shredder
if (level->containsFireTile(this->bb)) {
hurt(NULL, 1);
if (!isInWater()) {
if (onFire <= 0) {
onFire = 20 * 15;
}
}
}
// Awful hack ends here
foodData.tick(this);
// if (containerMenu != NULL && !containerMenu->stillValid(this)) {
// closeContainer();
// }
// if (containerMenu != NULL && !containerMenu->stillValid(this)) {
// closeContainer();
// }
}
}

View File

@@ -141,6 +141,11 @@ bool FillingContainer::add( ItemInstance* item )
// // silently destroy the item when having a full inventory
// item->count = 0;
// return true;
LOGI("Inventory:\n");
for (int i = 0; i < numTotalSlots; i++) {
LOGI("\t %i: %s (%i)\n", i, items.at(i)->getName().c_str(), items.at(i)->count);
}
}
return false;

View File

@@ -290,3 +290,7 @@ bool ItemInstance::isArmorItem( const ItemInstance* instance ) {
return item->isArmor();
}
bool ItemInstance::isBlock(const ItemInstance* instance) {
return instance->id < 256;
}

View File

@@ -81,6 +81,8 @@ public:
static bool isArmorItem(const ItemInstance* instance);
static bool isBlock(const ItemInstance* instance);
/**
* Checks if this item is the same item as the other one, disregarding the
* 'count' value.

View File

@@ -4,6 +4,8 @@
//package net.minecraft.world.item;
#include <string>
#include <plugins/PluginsManager.hpp>
#include <plugins/LuaPlayer.hpp>
#include "Item.h"
#include "ItemInstance.h"
@@ -61,7 +63,7 @@ public:
if (level->setTileAndData(x, y, z, tileId, data)) {
Tile::tiles[tileId]->setPlacedBy(level, x, y, z, player);
level->playSound(x + 0.5f, y + 0.5f, z + 0.5f, tile->soundType->getStepSound(), (tile->soundType->getVolume() + 1) / 2, tile->soundType->getPitch() * 0.8f);
PluginsManager::get().emit("PlayerPlaceBlock", LuaPlayer(player->owner), x, y, z, face, tileId, instance->getAuxValue());
/*
PlaceBlockPacket packet(player->entityId, x, y, z, face, tileId, instance->getAuxValue());
//LOGI("Place block at @ %d, %d, %d\n", x, y, z);

View File

@@ -29,6 +29,9 @@
#include "../Difficulty.h"
#include "../../network/packet/ExplodePacket.h"
const int Level::DEPTH = LevelConstants::LEVEL_HEIGHT;
const int Level::SEA_LEVEL = Level::DEPTH / 2 - 1;
Level::Level(LevelStorage* levelStorage, const std::string& levelName, const LevelSettings& settings, int generatorVersion, Dimension* fixedDimension /* = NULL */)
: levelStorage(levelStorage),
isClientSide(false),
@@ -278,8 +281,8 @@ void Level::tickTiles() {
for (int i = 0; i < pollChunkOffsetsSize; i += 2) {
const int xp = xx + pollChunkOffsets[i];
const int zp = zz + pollChunkOffsets[i+1];
if (xp >= 0 && xp < CHUNK_CACHE_WIDTH &&
zp >= 0 && zp < CHUNK_CACHE_WIDTH)
if (xp >= 0 && xp < LevelConstants::CHUNK_CACHE_WIDTH &&
zp >= 0 && zp < LevelConstants::CHUNK_CACHE_WIDTH)
_chunksToPoll.insert(ChunkPos(xp, zp));
}
}
@@ -427,21 +430,21 @@ bool Level::findPath(Path* path, Entity* from, int xBest, int yBest, int zBest,
*/
/*protected*/
void Level::setInitialSpawn() {
isFindingSpawn = true;
int xSpawn = CHUNK_CACHE_WIDTH * CHUNK_WIDTH / 2; // (Level.MAX_LEVEL_SIZE - 100) * 0;
int ySpawn = 64;
int zSpawn = CHUNK_CACHE_WIDTH * CHUNK_DEPTH / 2; // (Level.MAX_LEVEL_SIZE - 100) * 0;
while (!dimension->isValidSpawn(xSpawn, zSpawn)) {
xSpawn += random.nextInt(32) - random.nextInt(32);
zSpawn += random.nextInt(32) - random.nextInt(32);
isFindingSpawn = true;
int xSpawn = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_WIDTH / 2; // (Level.MAX_LEVEL_SIZE - 100) * 0;
int ySpawn = 64;
int zSpawn = LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_DEPTH / 2; // (Level.MAX_LEVEL_SIZE - 100) * 0;
while (!dimension->isValidSpawn(xSpawn, zSpawn)) {
xSpawn += random.nextInt(32) - random.nextInt(32);
zSpawn += random.nextInt(32) - random.nextInt(32);
if (xSpawn < 4) xSpawn += 32;
if (xSpawn >= LEVEL_WIDTH-4) xSpawn -= 32;
if (xSpawn >= LevelConstants::LEVEL_WIDTH-4) xSpawn -= 32;
if (zSpawn < 4) zSpawn += 32;
if (zSpawn >= LEVEL_DEPTH-4) zSpawn -= 32;
}
levelData.setSpawn(xSpawn, ySpawn, zSpawn);
isFindingSpawn = false;
if (zSpawn >= LevelConstants::LEVEL_DEPTH-4) zSpawn -= 32;
}
levelData.setSpawn(xSpawn, ySpawn, zSpawn);
isFindingSpawn = false;
}
/*public*/
@@ -456,12 +459,12 @@ void Level::validateSpawn() {
zSpawn += random.nextInt(8) - random.nextInt(8);
if (xSpawn < 4) xSpawn += 8;
if (xSpawn >= LEVEL_WIDTH-4) xSpawn -= 8;
if (xSpawn >= LevelConstants::LEVEL_WIDTH-4) xSpawn -= 8;
if (zSpawn < 4) zSpawn += 8;
if (zSpawn >= LEVEL_DEPTH-4) zSpawn -= 8;
}
levelData.setXSpawn(xSpawn);
levelData.setZSpawn(zSpawn);
if (zSpawn >= LevelConstants::LEVEL_DEPTH-4) zSpawn -= 8;
}
levelData.setXSpawn(xSpawn);
levelData.setZSpawn(zSpawn);
}
int Level::getTopTile(int x, int z) {
@@ -944,7 +947,7 @@ HitResult Level::clip(const Vec3& A, const Vec3& b, bool liquid /*= false*/, boo
if (solidOnly && tile != NULL && tile->getAABB(this, xTile0, yTile0, zTile0) == NULL) {
// No collision
} else if (t > 0 && tile->mayPick(data, liquid)) {
if(xTile0 >= 0 && zTile0 >= 0 && xTile0 < LEVEL_WIDTH && zTile0 < LEVEL_WIDTH) {
if(xTile0 >= 0 && zTile0 >= 0 && xTile0 < LevelConstants::LEVEL_WIDTH && zTile0 < LevelConstants::LEVEL_WIDTH) {
HitResult r = tile->clip(this, xTile0, yTile0, zTile0, a, b);
if (r.isHit()) return r;
}
@@ -1984,10 +1987,10 @@ void Level::prepare() {
;
}
bool Level::mayPlace(int tileId, int x, int y, int z, bool ignoreEntities,unsigned char face) {
int targetType = getTile(x, y, z);
const Tile* targetTile = Tile::tiles[targetType];
Tile* tile = Tile::tiles[tileId];
bool Level::mayPlace(int tileId, int x, int y, int z, bool ignoreEntities,unsigned char face) {
int targetType = getTile(x, y, z);
const Tile* targetTile = Tile::tiles[targetType];
Tile* tile = Tile::tiles[tileId];
AABB* aabb = tile->getAABB(this, x, y, z);
if (ignoreEntities) aabb = NULL;
@@ -2247,9 +2250,9 @@ void Level::setNightMode( bool isNightMode ) {
}
bool Level::inRange( int x, int y, int z ) {
return x >= 0 && x < LEVEL_WIDTH
&& y >= 0 && y < LEVEL_HEIGHT
&& z >= 0 && z < LEVEL_DEPTH;
return x >= 0 && x < LevelConstants::LEVEL_WIDTH
&& y >= 0 && y < LevelConstants::LEVEL_HEIGHT
&& z >= 0 && z < LevelConstants::LEVEL_DEPTH;
}
//

View File

@@ -67,8 +67,8 @@ class Level: public LevelSource
public:
static const int MAX_LEVEL_SIZE = 32000000;
static const short DEPTH = LEVEL_HEIGHT;
static const short SEA_LEVEL = DEPTH / 2 - 1;
static const int DEPTH;
static const int SEA_LEVEL;
static const int MAX_BRIGHTNESS = 15;
static const int TICKS_PER_DAY = SharedConstants::TicksPerSecond * 60 * 16;// SharedConstants::TicksPerSecond * 60 * 12; // ORG:20*60*20
@@ -310,6 +310,10 @@ public:
Dimension* dimension;
IRakNetInstance* raknetInstance;
Random random;
std::set<std::string> ops;
std::set<std::string> bannedPpl;
std::set<std::string> bannedIps;
protected:
bool isFindingSpawn;

View File

@@ -0,0 +1,10 @@
#include "LevelConstants.h"
int LevelConstants::LEVEL_HEIGHT = 128;
int LevelConstants::CHUNK_CACHE_WIDTH = 16; // in chunks
int LevelConstants::CHUNK_WIDTH = 16; // in blocks
int LevelConstants::CHUNK_DEPTH = 16;
int LevelConstants::LEVEL_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH * CHUNK_WIDTH;
int LevelConstants::LEVEL_DEPTH = LevelConstants::CHUNK_CACHE_WIDTH * CHUNK_DEPTH;
int LevelConstants::CHUNK_COLUMNS = LevelConstants::CHUNK_WIDTH * LevelConstants::CHUNK_DEPTH;
int LevelConstants::CHUNK_BLOCK_COUNT = LevelConstants::CHUNK_COLUMNS * LevelConstants::LEVEL_HEIGHT;

View File

@@ -1,14 +1,14 @@
#ifndef _MINECRAFT_WORLD_LEVELCONSTANTS_H_
#define _MINECRAFT_WORLD_LEVELCONSTANTS_H_
#pragma once
const int LEVEL_HEIGHT = 128;
const int CHUNK_CACHE_WIDTH = 16; // in chunks
const int CHUNK_WIDTH = 16; // in blocks
const int CHUNK_DEPTH = 16;
const int LEVEL_WIDTH = CHUNK_CACHE_WIDTH * CHUNK_WIDTH;
const int LEVEL_DEPTH = CHUNK_CACHE_WIDTH * CHUNK_DEPTH;
const int CHUNK_COLUMNS = CHUNK_WIDTH * CHUNK_DEPTH;
const int CHUNK_BLOCK_COUNT = CHUNK_COLUMNS * LEVEL_HEIGHT;
#endif
class LevelConstants {
public:
static int CHUNK_CACHE_WIDTH; // in chunks
static int LEVEL_WIDTH;
static int LEVEL_DEPTH;
static int LEVEL_HEIGHT;
static int CHUNK_WIDTH; // in blocks
static int CHUNK_DEPTH;
static int CHUNK_COLUMNS;
static int CHUNK_BLOCK_COUNT;
};

View File

@@ -10,7 +10,7 @@
#include "../LevelConstants.h"
class ChunkCache: public ChunkSource {
//static const int CHUNK_CACHE_WIDTH = CHUNK_CACHE_WIDTH; // WAS 32;
//static const int LevelConstants::CHUNK_CACHE_WIDTH = LevelConstants::CHUNK_CACHE_WIDTH; // WAS 32;
static const int MAX_SAVES = 2;
public:
ChunkCache(Level* level_, ChunkStorage* storage_, ChunkSource* source_)
@@ -24,14 +24,17 @@ public:
isChunkCache = true;
//emptyChunk = new EmptyLevelChunk(level_, emptyChunkBlocks, 0, 0);
emptyChunk = new EmptyLevelChunk(level_, NULL, 0, 0);
memset(chunks, 0, sizeof(LevelChunk*) * CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH);
chunks = new LevelChunk *[LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH];
memset(chunks, 0, sizeof(LevelChunk*) * LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH);
LOGI("Chunks allocated.");
}
~ChunkCache() {
delete source;
delete emptyChunk;
for (int i = 0; i < CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH; i++)
for (int i = 0; i < LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH; i++)
{
if (chunks[i])
{
@@ -42,7 +45,7 @@ public:
}
bool fits(int x, int z) {
return (x >= 0 && z >= 0 && x < CHUNK_CACHE_WIDTH && z < CHUNK_CACHE_WIDTH);
return (x >= 0 && z >= 0 && x < LevelConstants::CHUNK_CACHE_WIDTH && z < LevelConstants::CHUNK_CACHE_WIDTH);
}
bool hasChunk(int x, int z) {
@@ -52,9 +55,9 @@ public:
if (x == xLast && z == zLast && last != NULL) {
return true;
}
int xs = x & (CHUNK_CACHE_WIDTH - 1);
int zs = z & (CHUNK_CACHE_WIDTH - 1);
int slot = xs + zs * CHUNK_CACHE_WIDTH;
int xs = x & (LevelConstants::CHUNK_CACHE_WIDTH - 1);
int zs = z & (LevelConstants::CHUNK_CACHE_WIDTH - 1);
int slot = xs + zs * LevelConstants::CHUNK_CACHE_WIDTH;
return chunks[slot] != NULL && (chunks[slot] == emptyChunk || chunks[slot]->isAt(x, z));
}
@@ -71,9 +74,9 @@ public:
}
if (!fits(x, z)) return emptyChunk;
//if (!level->isFindingSpawn && !fits(x, z)) return emptyChunk;
int xs = x & (CHUNK_CACHE_WIDTH - 1);
int zs = z & (CHUNK_CACHE_WIDTH - 1);
int slot = xs + zs * CHUNK_CACHE_WIDTH;
int xs = x & (LevelConstants::CHUNK_CACHE_WIDTH - 1);
int zs = z & (LevelConstants::CHUNK_CACHE_WIDTH - 1);
int slot = xs + zs * LevelConstants::CHUNK_CACHE_WIDTH;
if (!hasChunk(x, z)) {
if (chunks[slot] != NULL) {
chunks[slot]->unload();
@@ -195,15 +198,15 @@ public:
std::string gatherStats() {
// return "ChunkCache: 1024";
std::stringstream ss;
ss << "ChunkCache: " << CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH;
ss << "ChunkCache: " << LevelConstants::CHUNK_CACHE_WIDTH * LevelConstants::CHUNK_CACHE_WIDTH;
return ss.str();
}
void saveAll(bool onlyUnsaved) {
if (storage != NULL) {
std::vector<LevelChunk*> chunks;
for (int z = 0; z < CHUNK_CACHE_WIDTH; ++z)
for (int x = 0; x < CHUNK_CACHE_WIDTH; ++x) {
for (int z = 0; z < LevelConstants::CHUNK_CACHE_WIDTH; ++z)
for (int x = 0; x < LevelConstants::CHUNK_CACHE_WIDTH; ++x) {
LevelChunk* chunk = level->getChunk(x, z);
if (!onlyUnsaved || chunk->shouldSave(false))
chunks.push_back( chunk );
@@ -214,7 +217,7 @@ public:
private:
LevelChunk* load(int x, int z) {
if (storage == NULL) return emptyChunk;
if (x < 0 || x >= CHUNK_CACHE_WIDTH || z < 0 || z >= CHUNK_CACHE_WIDTH)
if (x < 0 || x >= LevelConstants::CHUNK_CACHE_WIDTH || z < 0 || z >= LevelConstants::CHUNK_CACHE_WIDTH)
{
return emptyChunk;
}
@@ -257,7 +260,7 @@ private:
LevelChunk* emptyChunk;
ChunkSource* source;
ChunkStorage* storage;
LevelChunk* chunks[CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH];
LevelChunk** chunks;
Level* level;
LevelChunk* last;

Some files were not shown because too many files have changed in this diff Show More