mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
Merge remote-tracking branch 'upstream/main' into crossplatform
This commit is contained in:
commit
48477ac0c6
53
.clang-format
Normal file
53
.clang-format
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
---
|
||||||
|
BasedOnStyle: Microsoft
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: true
|
||||||
|
AfterControlStatement: Always
|
||||||
|
AfterEnum: true
|
||||||
|
AfterExternBlock: true
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: true
|
||||||
|
AfterObjCDeclaration: true
|
||||||
|
AfterStruct: true
|
||||||
|
AfterUnion: false
|
||||||
|
BeforeCatch: true
|
||||||
|
BeforeElse: true
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
ColumnLimit: 0
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IndentAccessModifiers: false
|
||||||
|
IndentCaseBlocks: true
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentExportBlock: true
|
||||||
|
IndentExternBlock: AfterExternBlock
|
||||||
|
IndentGotoLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 4
|
||||||
|
InsertBraces: true
|
||||||
|
InsertNewlineAtEOF: true
|
||||||
|
NamespaceIndentation: None
|
||||||
|
PointerAlignment: Right
|
||||||
|
RemoveParentheses: Leave
|
||||||
|
RemoveSemicolon: false
|
||||||
|
SeparateDefinitionBlocks: Leave
|
||||||
|
ShortNamespaceLines: 1
|
||||||
|
SkipMacroDefinitionBody: false
|
||||||
|
SortIncludes: CaseSensitive
|
||||||
|
SpacesInParens: Never
|
||||||
|
SpacesInParensOptions:
|
||||||
|
ExceptDoubleParentheses: false
|
||||||
|
InCStyleCasts: false
|
||||||
|
InConditionalStatements: false
|
||||||
|
InEmptyParentheses: false
|
||||||
|
Other: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Latest
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
||||||
16
.github/pull_request_template.md
vendored
16
.github/pull_request_template.md
vendored
|
|
@ -1,23 +1,23 @@
|
||||||
# Pull Request
|
<!--
|
||||||
|
Note: IF YOUR PR CHANGES THE GAME BEHAVIOR VISIBLY, REMEMBER TO ATTACH A GAMEPLAY FOOTAGE (or at least a screenshot) OF YOU *ACTUALLY* PLAYING THE GAME WITH YOUR CHANGES. Untested PRs are *NOT* welcome. Please don't forget to describe what did you do in each commit in your PR.
|
||||||
## Note: IF YOUR PR CHANGES THE GAME BEHAVIOR VISIBLY, REMEMBER TO ATTACH A GAMEPLAY FOOTAGE (or at least a screenshot) OF YOU *ACTUALLY* PLAYING THE GAME WITH YOUR CHANGES. Untested PRs are *NOT* welcome. Please don't forget to describe what did you do in each commit in your PR.
|
-->
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
Briefly describe the changes this PR introduces.
|
<!-- Briefly describe the changes this PR introduces. -->
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
### Previous Behavior
|
### Previous Behavior
|
||||||
*Describe how the code behaved before this change.*
|
<!-- Describe how the code behaved before this change. -->
|
||||||
|
|
||||||
### Root Cause
|
### Root Cause
|
||||||
*Explain the core reason behind the erroneous/old behavior (e.g., bug, design flaw, missing edge case).*
|
<!-- Explain the core reason behind the erroneous/old behavior (e.g., bug, design flaw, missing edge case). -->
|
||||||
|
|
||||||
### New Behavior
|
### New Behavior
|
||||||
*Describe how the code behaves after this change.*
|
<!-- Describe how the code behaves after this change. -->
|
||||||
|
|
||||||
### Fix Implementation
|
### Fix Implementation
|
||||||
*Detail exactly how the issue was resolved (specific code changes, algorithms, logic flows).*
|
<!-- Detail exactly how the issue was resolved (specific code changes, algorithms, logic flows). -->
|
||||||
|
|
||||||
## Related Issues
|
## Related Issues
|
||||||
- Fixes #[issue-number]
|
- Fixes #[issue-number]
|
||||||
|
|
|
||||||
7
.github/workflows/nightly.yml
vendored
7
.github/workflows/nightly.yml
vendored
|
|
@ -8,6 +8,7 @@ on:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '.gitignore'
|
- '.gitignore'
|
||||||
- '*.md'
|
- '*.md'
|
||||||
|
- '.github/*.md'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
@ -35,4 +36,8 @@ jobs:
|
||||||
with:
|
with:
|
||||||
tag_name: nightly
|
tag_name: nightly
|
||||||
name: Nightly Release
|
name: Nightly Release
|
||||||
files: LCEWindows64.zip
|
body: Requires at least Windows 7 and DirectX 11 compatible GPU to run. Compiled with MSVC v14.44.35207 in Release mode with Whole Program Optimization, as well as `/O2 /Ot /Oi /Ob3 /GF /fp:precise`.
|
||||||
|
files: |
|
||||||
|
LCEWindows64.zip
|
||||||
|
./x64/Release/Minecraft.Client.exe
|
||||||
|
./x64/Release/Minecraft.Client.pdb
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,17 @@ if(MSVC)
|
||||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
function(configure_msvc_target target)
|
||||||
|
target_compile_options(${target} PRIVATE
|
||||||
|
$<$<AND:$<NOT:$<CONFIG:Release>>,$<COMPILE_LANGUAGE:C,CXX>>:/W3>
|
||||||
|
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/W0>
|
||||||
|
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
|
||||||
|
$<$<COMPILE_LANGUAGE:C,CXX>:/FS>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:/EHsc>
|
||||||
|
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/GL /O2 /Oi /GT /GF>
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
# minecraftworld is shared with every backend.
|
# minecraftworld is shared with every backend.
|
||||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/WorldSources.cmake")
|
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/WorldSources.cmake")
|
||||||
list(TRANSFORM MINECRAFT_WORLD_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/")
|
list(TRANSFORM MINECRAFT_WORLD_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/")
|
||||||
|
|
@ -47,10 +58,7 @@ target_compile_definitions(MinecraftWorld PRIVATE
|
||||||
$<$<STREQUAL:${BACKEND},Cross64>:_CROSS64>
|
$<$<STREQUAL:${BACKEND},Cross64>:_CROSS64>
|
||||||
)
|
)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_compile_options(MinecraftWorld PRIVATE
|
configure_msvc_target(MinecraftWorld)
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:/W3 /MP>
|
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:/EHsc>
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClientSources.cmake")
|
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClientSources.cmake")
|
||||||
|
|
@ -82,24 +90,53 @@ if(BACKEND STREQUAL "Windows64")
|
||||||
|
|
||||||
list(TRANSFORM MINECRAFT_CLIENT_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/")
|
list(TRANSFORM MINECRAFT_CLIENT_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/")
|
||||||
|
|
||||||
add_executable(MinecraftClient WIN32 ${MINECRAFT_CLIENT_SOURCES})
|
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClientSources.cmake")
|
||||||
target_include_directories(MinecraftClient PRIVATE
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
# each backend is assumed to change these in some way.
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/include"
|
set(BACKEND_SOURCES
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Xbox/Sentient/Include"
|
"glWrapper.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/x64headers"
|
"stubs.cpp"
|
||||||
)
|
"stdafx.cpp"
|
||||||
target_compile_definitions(MinecraftClient PRIVATE
|
"iob_shim.asm"
|
||||||
$<$<CONFIG:Debug>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_DEBUG;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
|
"Windows64/Iggy/gdraw/gdraw_d3d11.cpp"
|
||||||
$<$<NOT:$<CONFIG:Debug>>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
|
"Windows64/KeyboardMouseInput.cpp"
|
||||||
)
|
"Windows64/Leaderboards/WindowsLeaderboardManager.cpp"
|
||||||
if(MSVC)
|
"Windows64/Windows64_App.cpp"
|
||||||
target_compile_options(MinecraftClient PRIVATE
|
"Windows64/Windows64_Minecraft.cpp"
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:/W /MP>
|
"Windows64/Windows64_UIController.cpp"
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:/EHsc>
|
"Windows64/Network/WinsockNetLayer.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# remove backend specific stuff
|
||||||
|
set(CLIENT_SHARED_SOURCES ${MINECRAFT_CLIENT_SOURCES})
|
||||||
|
list(REMOVE_ITEM CLIENT_SHARED_SOURCES ${BACKEND_SOURCES})
|
||||||
|
list(TRANSFORM CLIENT_SHARED_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/")
|
||||||
|
|
||||||
|
if(BACKEND STREQUAL "Windows64")
|
||||||
|
if(NOT WIN32)
|
||||||
|
message(FATAL_ERROR "The Windows64 backend can only be built on Windows.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
list(TRANSFORM MINECRAFT_CLIENT_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/")
|
||||||
|
|
||||||
|
add_executable(MinecraftClient WIN32 ${MINECRAFT_CLIENT_SOURCES})
|
||||||
|
target_include_directories(MinecraftClient PRIVATE
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/include"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Xbox/Sentient/Include"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/x64headers"
|
||||||
|
)
|
||||||
|
target_compile_definitions(MinecraftClient PRIVATE
|
||||||
|
$<$<CONFIG:Debug>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_DEBUG;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
|
||||||
|
$<$<NOT:$<CONFIG:Debug>>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
|
||||||
|
)
|
||||||
|
if(MSVC)
|
||||||
|
configure_msvc_target(MinecraftClient)
|
||||||
|
target_compile_options(MinecraftClient PRIVATE
|
||||||
|
$<$<CONFIG:Release>:/LTCG /INCREMENTAL:NO>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
set_target_properties(MinecraftClient PROPERTIES
|
set_target_properties(MinecraftClient PROPERTIES
|
||||||
VS_DEBUGGER_WORKING_DIRECTORY "$<TARGET_FILE_DIR:MinecraftClient>"
|
VS_DEBUGGER_WORKING_DIRECTORY "$<TARGET_FILE_DIR:MinecraftClient>"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ Chunk::Chunk(Level *level, LevelRenderer::rteMap &globalRenderableTileEntities,
|
||||||
: globalRenderableTileEntities( &globalRenderableTileEntities ), globalRenderableTileEntities_cs(&globalRenderableTileEntities_cs)
|
: globalRenderableTileEntities( &globalRenderableTileEntities ), globalRenderableTileEntities_cs(&globalRenderableTileEntities_cs)
|
||||||
{
|
{
|
||||||
clipChunk->visible = false;
|
clipChunk->visible = false;
|
||||||
bb = NULL;
|
bb = nullptr;
|
||||||
id = 0;
|
id = 0;
|
||||||
|
|
||||||
this->level = level;
|
this->level = level;
|
||||||
|
|
@ -101,15 +101,15 @@ void Chunk::setPos(int x, int y, int z)
|
||||||
|
|
||||||
float g = 6.0f;
|
float g = 6.0f;
|
||||||
// 4J - changed to just set the value rather than make a new one, if we've already created storage
|
// 4J - changed to just set the value rather than make a new one, if we've already created storage
|
||||||
if( bb == NULL )
|
if( !bb )
|
||||||
{
|
{
|
||||||
bb = AABB::newPermanent(-g, -g, -g, XZSIZE+g, SIZE+g, XZSIZE+g);
|
bb = shared_ptr<AABB>(AABB::newPermanent(-g, -g, -g, XZSIZE+g, SIZE+g, XZSIZE+g));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 4J MGH - bounds are relative to the position now, so the AABB will be setup already, either above, or from the tesselator bounds.
|
// 4J MGH - bounds are relative to the position now, so the AABB will be setup already, either above, or from the tesselator bounds.
|
||||||
// bb->set(-g, -g, -g, SIZE+g, SIZE+g, SIZE+g);
|
// bb->set(-g, -g, -g, SIZE+g, SIZE+g, SIZE+g);
|
||||||
}
|
}
|
||||||
clipChunk->aabb[0] = bb->x0 + x;
|
clipChunk->aabb[0] = bb->x0 + x;
|
||||||
clipChunk->aabb[1] = bb->y0 + y;
|
clipChunk->aabb[1] = bb->y0 + y;
|
||||||
clipChunk->aabb[2] = bb->z0 + z;
|
clipChunk->aabb[2] = bb->z0 + z;
|
||||||
|
|
@ -154,6 +154,7 @@ void Chunk::translateToPos()
|
||||||
|
|
||||||
Chunk::Chunk()
|
Chunk::Chunk()
|
||||||
{
|
{
|
||||||
|
bb = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::makeCopyForRebuild(Chunk *source)
|
void Chunk::makeCopyForRebuild(Chunk *source)
|
||||||
|
|
@ -998,7 +999,7 @@ int Chunk::getList(int layer)
|
||||||
|
|
||||||
void Chunk::cull(Culler *culler)
|
void Chunk::cull(Culler *culler)
|
||||||
{
|
{
|
||||||
clipChunk->visible = culler->isVisible(bb);
|
clipChunk->visible = culler->isVisible(bb.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::renderBB()
|
void Chunk::renderBB()
|
||||||
|
|
@ -1027,10 +1028,7 @@ void Chunk::clearDirty()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Chunk::~Chunk()
|
Chunk::~Chunk() = default;
|
||||||
{
|
|
||||||
delete bb;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Chunk::emptyFlagSet(int layer)
|
bool Chunk::emptyFlagSet(int layer)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,11 @@ public:
|
||||||
int xRender, yRender, zRender;
|
int xRender, yRender, zRender;
|
||||||
int xRenderOffs, yRenderOffs, zRenderOffs;
|
int xRenderOffs, yRenderOffs, zRenderOffs;
|
||||||
|
|
||||||
int xm, ym, zm;
|
int xm, ym, zm;
|
||||||
AABB *bb;
|
shared_ptr<AABB> bb;
|
||||||
ClipChunk *clipChunk;
|
ClipChunk *clipChunk;
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
//public:
|
//public:
|
||||||
// vector<shared_ptr<TileEntity> > renderableTileEntities; // 4J - removed
|
// vector<shared_ptr<TileEntity> > renderableTileEntities; // 4J - removed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,12 @@
|
||||||
#endif
|
#endif
|
||||||
#include "DLCTexturePack.h"
|
#include "DLCTexturePack.h"
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
#include "Xbox\Network\NetworkPlayerXbox.h"
|
||||||
|
#include "Common\Network\PlatformNetworkManagerStub.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef _DURANGO
|
#ifdef _DURANGO
|
||||||
#include "Minecraft.World/DurangoStats.h"
|
#include "Minecraft.World/DurangoStats.h"
|
||||||
#include "Minecraft.World/GenericStats.h"
|
#include "Minecraft.World/GenericStats.h"
|
||||||
|
|
@ -421,7 +427,6 @@ void ClientConnection::handleAddEntity(shared_ptr<AddEntityPacket> packet)
|
||||||
{
|
{
|
||||||
case AddEntityPacket::MINECART:
|
case AddEntityPacket::MINECART:
|
||||||
e = Minecart::createMinecart(level, x, y, z, packet->data);
|
e = Minecart::createMinecart(level, x, y, z, packet->data);
|
||||||
break;
|
|
||||||
case AddEntityPacket::FISH_HOOK:
|
case AddEntityPacket::FISH_HOOK:
|
||||||
{
|
{
|
||||||
// 4J Stu - Brought forward from 1.4 to be able to drop XP from fishing
|
// 4J Stu - Brought forward from 1.4 to be able to drop XP from fishing
|
||||||
|
|
@ -444,7 +449,7 @@ void ClientConnection::handleAddEntity(shared_ptr<AddEntityPacket> packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (owner->instanceof(eTYPE_PLAYER))
|
if (owner != NULL && owner->instanceof(eTYPE_PLAYER))
|
||||||
{
|
{
|
||||||
shared_ptr<Player> player = dynamic_pointer_cast<Player>(owner);
|
shared_ptr<Player> player = dynamic_pointer_cast<Player>(owner);
|
||||||
shared_ptr<FishingHook> hook = shared_ptr<FishingHook>( new FishingHook(level, x, y, z, player) );
|
shared_ptr<FishingHook> hook = shared_ptr<FishingHook>( new FishingHook(level, x, y, z, player) );
|
||||||
|
|
@ -793,7 +798,28 @@ void ClientConnection::handleAddPlayer(shared_ptr<AddPlayerPacket> packet)
|
||||||
if (networkPlayer != NULL) player->m_displayName = networkPlayer->GetDisplayName();
|
if (networkPlayer != NULL) player->m_displayName = networkPlayer->GetDisplayName();
|
||||||
#else
|
#else
|
||||||
// On all other platforms display name is just gamertag so don't check with the network manager
|
// On all other platforms display name is just gamertag so don't check with the network manager
|
||||||
player->m_displayName = player->name;
|
player->m_displayName = player->getName();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
{
|
||||||
|
PlayerUID pktXuid = player->getXuid();
|
||||||
|
const PlayerUID WIN64_XUID_BASE = (PlayerUID)0xe000d45248242f2e;
|
||||||
|
if (pktXuid >= WIN64_XUID_BASE && pktXuid < WIN64_XUID_BASE + MINECRAFT_NET_MAX_PLAYERS)
|
||||||
|
{
|
||||||
|
BYTE smallId = (BYTE)(pktXuid - WIN64_XUID_BASE);
|
||||||
|
INetworkPlayer* np = g_NetworkManager.GetPlayerBySmallId(smallId);
|
||||||
|
if (np != NULL)
|
||||||
|
{
|
||||||
|
NetworkPlayerXbox* npx = (NetworkPlayerXbox*)np;
|
||||||
|
IQNetPlayer* qp = npx->GetQNetPlayer();
|
||||||
|
if (qp != NULL && qp->m_gamertag[0] == 0)
|
||||||
|
{
|
||||||
|
wcsncpy_s(qp->m_gamertag, 32, packet->name.c_str(), _TRUNCATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// printf("\t\t\t\t%d: Add player\n",packet->id,packet->yRot);
|
// printf("\t\t\t\t%d: Add player\n",packet->id,packet->yRot);
|
||||||
|
|
@ -938,6 +964,39 @@ void ClientConnection::handleMoveEntitySmall(shared_ptr<MoveEntityPacketSmall> p
|
||||||
|
|
||||||
void ClientConnection::handleRemoveEntity(shared_ptr<RemoveEntitiesPacket> packet)
|
void ClientConnection::handleRemoveEntity(shared_ptr<RemoveEntitiesPacket> packet)
|
||||||
{
|
{
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (!g_NetworkManager.IsHost())
|
||||||
|
{
|
||||||
|
for (int i = 0; i < packet->ids.length; i++)
|
||||||
|
{
|
||||||
|
shared_ptr<Entity> entity = getEntity(packet->ids[i]);
|
||||||
|
if (entity != NULL && entity->GetType() == eTYPE_PLAYER)
|
||||||
|
{
|
||||||
|
shared_ptr<Player> player = dynamic_pointer_cast<Player>(entity);
|
||||||
|
if (player != NULL)
|
||||||
|
{
|
||||||
|
PlayerUID xuid = player->getXuid();
|
||||||
|
INetworkPlayer* np = g_NetworkManager.GetPlayerByXuid(xuid);
|
||||||
|
if (np != NULL)
|
||||||
|
{
|
||||||
|
NetworkPlayerXbox* npx = (NetworkPlayerXbox*)np;
|
||||||
|
IQNetPlayer* qp = npx->GetQNetPlayer();
|
||||||
|
if (qp != NULL)
|
||||||
|
{
|
||||||
|
extern CPlatformNetworkManagerStub* g_pPlatformNetworkManager;
|
||||||
|
g_pPlatformNetworkManager->NotifyPlayerLeaving(qp);
|
||||||
|
qp->m_smallId = 0;
|
||||||
|
qp->m_isRemote = false;
|
||||||
|
qp->m_isHostPlayer = false;
|
||||||
|
qp->m_gamertag[0] = 0;
|
||||||
|
qp->SetCustomDataValue(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
for (int i = 0; i < packet->ids.length; i++)
|
for (int i = 0; i < packet->ids.length; i++)
|
||||||
{
|
{
|
||||||
level->removeEntity(packet->ids[i]);
|
level->removeEntity(packet->ids[i]);
|
||||||
|
|
|
||||||
|
|
@ -829,6 +829,7 @@ enum EControllerActions
|
||||||
ACTION_MENU_OTHER_STICK_LEFT,
|
ACTION_MENU_OTHER_STICK_LEFT,
|
||||||
ACTION_MENU_OTHER_STICK_RIGHT,
|
ACTION_MENU_OTHER_STICK_RIGHT,
|
||||||
ACTION_MENU_PAUSEMENU,
|
ACTION_MENU_PAUSEMENU,
|
||||||
|
ACTION_MENU_QUICK_MOVE,
|
||||||
|
|
||||||
#ifdef _DURANGO
|
#ifdef _DURANGO
|
||||||
ACTION_MENU_GTC_PAUSE,
|
ACTION_MENU_GTC_PAUSE,
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1978,7 +1978,7 @@ bool CGameNetworkManager::AllowedToPlayMultiplayer(int playerIdx)
|
||||||
return ProfileManager.AllowedToPlayMultiplayer(playerIdx);
|
return ProfileManager.AllowedToPlayMultiplayer(playerIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *CGameNetworkManager::GetOnlineName(int playerIdx)
|
const char *CGameNetworkManager::GetOnlineName(int playerIdx)
|
||||||
{
|
{
|
||||||
return ProfileManager.GetGamertag(playerIdx);
|
return ProfileManager.GetGamertag(playerIdx);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,7 @@ private:
|
||||||
int GetLockedProfile();
|
int GetLockedProfile();
|
||||||
bool IsSignedInLive(int playerIdx);
|
bool IsSignedInLive(int playerIdx);
|
||||||
bool AllowedToPlayMultiplayer(int playerIdx);
|
bool AllowedToPlayMultiplayer(int playerIdx);
|
||||||
char *GetOnlineName(int playerIdx);
|
const char *GetOnlineName(int playerIdx);
|
||||||
|
|
||||||
C4JThread::Event* m_hServerStoppedEvent;
|
C4JThread::Event* m_hServerStoppedEvent;
|
||||||
C4JThread::Event* m_hServerReadyEvent;
|
C4JThread::Event* m_hServerReadyEvent;
|
||||||
|
|
|
||||||
|
|
@ -362,12 +362,23 @@ void CPlatformNetworkManagerStub::HostGame(int localUsersMask, bool bOnlineGame,
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
int port = WIN64_NET_DEFAULT_PORT;
|
int port = WIN64_NET_DEFAULT_PORT;
|
||||||
|
const char* bindIp = NULL;
|
||||||
|
if (g_Win64DedicatedServer)
|
||||||
|
{
|
||||||
|
if (g_Win64DedicatedServerPort > 0)
|
||||||
|
port = g_Win64DedicatedServerPort;
|
||||||
|
if (g_Win64DedicatedServerBindIP[0] != 0)
|
||||||
|
bindIp = g_Win64DedicatedServerBindIP;
|
||||||
|
}
|
||||||
if (!WinsockNetLayer::IsActive())
|
if (!WinsockNetLayer::IsActive())
|
||||||
WinsockNetLayer::HostGame(port);
|
WinsockNetLayer::HostGame(port, bindIp);
|
||||||
|
|
||||||
const wchar_t* hostName = IQNet::m_player[0].m_gamertag;
|
if (WinsockNetLayer::IsActive())
|
||||||
unsigned int settings = app.GetGameHostOption(eGameHostOption_All);
|
{
|
||||||
WinsockNetLayer::StartAdvertising(port, hostName, settings, 0, 0, MINECRAFT_NET_VERSION);
|
const wchar_t* hostName = IQNet::m_player[0].m_gamertag;
|
||||||
|
unsigned int settings = app.GetGameHostOption(eGameHostOption_All);
|
||||||
|
WinsockNetLayer::StartAdvertising(port, hostName, settings, 0, 0, MINECRAFT_NET_VERSION);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ bool ChoiceTask::isCompleted()
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
if (!m_bConfirmMappingComplete &&
|
if (!m_bConfirmMappingComplete &&
|
||||||
(InputManager.GetValue(xboxPad, m_iConfirmMapping) > 0
|
(InputManager.GetValue(xboxPad, m_iConfirmMapping) > 0
|
||||||
|| KMInput.IsKeyDown(VK_RETURN)))
|
|| g_KBMInput.IsKeyDown(VK_RETURN)))
|
||||||
#else
|
#else
|
||||||
if (!m_bConfirmMappingComplete &&
|
if (!m_bConfirmMappingComplete &&
|
||||||
InputManager.GetValue(xboxPad, m_iConfirmMapping) > 0)
|
InputManager.GetValue(xboxPad, m_iConfirmMapping) > 0)
|
||||||
|
|
@ -75,7 +75,7 @@ bool ChoiceTask::isCompleted()
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
if (!m_bCancelMappingComplete &&
|
if (!m_bCancelMappingComplete &&
|
||||||
(InputManager.GetValue(xboxPad, m_iCancelMapping) > 0
|
(InputManager.GetValue(xboxPad, m_iCancelMapping) > 0
|
||||||
|| KMInput.IsKeyDown('B')))
|
|| g_KBMInput.IsKeyDown('B')))
|
||||||
#else
|
#else
|
||||||
if (!m_bCancelMappingComplete &&
|
if (!m_bCancelMappingComplete &&
|
||||||
InputManager.GetValue(xboxPad, m_iCancelMapping) > 0)
|
InputManager.GetValue(xboxPad, m_iCancelMapping) > 0)
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ bool InfoTask::isCompleted()
|
||||||
if(!current)
|
if(!current)
|
||||||
{
|
{
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
if (InputManager.GetValue(pMinecraft->player->GetXboxPad(), (*it).first) > 0 || KMInput.IsKeyDown(VK_SPACE))
|
if (InputManager.GetValue(pMinecraft->player->GetXboxPad(), (*it).first) > 0 || g_KBMInput.IsKeyDown(VK_SPACE))
|
||||||
#else
|
#else
|
||||||
if( InputManager.GetValue(pMinecraft->player->GetXboxPad(), (*it).first) > 0)
|
if( InputManager.GetValue(pMinecraft->player->GetXboxPad(), (*it).first) > 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,12 @@
|
||||||
#include <pad.h>
|
#include <pad.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
#include "..\..\Windows64\KeyboardMouseInput.h"
|
||||||
|
|
||||||
|
SavedInventoryCursorPos g_savedInventoryCursorPos = { 0.0f, 0.0f, false };
|
||||||
|
#endif
|
||||||
|
|
||||||
IUIScene_AbstractContainerMenu::IUIScene_AbstractContainerMenu()
|
IUIScene_AbstractContainerMenu::IUIScene_AbstractContainerMenu()
|
||||||
{
|
{
|
||||||
m_menu = NULL;
|
m_menu = NULL;
|
||||||
|
|
@ -483,6 +489,34 @@ void IUIScene_AbstractContainerMenu::onMouseTick()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
|
||||||
|
{
|
||||||
|
int deltaX = g_KBMInput.GetMouseDeltaX();
|
||||||
|
int deltaY = g_KBMInput.GetMouseDeltaY();
|
||||||
|
|
||||||
|
extern HWND g_hWnd;
|
||||||
|
RECT rc;
|
||||||
|
GetClientRect(g_hWnd, &rc);
|
||||||
|
int winW = rc.right - rc.left;
|
||||||
|
int winH = rc.bottom - rc.top;
|
||||||
|
|
||||||
|
if (winW > 0 && winH > 0)
|
||||||
|
{
|
||||||
|
float scaleX = (float)getMovieWidth() / (float)winW;
|
||||||
|
float scaleY = (float)getMovieHeight() / (float)winH;
|
||||||
|
|
||||||
|
vPointerPos.x += (float)deltaX * scaleX;
|
||||||
|
vPointerPos.y += (float)deltaY * scaleY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deltaX != 0 || deltaY != 0)
|
||||||
|
{
|
||||||
|
bStickInput = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Determine which slot the pointer is currently over.
|
// Determine which slot the pointer is currently over.
|
||||||
ESceneSection eSectionUnderPointer = eSectionNone;
|
ESceneSection eSectionUnderPointer = eSectionNone;
|
||||||
int iNewSlotX = -1;
|
int iNewSlotX = -1;
|
||||||
|
|
@ -703,7 +737,11 @@ void IUIScene_AbstractContainerMenu::onMouseTick()
|
||||||
|
|
||||||
// If there is no stick input, and we are over a slot, then snap pointer to slot centre.
|
// If there is no stick input, and we are over a slot, then snap pointer to slot centre.
|
||||||
// 4J - TomK - only if this particular component allows so!
|
// 4J - TomK - only if this particular component allows so!
|
||||||
if(!m_bPointerDrivenByMouse && CanHaveFocus(eSectionUnderPointer))
|
#ifdef _WINDOWS64
|
||||||
|
if((g_KBMInput.IsMouseGrabbed() || !g_KBMInput.IsKBMActive()) && CanHaveFocus(eSectionUnderPointer))
|
||||||
|
#else
|
||||||
|
if(CanHaveFocus(eSectionUnderPointer))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
vPointerPos.x = vSnapPos.x;
|
vPointerPos.x = vSnapPos.x;
|
||||||
vPointerPos.y = vSnapPos.y;
|
vPointerPos.y = vSnapPos.y;
|
||||||
|
|
@ -1313,42 +1351,60 @@ bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool b
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int buttonNum=0; // 0 = LeftMouse, 1 = RightMouse
|
int buttonNum=0; // 0 = LeftMouse, 1 = RightMouse
|
||||||
BOOL quickKeyHeld=FALSE; // Represents shift key on PC
|
BOOL quickKeyHeld=false; // Represents shift key on PC
|
||||||
|
BOOL quickKeyDown = false; // Represents shift key on PC
|
||||||
BOOL validKeyPress = FALSE;
|
BOOL validKeyPress = false;
|
||||||
bool itemEditorKeyPress = false;
|
bool itemEditorKeyPress = false;
|
||||||
|
|
||||||
// Ignore input from other players
|
// Ignore input from other players
|
||||||
//if(pMinecraft->player->GetXboxPad()!=pInputData->UserIndex) return S_OK;
|
//if(pMinecraft->player->GetXboxPad()!=pInputData->UserIndex) return S_OK;
|
||||||
|
|
||||||
switch(iAction)
|
switch(iAction)
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG_MENUS_ENABLED
|
#ifdef _DEBUG_MENUS_ENABLED
|
||||||
case ACTION_MENU_OTHER_STICK_PRESS:
|
case ACTION_MENU_OTHER_STICK_PRESS:
|
||||||
itemEditorKeyPress = TRUE;
|
itemEditorKeyPress = TRUE;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case ACTION_MENU_A:
|
case ACTION_MENU_A:
|
||||||
#ifdef __ORBIS__
|
#ifdef __ORBIS__
|
||||||
case ACTION_MENU_TOUCHPAD_PRESS:
|
case ACTION_MENU_TOUCHPAD_PRESS:
|
||||||
#endif
|
#endif
|
||||||
if(!bRepeat)
|
if (!bRepeat)
|
||||||
{
|
{
|
||||||
validKeyPress = TRUE;
|
validKeyPress = TRUE;
|
||||||
|
|
||||||
// Standard left click
|
// Standard left click
|
||||||
buttonNum = 0;
|
buttonNum = 0;
|
||||||
quickKeyHeld = FALSE;
|
if (g_KBMInput.IsKeyDown(VK_LSHIFT))
|
||||||
|
|
||||||
if( IsSectionSlotList( m_eCurrSection ) )
|
|
||||||
{
|
{
|
||||||
int currentIndex = getCurrentIndex( m_eCurrSection ) - getSectionStartOffset(m_eCurrSection);
|
{
|
||||||
|
validKeyPress = TRUE;
|
||||||
|
|
||||||
bool bSlotHasItem = !isSlotEmpty(m_eCurrSection, currentIndex);
|
// Shift and left click
|
||||||
if ( bSlotHasItem )
|
buttonNum = 0;
|
||||||
ui.PlayUISFX(eSFX_Press);
|
quickKeyHeld = TRUE;
|
||||||
|
if (IsSectionSlotList(m_eCurrSection))
|
||||||
|
{
|
||||||
|
int currentIndex = getCurrentIndex(m_eCurrSection) - getSectionStartOffset(m_eCurrSection);
|
||||||
|
|
||||||
|
bool bSlotHasItem = !isSlotEmpty(m_eCurrSection, currentIndex);
|
||||||
|
if (bSlotHasItem)
|
||||||
|
ui.PlayUISFX(eSFX_Press);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (IsSectionSlotList(m_eCurrSection))
|
||||||
|
{
|
||||||
|
int currentIndex = getCurrentIndex(m_eCurrSection) - getSectionStartOffset(m_eCurrSection);
|
||||||
|
|
||||||
|
bool bSlotHasItem = !isSlotEmpty(m_eCurrSection, currentIndex);
|
||||||
|
if (bSlotHasItem)
|
||||||
|
ui.PlayUISFX(eSFX_Press);
|
||||||
|
}
|
||||||
|
//
|
||||||
}
|
}
|
||||||
//
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ACTION_MENU_X:
|
case ACTION_MENU_X:
|
||||||
|
|
@ -1370,6 +1426,7 @@ bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACTION_MENU_Y:
|
case ACTION_MENU_Y:
|
||||||
if(!bRepeat)
|
if(!bRepeat)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
struct SavedInventoryCursorPos
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
bool hasSavedPos;
|
||||||
|
};
|
||||||
|
extern SavedInventoryCursorPos g_savedInventoryCursorPos;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Uncomment to enable tap input detection to jump 1 slot. Doesn't work particularly well yet, and I feel the system does not need it.
|
// Uncomment to enable tap input detection to jump 1 slot. Doesn't work particularly well yet, and I feel the system does not need it.
|
||||||
// Would probably be required if we decide to slow down the pointer movement.
|
// Would probably be required if we decide to slow down the pointer movement.
|
||||||
// 4J Stu - There was a request to be able to navigate the scenes with the dpad, so I have used much of the TAP_DETECTION
|
// 4J Stu - There was a request to be able to navigate the scenes with the dpad, so I have used much of the TAP_DETECTION
|
||||||
|
|
@ -265,4 +275,6 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int getPad() = 0;
|
virtual int getPad() = 0;
|
||||||
|
virtual int getMovieWidth() = 0;
|
||||||
|
virtual int getMovieHeight() = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -223,7 +223,6 @@ void IUIScene_CreativeMenu::staticCtor()
|
||||||
ITEM_AUX(Tile::woolCarpet_Id,13) // Green
|
ITEM_AUX(Tile::woolCarpet_Id,13) // Green
|
||||||
ITEM_AUX(Tile::woolCarpet_Id,12) // Brown
|
ITEM_AUX(Tile::woolCarpet_Id,12) // Brown
|
||||||
|
|
||||||
#if 0
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,14) // Red
|
ITEM_AUX(Tile::stained_glass_Id,14) // Red
|
||||||
ITEM_AUX(Tile::stained_glass_Id,1) // Orange
|
ITEM_AUX(Tile::stained_glass_Id,1) // Orange
|
||||||
ITEM_AUX(Tile::stained_glass_Id,4) // Yellow
|
ITEM_AUX(Tile::stained_glass_Id,4) // Yellow
|
||||||
|
|
@ -257,7 +256,6 @@ void IUIScene_CreativeMenu::staticCtor()
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,15) // Black
|
ITEM_AUX(Tile::stained_glass_pane_Id,15) // Black
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,13) // Green
|
ITEM_AUX(Tile::stained_glass_pane_Id,13) // Green
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,12) // Brown
|
ITEM_AUX(Tile::stained_glass_pane_Id,12) // Brown
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _CONTENT_PACKAGE
|
#ifndef _CONTENT_PACKAGE
|
||||||
DEF(eCreativeInventory_ArtToolsDecorations)
|
DEF(eCreativeInventory_ArtToolsDecorations)
|
||||||
|
|
@ -278,40 +276,6 @@ void IUIScene_CreativeMenu::staticCtor()
|
||||||
BuildFirework(list, FireworksItem::TYPE_CREEPER, DyePowderItem::BLUE, 1, true, false);
|
BuildFirework(list, FireworksItem::TYPE_CREEPER, DyePowderItem::BLUE, 1, true, false);
|
||||||
BuildFirework(list, FireworksItem::TYPE_STAR, DyePowderItem::YELLOW, 1, false, false);
|
BuildFirework(list, FireworksItem::TYPE_STAR, DyePowderItem::YELLOW, 1, false, false);
|
||||||
BuildFirework(list, FireworksItem::TYPE_BIG, DyePowderItem::WHITE, 1, true, true);
|
BuildFirework(list, FireworksItem::TYPE_BIG, DyePowderItem::WHITE, 1, true, true);
|
||||||
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,14) // Red
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,1) // Orange
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,4) // Yellow
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,5) // Lime
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,3) // Light Blue
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,9) // Cyan
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,11) // Blue
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,10) // Purple
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,2) // Magenta
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,6) // Pink
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,0) // White
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,8) // Light Gray
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,7) // Gray
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,15) // Black
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,13) // Green
|
|
||||||
ITEM_AUX(Tile::stained_glass_Id,12) // Brown
|
|
||||||
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,14) // Red
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,1) // Orange
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,4) // Yellow
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,5) // Lime
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,3) // Light Blue
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,9) // Cyan
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,11) // Blue
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,10) // Purple
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,2) // Magenta
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,6) // Pink
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,0) // White
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,8) // Light Gray
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,7) // Gray
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,15) // Black
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,13) // Green
|
|
||||||
ITEM_AUX(Tile::stained_glass_pane_Id,12) // Brown
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -858,8 +822,9 @@ IUIScene_CreativeMenu::TabSpec::TabSpec(LPCWSTR icon, int descriptionId, int sta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_staticPerPage = MAX_SIZE - dynamicItems;
|
m_staticPerPage = columns;
|
||||||
m_pages = (int)ceil((float)m_staticItems / m_staticPerPage);
|
const int totalRows = (m_staticItems + columns - 1) / columns;
|
||||||
|
m_pages = std::max<int>(1, totalRows - 5 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
IUIScene_CreativeMenu::TabSpec::~TabSpec()
|
IUIScene_CreativeMenu::TabSpec::~TabSpec()
|
||||||
|
|
@ -894,7 +859,7 @@ void IUIScene_CreativeMenu::TabSpec::populateMenu(AbstractContainerMenu *menu, i
|
||||||
for(; currentGroup < m_staticGroupsCount; ++currentGroup)
|
for(; currentGroup < m_staticGroupsCount; ++currentGroup)
|
||||||
{
|
{
|
||||||
int size = categoryGroups[m_staticGroupsA[currentGroup]].size();
|
int size = categoryGroups[m_staticGroupsA[currentGroup]].size();
|
||||||
if( currentIndex + size < startIndex)
|
if( currentIndex + size <= startIndex)
|
||||||
{
|
{
|
||||||
currentIndex += size;
|
currentIndex += size;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -944,7 +909,7 @@ void IUIScene_CreativeMenu::TabSpec::populateMenu(AbstractContainerMenu *menu, i
|
||||||
for(; currentGroup < m_debugGroupsCount; ++currentGroup)
|
for(; currentGroup < m_debugGroupsCount; ++currentGroup)
|
||||||
{
|
{
|
||||||
int size = categoryGroups[m_debugGroupsA[currentGroup]].size();
|
int size = categoryGroups[m_debugGroupsA[currentGroup]].size();
|
||||||
if( currentIndex + size < startIndex)
|
if( currentIndex + size <= startIndex)
|
||||||
{
|
{
|
||||||
currentIndex += size;
|
currentIndex += size;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -985,7 +950,9 @@ unsigned int IUIScene_CreativeMenu::TabSpec::getPageCount()
|
||||||
#ifndef _CONTENT_PACKAGE
|
#ifndef _CONTENT_PACKAGE
|
||||||
if(app.DebugArtToolsOn())
|
if(app.DebugArtToolsOn())
|
||||||
{
|
{
|
||||||
return (int)ceil((float)(m_staticItems + m_debugItems) / m_staticPerPage);
|
int totalItems = m_staticItems + m_debugItems;
|
||||||
|
const int totalRows = (totalItems + columns - 1) / columns;
|
||||||
|
return std::max<int>(1, totalRows - rows + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1144,7 +1111,15 @@ void IUIScene_CreativeMenu::handleAdditionalKeyPress(int iAction)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ACTION_MENU_OTHER_STICK_DOWN:
|
case ACTION_MENU_OTHER_STICK_DOWN:
|
||||||
++m_tabPage[m_curTab];
|
{
|
||||||
|
int pageStep = TabSpec::rows;
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (g_KBMInput.WasMouseWheelConsumed())
|
||||||
|
{
|
||||||
|
pageStep = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
m_tabPage[m_curTab] += pageStep;
|
||||||
if(m_tabPage[m_curTab] >= specs[m_curTab]->getPageCount())
|
if(m_tabPage[m_curTab] >= specs[m_curTab]->getPageCount())
|
||||||
{
|
{
|
||||||
m_tabPage[m_curTab] = specs[m_curTab]->getPageCount() - 1;
|
m_tabPage[m_curTab] = specs[m_curTab]->getPageCount() - 1;
|
||||||
|
|
@ -1153,9 +1128,18 @@ void IUIScene_CreativeMenu::handleAdditionalKeyPress(int iAction)
|
||||||
{
|
{
|
||||||
switchTab(m_curTab);
|
switchTab(m_curTab);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ACTION_MENU_OTHER_STICK_UP:
|
case ACTION_MENU_OTHER_STICK_UP:
|
||||||
--m_tabPage[m_curTab];
|
{
|
||||||
|
int pageStep = TabSpec::rows;
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (g_KBMInput.WasMouseWheelConsumed())
|
||||||
|
{
|
||||||
|
pageStep = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
m_tabPage[m_curTab] -= pageStep;
|
||||||
if(m_tabPage[m_curTab] < 0)
|
if(m_tabPage[m_curTab] < 0)
|
||||||
{
|
{
|
||||||
m_tabPage[m_curTab] = 0;
|
m_tabPage[m_curTab] = 0;
|
||||||
|
|
@ -1164,6 +1148,7 @@ void IUIScene_CreativeMenu::handleAdditionalKeyPress(int iAction)
|
||||||
{
|
{
|
||||||
switchTab(m_curTab);
|
switchTab(m_curTab);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@ bool UIControl::setupControl(UIScene *scene, IggyValuePath *parent, const string
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __PSVITA__
|
|
||||||
void UIControl::UpdateControl()
|
void UIControl::UpdateControl()
|
||||||
{
|
{
|
||||||
F64 fx, fy, fwidth, fheight;
|
F64 fx, fy, fwidth, fheight;
|
||||||
|
|
@ -55,7 +54,6 @@ void UIControl::UpdateControl()
|
||||||
m_width = (S32)Math::round(fwidth);
|
m_width = (S32)Math::round(fwidth);
|
||||||
m_height = (S32)Math::round(fheight);
|
m_height = (S32)Math::round(fheight);
|
||||||
}
|
}
|
||||||
#endif // __PSVITA__
|
|
||||||
|
|
||||||
void UIControl::ReInit()
|
void UIControl::ReInit()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,8 @@ public:
|
||||||
UIControl();
|
UIControl();
|
||||||
|
|
||||||
virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName);
|
virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName);
|
||||||
#ifdef __PSVITA__
|
|
||||||
void UpdateControl();
|
void UpdateControl();
|
||||||
|
#ifdef __PSVITA__
|
||||||
void setHidden(bool bHidden) {m_bHidden=bHidden;}
|
void setHidden(bool bHidden) {m_bHidden=bHidden;}
|
||||||
bool getHidden(void) {return m_bHidden;}
|
bool getHidden(void) {return m_bHidden;}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#include "UIController.h"
|
#include "UIController.h"
|
||||||
#include "UI.h"
|
#include "UI.h"
|
||||||
#include "UIScene.h"
|
#include "UIScene.h"
|
||||||
|
|
||||||
|
#include "UIControl_Slider.h"
|
||||||
#include "Minecraft.World/StringHelpers.h"
|
#include "Minecraft.World/StringHelpers.h"
|
||||||
#include "Minecraft.Client/LocalPlayer.h"
|
#include "Minecraft.Client/LocalPlayer.h"
|
||||||
#include "Minecraft.Client/DLCTexturePack.h"
|
#include "Minecraft.Client/DLCTexturePack.h"
|
||||||
|
|
@ -11,6 +13,9 @@
|
||||||
#include "Minecraft.Client/EnderDragonRenderer.h"
|
#include "Minecraft.Client/EnderDragonRenderer.h"
|
||||||
#include "Minecraft.Client/MultiPlayerLocalPlayer.h"
|
#include "Minecraft.Client/MultiPlayerLocalPlayer.h"
|
||||||
#include "UIFontData.h"
|
#include "UIFontData.h"
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
#include "..\..\Windows64\KeyboardMouseInput.h"
|
||||||
|
#endif
|
||||||
#ifdef __PSVITA__
|
#ifdef __PSVITA__
|
||||||
#include <message_dialog.h>
|
#include <message_dialog.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -41,7 +46,7 @@
|
||||||
#elif defined __PSVITA__
|
#elif defined __PSVITA__
|
||||||
#include "PSVita\Iggy\include\iggyperfmon.h"
|
#include "PSVita\Iggy\include\iggyperfmon.h"
|
||||||
#include "PSVita\Iggy\include\iggyperfmon_psp2.h"
|
#include "PSVita\Iggy\include\iggyperfmon_psp2.h"
|
||||||
#elif defined __WINDOWS64
|
#elif defined _WINDOWS64
|
||||||
#include "Windows64\Iggy\include\iggyperfmon.h"
|
#include "Windows64\Iggy\include\iggyperfmon.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -52,6 +57,21 @@ bool UIController::ms_bReloadSkinCSInitialised = false;
|
||||||
|
|
||||||
DWORD UIController::m_dwTrialTimerLimitSecs=DYNAMIC_CONFIG_DEFAULT_TRIAL_TIME;
|
DWORD UIController::m_dwTrialTimerLimitSecs=DYNAMIC_CONFIG_DEFAULT_TRIAL_TIME;
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
static UIControl_Slider *FindSliderById(UIScene *pScene, int sliderId)
|
||||||
|
{
|
||||||
|
vector<UIControl *> *controls = pScene->GetControls();
|
||||||
|
if (!controls) return NULL;
|
||||||
|
for (size_t i = 0; i < controls->size(); ++i)
|
||||||
|
{
|
||||||
|
UIControl *ctrl = (*controls)[i];
|
||||||
|
if (ctrl && ctrl->getControlType() == UIControl::eSlider && ctrl->getId() == sliderId)
|
||||||
|
return (UIControl_Slider *)ctrl;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void RADLINK WarningCallback(void *user_callback_data, Iggy *player, IggyResult code, const char *message)
|
static void RADLINK WarningCallback(void *user_callback_data, Iggy *player, IggyResult code, const char *message)
|
||||||
{
|
{
|
||||||
//enum IggyResult{ IGGY_RESULT_SUCCESS = 0, IGGY_RESULT_Warning_None = 0,
|
//enum IggyResult{ IGGY_RESULT_SUCCESS = 0, IGGY_RESULT_Warning_None = 0,
|
||||||
|
|
@ -216,6 +236,10 @@ UIController::UIController()
|
||||||
m_currentRenderViewport = C4JRender::VIEWPORT_TYPE_FULLSCREEN;
|
m_currentRenderViewport = C4JRender::VIEWPORT_TYPE_FULLSCREEN;
|
||||||
m_bCustomRenderPosition = false;
|
m_bCustomRenderPosition = false;
|
||||||
m_winUserIndex = 0;
|
m_winUserIndex = 0;
|
||||||
|
m_mouseDraggingSliderScene = eUIScene_COUNT;
|
||||||
|
m_mouseDraggingSliderId = -1;
|
||||||
|
m_lastHoverMouseX = -1;
|
||||||
|
m_lastHoverMouseY = -1;
|
||||||
m_accumulatedTicks = 0;
|
m_accumulatedTicks = 0;
|
||||||
m_lastUiSfx = 0;
|
m_lastUiSfx = 0;
|
||||||
|
|
||||||
|
|
@ -761,6 +785,168 @@ void UIController::tickInput()
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
|
||||||
|
{
|
||||||
|
UIScene *pScene = NULL;
|
||||||
|
for (int grp = 0; grp < eUIGroup_COUNT && !pScene; ++grp)
|
||||||
|
{
|
||||||
|
pScene = m_groups[grp]->GetTopScene(eUILayer_Debug);
|
||||||
|
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Tooltips);
|
||||||
|
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Error);
|
||||||
|
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Alert);
|
||||||
|
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Popup);
|
||||||
|
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Fullscreen);
|
||||||
|
if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Scene);
|
||||||
|
}
|
||||||
|
if (pScene && pScene->getMovie())
|
||||||
|
{
|
||||||
|
Iggy *movie = pScene->getMovie();
|
||||||
|
int rawMouseX = g_KBMInput.GetMouseX();
|
||||||
|
int rawMouseY = g_KBMInput.GetMouseY();
|
||||||
|
F32 mouseX = (F32)rawMouseX;
|
||||||
|
F32 mouseY = (F32)rawMouseY;
|
||||||
|
|
||||||
|
extern HWND g_hWnd;
|
||||||
|
if (g_hWnd)
|
||||||
|
{
|
||||||
|
RECT rc;
|
||||||
|
GetClientRect(g_hWnd, &rc);
|
||||||
|
int winW = rc.right - rc.left;
|
||||||
|
int winH = rc.bottom - rc.top;
|
||||||
|
if (winW > 0 && winH > 0)
|
||||||
|
{
|
||||||
|
mouseX = mouseX * (m_fScreenWidth / (F32)winW);
|
||||||
|
mouseY = mouseY * (m_fScreenHeight / (F32)winH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only update hover focus when the mouse has actually moved,
|
||||||
|
// so that mouse-wheel scrolling can change list selection
|
||||||
|
// without the hover immediately snapping focus back.
|
||||||
|
bool mouseMoved = (rawMouseX != m_lastHoverMouseX || rawMouseY != m_lastHoverMouseY);
|
||||||
|
m_lastHoverMouseX = rawMouseX;
|
||||||
|
m_lastHoverMouseY = rawMouseY;
|
||||||
|
|
||||||
|
if (mouseMoved)
|
||||||
|
{
|
||||||
|
IggyFocusHandle currentFocus = IGGY_FOCUS_NULL;
|
||||||
|
IggyFocusableObject focusables[64];
|
||||||
|
S32 numFocusables = 0;
|
||||||
|
IggyPlayerGetFocusableObjects(movie, ¤tFocus, focusables, 64, &numFocusables);
|
||||||
|
|
||||||
|
if (numFocusables > 0 && numFocusables <= 64)
|
||||||
|
{
|
||||||
|
IggyFocusHandle hitObject = IGGY_FOCUS_NULL;
|
||||||
|
for (S32 i = 0; i < numFocusables; ++i)
|
||||||
|
{
|
||||||
|
if (mouseX >= focusables[i].x0 && mouseX <= focusables[i].x1 &&
|
||||||
|
mouseY >= focusables[i].y0 && mouseY <= focusables[i].y1)
|
||||||
|
{
|
||||||
|
hitObject = focusables[i].object;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hitObject != currentFocus)
|
||||||
|
{
|
||||||
|
IggyPlayerSetFocusRS(movie, hitObject, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert mouse to scene/movie coordinates for slider hit testing
|
||||||
|
F32 sceneMouseX = mouseX;
|
||||||
|
F32 sceneMouseY = mouseY;
|
||||||
|
{
|
||||||
|
S32 displayWidth = 0, displayHeight = 0;
|
||||||
|
pScene->GetParentLayer()->getRenderDimensions(displayWidth, displayHeight);
|
||||||
|
if (displayWidth > 0 && displayHeight > 0)
|
||||||
|
{
|
||||||
|
sceneMouseX = mouseX * ((F32)pScene->getRenderWidth() / (F32)displayWidth);
|
||||||
|
sceneMouseY = mouseY * ((F32)pScene->getRenderHeight() / (F32)displayHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get main panel offset (controls are positioned relative to it)
|
||||||
|
S32 panelOffsetX = 0, panelOffsetY = 0;
|
||||||
|
UIControl *pMainPanel = pScene->GetMainPanel();
|
||||||
|
if (pMainPanel)
|
||||||
|
{
|
||||||
|
pMainPanel->UpdateControl();
|
||||||
|
panelOffsetX = pMainPanel->getXPos();
|
||||||
|
panelOffsetY = pMainPanel->getYPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool leftPressed = g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT);
|
||||||
|
bool leftDown = leftPressed || g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT);
|
||||||
|
|
||||||
|
if (m_mouseDraggingSliderScene != eUIScene_COUNT && m_mouseDraggingSliderScene != pScene->getSceneType())
|
||||||
|
{
|
||||||
|
m_mouseDraggingSliderScene = eUIScene_COUNT;
|
||||||
|
m_mouseDraggingSliderId = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leftPressed)
|
||||||
|
{
|
||||||
|
vector<UIControl *> *controls = pScene->GetControls();
|
||||||
|
if (controls)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < controls->size(); ++i)
|
||||||
|
{
|
||||||
|
UIControl *ctrl = (*controls)[i];
|
||||||
|
if (!ctrl || ctrl->getControlType() != UIControl::eSlider || !ctrl->getVisible())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
UIControl_Slider *pSlider = (UIControl_Slider *)ctrl;
|
||||||
|
pSlider->UpdateControl();
|
||||||
|
S32 cx = pSlider->getXPos() + panelOffsetX;
|
||||||
|
S32 cy = pSlider->getYPos() + panelOffsetY;
|
||||||
|
S32 cw = pSlider->GetRealWidth();
|
||||||
|
S32 ch = pSlider->getHeight();
|
||||||
|
if (cw <= 0 || ch <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (sceneMouseX >= cx && sceneMouseX <= cx + cw && sceneMouseY >= cy && sceneMouseY <= cy + ch)
|
||||||
|
{
|
||||||
|
m_mouseDraggingSliderScene = pScene->getSceneType();
|
||||||
|
m_mouseDraggingSliderId = pSlider->getId();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leftDown && m_mouseDraggingSliderScene == pScene->getSceneType() && m_mouseDraggingSliderId >= 0)
|
||||||
|
{
|
||||||
|
UIControl_Slider *pSlider = FindSliderById(pScene, m_mouseDraggingSliderId);
|
||||||
|
if (pSlider && pSlider->getVisible())
|
||||||
|
{
|
||||||
|
pSlider->UpdateControl();
|
||||||
|
S32 sliderX = pSlider->getXPos() + panelOffsetX;
|
||||||
|
S32 sliderWidth = pSlider->GetRealWidth();
|
||||||
|
if (sliderWidth > 0)
|
||||||
|
{
|
||||||
|
float fNewSliderPos = (sceneMouseX - (float)sliderX) / (float)sliderWidth;
|
||||||
|
if (fNewSliderPos < 0.0f) fNewSliderPos = 0.0f;
|
||||||
|
if (fNewSliderPos > 1.0f) fNewSliderPos = 1.0f;
|
||||||
|
pSlider->SetSliderTouchPos(fNewSliderPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_mouseDraggingSliderScene = eUIScene_COUNT;
|
||||||
|
m_mouseDraggingSliderId = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!leftDown)
|
||||||
|
{
|
||||||
|
m_mouseDraggingSliderScene = eUIScene_COUNT;
|
||||||
|
m_mouseDraggingSliderId = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
handleInput();
|
handleInput();
|
||||||
++m_accumulatedTicks;
|
++m_accumulatedTicks;
|
||||||
}
|
}
|
||||||
|
|
@ -995,27 +1181,59 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
|
||||||
released = InputManager.ButtonReleased(iPad,key); // Toggle
|
released = InputManager.ButtonReleased(iPad,key); // Toggle
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
// Keyboard menu input for player 0
|
|
||||||
if (iPad == 0)
|
if (iPad == 0)
|
||||||
{
|
{
|
||||||
bool kbDown = false, kbPressed = false, kbReleased = false;
|
int vk = 0;
|
||||||
switch(key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case ACTION_MENU_UP: kbDown = KMInput.IsKeyDown(VK_UP); kbPressed = KMInput.IsKeyPressed(VK_UP); kbReleased = KMInput.IsKeyReleased(VK_UP); break;
|
case ACTION_MENU_OK: case ACTION_MENU_A: vk = VK_RETURN; break;
|
||||||
case ACTION_MENU_DOWN: kbDown = KMInput.IsKeyDown(VK_DOWN); kbPressed = KMInput.IsKeyPressed(VK_DOWN); kbReleased = KMInput.IsKeyReleased(VK_DOWN); break;
|
case ACTION_MENU_CANCEL: case ACTION_MENU_B: vk = VK_ESCAPE; break;
|
||||||
case ACTION_MENU_LEFT: kbDown = KMInput.IsKeyDown(VK_LEFT); kbPressed = KMInput.IsKeyPressed(VK_LEFT); kbReleased = KMInput.IsKeyReleased(VK_LEFT); break;
|
case ACTION_MENU_UP: vk = VK_UP; break;
|
||||||
case ACTION_MENU_RIGHT: kbDown = KMInput.IsKeyDown(VK_RIGHT); kbPressed = KMInput.IsKeyPressed(VK_RIGHT); kbReleased = KMInput.IsKeyReleased(VK_RIGHT); break;
|
case ACTION_MENU_DOWN: vk = VK_DOWN; break;
|
||||||
case ACTION_MENU_OK: kbDown = KMInput.IsKeyDown(VK_RETURN); kbPressed = KMInput.IsKeyPressed(VK_RETURN); kbReleased = KMInput.IsKeyReleased(VK_RETURN); break;
|
case ACTION_MENU_LEFT: vk = VK_LEFT; break;
|
||||||
case ACTION_MENU_A: kbDown = KMInput.IsKeyDown(VK_RETURN); kbPressed = KMInput.IsKeyPressed(VK_RETURN); kbReleased = KMInput.IsKeyReleased(VK_RETURN); break;
|
case ACTION_MENU_RIGHT: vk = VK_RIGHT; break;
|
||||||
case ACTION_MENU_CANCEL: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break;
|
case ACTION_MENU_X: vk = 'R'; break;
|
||||||
case ACTION_MENU_B: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break;
|
case ACTION_MENU_Y: vk = VK_TAB; break;
|
||||||
case ACTION_MENU_PAUSEMENU: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break;
|
case ACTION_MENU_LEFT_SCROLL: vk = 'Q'; break;
|
||||||
case ACTION_MENU_LEFT_SCROLL: kbDown = KMInput.IsKeyDown('Q'); kbPressed = KMInput.IsKeyPressed('Q'); kbReleased = KMInput.IsKeyReleased('Q'); break;
|
case ACTION_MENU_RIGHT_SCROLL: vk = 'E'; break;
|
||||||
case ACTION_MENU_RIGHT_SCROLL: kbDown = KMInput.IsKeyDown('E'); kbPressed = KMInput.IsKeyPressed('E'); kbReleased = KMInput.IsKeyReleased('E'); break;
|
case ACTION_MENU_PAGEUP: vk = VK_PRIOR; break;
|
||||||
|
case ACTION_MENU_PAGEDOWN: vk = VK_NEXT; break;
|
||||||
|
}
|
||||||
|
if (vk != 0)
|
||||||
|
{
|
||||||
|
if (g_KBMInput.IsKeyPressed(vk)) { pressed = true; down = true; }
|
||||||
|
if (g_KBMInput.IsKeyReleased(vk)) { released = true; down = false; }
|
||||||
|
if (!pressed && !released && g_KBMInput.IsKeyDown(vk)) { down = true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key == ACTION_MENU_OK || key == ACTION_MENU_A) && !g_KBMInput.IsMouseGrabbed())
|
||||||
|
{
|
||||||
|
if (m_mouseDraggingSliderId < 0)
|
||||||
|
{
|
||||||
|
if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT)) { pressed = true; down = true; }
|
||||||
|
if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT)) { released = true; down = false; }
|
||||||
|
if (!pressed && !released && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT)) { down = true; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll wheel for list scrolling — only consume the wheel value when the
|
||||||
|
// action key actually matches, so the other direction isn't lost.
|
||||||
|
if (!g_KBMInput.IsMouseGrabbed() && (key == ACTION_MENU_OTHER_STICK_UP || key == ACTION_MENU_OTHER_STICK_DOWN))
|
||||||
|
{
|
||||||
|
int wheel = g_KBMInput.PeekMouseWheel();
|
||||||
|
if (key == ACTION_MENU_OTHER_STICK_UP && wheel > 0)
|
||||||
|
{
|
||||||
|
g_KBMInput.ConsumeMouseWheel();
|
||||||
|
pressed = true;
|
||||||
|
down = true;
|
||||||
|
}
|
||||||
|
else if (key == ACTION_MENU_OTHER_STICK_DOWN && wheel < 0)
|
||||||
|
{
|
||||||
|
g_KBMInput.ConsumeMouseWheel();
|
||||||
|
pressed = true;
|
||||||
|
down = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pressed = pressed || kbPressed;
|
|
||||||
released = released || kbReleased;
|
|
||||||
down = down || kbDown;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -1444,7 +1662,7 @@ GDrawTexture * RADLINK UIController::TextureSubstitutionCreateCallback ( void *
|
||||||
|
|
||||||
// 4J Stu - All our flash controls that allow replacing textures use a special 64x64 symbol
|
// 4J Stu - All our flash controls that allow replacing textures use a special 64x64 symbol
|
||||||
// Force this size here so that our images don't get scaled wildly
|
// Force this size here so that our images don't get scaled wildly
|
||||||
#if (defined __ORBIS__ || defined _DURANGO )
|
#if (defined __ORBIS__ || defined _DURANGO || defined _WINDOWS64 )
|
||||||
*width = 96;
|
*width = 96;
|
||||||
*height = 96;
|
*height = 96;
|
||||||
#else
|
#else
|
||||||
|
|
@ -3137,4 +3355,4 @@ void UIController::SendTouchInput(unsigned int iPad, unsigned int key, bool bPre
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,10 @@ private:
|
||||||
vector<QueuedMessageBoxData *> m_queuedMessageBoxData;
|
vector<QueuedMessageBoxData *> m_queuedMessageBoxData;
|
||||||
|
|
||||||
unsigned int m_winUserIndex;
|
unsigned int m_winUserIndex;
|
||||||
|
EUIScene m_mouseDraggingSliderScene;
|
||||||
|
int m_mouseDraggingSliderId;
|
||||||
|
int m_lastHoverMouseX;
|
||||||
|
int m_lastHoverMouseY;
|
||||||
//bool m_bSysUIShowing;
|
//bool m_bSysUIShowing;
|
||||||
bool m_bSystemUIShowing;
|
bool m_bSystemUIShowing;
|
||||||
C4JThread *m_reloadSkinThread;
|
C4JThread *m_reloadSkinThread;
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,7 @@ private:
|
||||||
public:
|
public:
|
||||||
UIGroup(EUIGroup group, int iPad);
|
UIGroup(EUIGroup group, int iPad);
|
||||||
|
|
||||||
#ifdef __PSVITA__
|
|
||||||
EUIGroup GetGroup() {return m_group;}
|
EUIGroup GetGroup() {return m_group;}
|
||||||
#endif
|
|
||||||
UIComponent_Tooltips *getTooltips() { return m_tooltips; }
|
UIComponent_Tooltips *getTooltips() { return m_tooltips; }
|
||||||
UIComponent_TutorialPopup *getTutorialPopup() { return m_tutorialPopup; }
|
UIComponent_TutorialPopup *getTutorialPopup() { return m_tutorialPopup; }
|
||||||
UIScene_HUD *getHUD() { return m_hud; }
|
UIScene_HUD *getHUD() { return m_hud; }
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,10 @@ public:
|
||||||
int getRenderHeight() { return m_renderHeight; }
|
int getRenderHeight() { return m_renderHeight; }
|
||||||
|
|
||||||
#ifdef __PSVITA__
|
#ifdef __PSVITA__
|
||||||
UILayer *GetParentLayer() {return m_parentLayer;}
|
|
||||||
EUIGroup GetParentLayerGroup() {return m_parentLayer->m_parentGroup->GetGroup();}
|
EUIGroup GetParentLayerGroup() {return m_parentLayer->m_parentGroup->GetGroup();}
|
||||||
|
#endif
|
||||||
|
#if defined(__PSVITA__) || defined(_WINDOWS64)
|
||||||
|
UILayer *GetParentLayer() {return m_parentLayer;}
|
||||||
vector<UIControl *> *GetControls() {return &m_controls;}
|
vector<UIControl *> *GetControls() {return &m_controls;}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,6 @@ UIScene_AbstractContainerMenu::UIScene_AbstractContainerMenu(int iPad, UILayer *
|
||||||
ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,true);
|
ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,true);
|
||||||
|
|
||||||
m_bIgnoreInput=false;
|
m_bIgnoreInput=false;
|
||||||
#ifdef _WINDOWS64
|
|
||||||
m_bMouseDragSlider=false;
|
|
||||||
m_bHasMousePosition = false;
|
|
||||||
m_lastMouseX = 0;
|
|
||||||
m_lastMouseY = 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UIScene_AbstractContainerMenu::~UIScene_AbstractContainerMenu()
|
UIScene_AbstractContainerMenu::~UIScene_AbstractContainerMenu()
|
||||||
|
|
@ -50,6 +44,16 @@ UIScene_AbstractContainerMenu::~UIScene_AbstractContainerMenu()
|
||||||
void UIScene_AbstractContainerMenu::handleDestroy()
|
void UIScene_AbstractContainerMenu::handleDestroy()
|
||||||
{
|
{
|
||||||
app.DebugPrintf("UIScene_AbstractContainerMenu::handleDestroy\n");
|
app.DebugPrintf("UIScene_AbstractContainerMenu::handleDestroy\n");
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
g_savedInventoryCursorPos.x = m_pointerPos.x;
|
||||||
|
g_savedInventoryCursorPos.y = m_pointerPos.y;
|
||||||
|
g_savedInventoryCursorPos.hasSavedPos = true;
|
||||||
|
|
||||||
|
g_KBMInput.SetScreenCursorHidden(false);
|
||||||
|
g_KBMInput.SetCursorHiddenForUI(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
Minecraft *pMinecraft = Minecraft::GetInstance();
|
||||||
if( pMinecraft->localgameModes[m_iPad] != NULL )
|
if( pMinecraft->localgameModes[m_iPad] != NULL )
|
||||||
{
|
{
|
||||||
|
|
@ -85,6 +89,10 @@ void UIScene_AbstractContainerMenu::InitDataAssociations(int iPad, AbstractConta
|
||||||
|
|
||||||
void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex)
|
void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex)
|
||||||
{
|
{
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
g_KBMInput.SetScreenCursorHidden(true);
|
||||||
|
g_KBMInput.SetCursorHiddenForUI(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
m_labelInventory.init( app.GetString(IDS_INVENTORY) );
|
m_labelInventory.init( app.GetString(IDS_INVENTORY) );
|
||||||
|
|
||||||
|
|
@ -169,6 +177,19 @@ void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex)
|
||||||
//m_pointerControl->SetPosition( &vPointerPos );
|
//m_pointerControl->SetPosition( &vPointerPos );
|
||||||
m_pointerPos = vPointerPos;
|
m_pointerPos = vPointerPos;
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (g_savedInventoryCursorPos.hasSavedPos)
|
||||||
|
{
|
||||||
|
m_pointerPos.x = g_savedInventoryCursorPos.x;
|
||||||
|
m_pointerPos.y = g_savedInventoryCursorPos.y;
|
||||||
|
|
||||||
|
if (m_pointerPos.x < m_fPointerMinX) m_pointerPos.x = m_fPointerMinX;
|
||||||
|
if (m_pointerPos.x > m_fPointerMaxX) m_pointerPos.x = m_fPointerMaxX;
|
||||||
|
if (m_pointerPos.y < m_fPointerMinY) m_pointerPos.y = m_fPointerMinY;
|
||||||
|
if (m_pointerPos.y > m_fPointerMaxY) m_pointerPos.y = m_fPointerMaxY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
IggyEvent mouseEvent;
|
IggyEvent mouseEvent;
|
||||||
S32 width, height;
|
S32 width, height;
|
||||||
m_parentLayer->getRenderDimensions(width, height);
|
m_parentLayer->getRenderDimensions(width, height);
|
||||||
|
|
@ -191,134 +212,15 @@ void UIScene_AbstractContainerMenu::tick()
|
||||||
{
|
{
|
||||||
UIScene::tick();
|
UIScene::tick();
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
|
||||||
bool mouseActive = (m_iPad == 0 && !KMInput.IsCaptured());
|
|
||||||
bool drivePointerFromMouse = false;
|
|
||||||
float rawMouseMovieX = 0, rawMouseMovieY = 0;
|
|
||||||
int scrollDelta = 0;
|
|
||||||
// Map Windows mouse position to the virtual pointer in movie coordinates
|
|
||||||
if (mouseActive)
|
|
||||||
{
|
|
||||||
RECT clientRect;
|
|
||||||
GetClientRect(KMInput.GetHWnd(), &clientRect);
|
|
||||||
int clientWidth = clientRect.right;
|
|
||||||
int clientHeight = clientRect.bottom;
|
|
||||||
if (clientWidth > 0 && clientHeight > 0)
|
|
||||||
{
|
|
||||||
int mouseX = KMInput.GetMouseX();
|
|
||||||
int mouseY = KMInput.GetMouseY();
|
|
||||||
bool mouseMoved = !m_bHasMousePosition || mouseX != m_lastMouseX || mouseY != m_lastMouseY;
|
|
||||||
|
|
||||||
m_bHasMousePosition = true;
|
|
||||||
m_lastMouseX = mouseX;
|
|
||||||
m_lastMouseY = mouseY;
|
|
||||||
scrollDelta = KMInput.ConsumeScrollDelta();
|
|
||||||
|
|
||||||
// Convert mouse position to movie coordinates using the movie/client ratio
|
|
||||||
float mx = (float)mouseX * ((float)m_movieWidth / (float)clientWidth);
|
|
||||||
float my = (float)mouseY * ((float)m_movieHeight / (float)clientHeight);
|
|
||||||
|
|
||||||
rawMouseMovieX = mx;
|
|
||||||
rawMouseMovieY = my;
|
|
||||||
|
|
||||||
// Once the mouse has taken over the container cursor, keep following the OS cursor
|
|
||||||
// until explicit controller input takes ownership back.
|
|
||||||
drivePointerFromMouse = m_bPointerDrivenByMouse || mouseMoved || KMInput.IsMouseDown(0) || KMInput.IsMouseDown(1) || KMInput.IsMouseDown(2) || scrollDelta != 0;
|
|
||||||
if (drivePointerFromMouse)
|
|
||||||
{
|
|
||||||
m_bPointerDrivenByMouse = true;
|
|
||||||
m_eCurrTapState = eTapStateNoInput;
|
|
||||||
m_pointerPos.x = mx;
|
|
||||||
m_pointerPos.y = my;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
onMouseTick();
|
onMouseTick();
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
|
||||||
// Dispatch mouse clicks AFTER onMouseTick() has updated m_eCurrSection from the new pointer position
|
|
||||||
if (mouseActive)
|
|
||||||
{
|
|
||||||
if (KMInput.ConsumeMousePress(0))
|
|
||||||
{
|
|
||||||
if (m_eCurrSection == eSectionInventoryCreativeSlider)
|
|
||||||
{
|
|
||||||
// Scrollbar click: use raw mouse position (onMouseTick may have snapped m_pointerPos)
|
|
||||||
m_bMouseDragSlider = true;
|
|
||||||
m_pointerPos.x = rawMouseMovieX;
|
|
||||||
m_pointerPos.y = rawMouseMovieY;
|
|
||||||
handleOtherClicked(m_iPad, eSectionInventoryCreativeSlider, 0, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
handleKeyDown(m_iPad, ACTION_MENU_A, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (m_bMouseDragSlider && KMInput.IsMouseDown(0))
|
|
||||||
{
|
|
||||||
// Continue scrollbar drag: update scroll position from current mouse Y
|
|
||||||
m_pointerPos.x = rawMouseMovieX;
|
|
||||||
m_pointerPos.y = rawMouseMovieY;
|
|
||||||
handleOtherClicked(m_iPad, eSectionInventoryCreativeSlider, 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!KMInput.IsMouseDown(0))
|
|
||||||
m_bMouseDragSlider = false;
|
|
||||||
|
|
||||||
if (KMInput.ConsumeMousePress(1))
|
|
||||||
{
|
|
||||||
handleKeyDown(m_iPad, ACTION_MENU_X, false);
|
|
||||||
}
|
|
||||||
if (KMInput.ConsumeMousePress(2))
|
|
||||||
{
|
|
||||||
handleKeyDown(m_iPad, ACTION_MENU_Y, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mouse scroll wheel for page scrolling
|
|
||||||
if (scrollDelta > 0)
|
|
||||||
{
|
|
||||||
handleKeyDown(m_iPad, ACTION_MENU_OTHER_STICK_UP, false);
|
|
||||||
}
|
|
||||||
else if (scrollDelta < 0)
|
|
||||||
{
|
|
||||||
handleKeyDown(m_iPad, ACTION_MENU_OTHER_STICK_DOWN, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ESC to close — must be last since it may destroy this scene
|
|
||||||
if (KMInput.ConsumeKeyPress(VK_ESCAPE))
|
|
||||||
{
|
|
||||||
handleKeyDown(m_iPad, ACTION_MENU_B, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IggyEvent mouseEvent;
|
IggyEvent mouseEvent;
|
||||||
S32 width, height;
|
S32 width, height;
|
||||||
m_parentLayer->getRenderDimensions(width, height);
|
m_parentLayer->getRenderDimensions(width, height);
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
S32 x = (S32)(m_pointerPos.x * ((float)width / m_movieWidth));
|
||||||
S32 x, y;
|
S32 y = (S32)(m_pointerPos.y * ((float)height / m_movieHeight));
|
||||||
if (mouseActive && m_bPointerDrivenByMouse)
|
|
||||||
{
|
|
||||||
// Send raw mouse position directly as Iggy event to avoid coordinate round-trip errors
|
|
||||||
// Scale mouse client coords to the Iggy display space (which was set to getRenderDimensions())
|
|
||||||
RECT clientRect;
|
|
||||||
GetClientRect(KMInput.GetHWnd(), &clientRect);
|
|
||||||
x = (S32)((float)KMInput.GetMouseX() * ((float)width / (float)clientRect.right));
|
|
||||||
y = (S32)((float)KMInput.GetMouseY() * ((float)height / (float)clientRect.bottom));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = (S32)(m_pointerPos.x * ((float)width / m_movieWidth));
|
|
||||||
y = (S32)(m_pointerPos.y * ((float)height / m_movieHeight));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
S32 x = m_pointerPos.x*((float)width/m_movieWidth);
|
|
||||||
S32 y = m_pointerPos.y*((float)height/m_movieHeight);
|
|
||||||
#endif
|
|
||||||
IggyMakeEventMouseMove( &mouseEvent, x, y);
|
IggyMakeEventMouseMove( &mouseEvent, x, y);
|
||||||
|
|
||||||
// 4J Stu - This seems to be broken on Durango, so do it ourself
|
// 4J Stu - This seems to be broken on Durango, so do it ourself
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,6 @@ class UIScene_AbstractContainerMenu : public UIScene, public virtual IUIScene_Ab
|
||||||
private:
|
private:
|
||||||
ESceneSection m_focusSection;
|
ESceneSection m_focusSection;
|
||||||
bool m_bIgnoreInput;
|
bool m_bIgnoreInput;
|
||||||
#ifdef _WINDOWS64
|
|
||||||
bool m_bMouseDragSlider;
|
|
||||||
bool m_bHasMousePosition;
|
|
||||||
int m_lastMouseX;
|
|
||||||
int m_lastMouseY;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UIControl m_controlMainPanel;
|
UIControl m_controlMainPanel;
|
||||||
|
|
@ -42,6 +36,8 @@ public:
|
||||||
virtual void handleDestroy();
|
virtual void handleDestroy();
|
||||||
|
|
||||||
int getPad() { return m_iPad; }
|
int getPad() { return m_iPad; }
|
||||||
|
int getMovieWidth() { return m_movieWidth; }
|
||||||
|
int getMovieHeight() { return m_movieHeight; }
|
||||||
bool getIgnoreInput() { return m_bIgnoreInput; }
|
bool getIgnoreInput() { return m_bIgnoreInput; }
|
||||||
void setIgnoreInput(bool bVal) { m_bIgnoreInput=bVal; }
|
void setIgnoreInput(bool bVal) { m_bIgnoreInput=bVal; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1085,6 +1085,7 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
|
||||||
__int64 seedValue = 0;
|
__int64 seedValue = 0;
|
||||||
|
|
||||||
NetworkGameInitData *param = new NetworkGameInitData();
|
NetworkGameInitData *param = new NetworkGameInitData();
|
||||||
|
param->levelName = wWorldName;
|
||||||
|
|
||||||
if (wSeed.length() != 0)
|
if (wSeed.length() != 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,17 +39,37 @@ UIScene_DebugOverlay::UIScene_DebugOverlay(int iPad, void *initData, UILayer *pa
|
||||||
m_buttonSetNight.init(L"Set Night", eControl_SetNight);
|
m_buttonSetNight.init(L"Set Night", eControl_SetNight);
|
||||||
|
|
||||||
m_buttonListItems.init(eControl_Items);
|
m_buttonListItems.init(eControl_Items);
|
||||||
|
|
||||||
|
// Sort items alphabetically
|
||||||
|
std::vector<std::pair<std::wstring, unsigned int>> sortedItems;
|
||||||
|
for (size_t i = 0; i < Item::items.length; ++i)
|
||||||
|
{
|
||||||
|
if (Item::items[i] != NULL)
|
||||||
|
{
|
||||||
|
sortedItems.emplace_back(std::wstring(app.GetString(Item::items[i]->getDescriptionId())), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 1; i < sortedItems.size(); ++i)
|
||||||
|
{
|
||||||
|
auto key = sortedItems[i];
|
||||||
|
int j = i - 1;
|
||||||
|
while (j >= 0 && sortedItems[j].first > key.first)
|
||||||
|
{
|
||||||
|
sortedItems[j + 1] = sortedItems[j];
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
sortedItems[j + 1] = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the list in sorted order
|
||||||
int listId = 0;
|
int listId = 0;
|
||||||
for(unsigned int i = 0; i < Item::items.length; ++i)
|
for (const auto& entry : sortedItems)
|
||||||
{
|
{
|
||||||
if(Item::items[i] != NULL)
|
m_itemIds.push_back(entry.second);
|
||||||
{
|
m_buttonListItems.addItem(entry.first.c_str(), listId);
|
||||||
m_itemIds.push_back(i);
|
++listId;
|
||||||
m_buttonListItems.addItem(app.GetString(Item::items[i]->getDescriptionId()), listId);
|
}
|
||||||
++listId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_buttonListEnchantments.init(eControl_Enchantments);
|
m_buttonListEnchantments.init(eControl_Enchantments);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,7 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
|
||||||
#endif
|
#endif
|
||||||
m_bShowTimer = true;
|
m_bShowTimer = true;
|
||||||
}
|
}
|
||||||
#if defined(_DURANGO)
|
#if defined(_DURANGO)
|
||||||
m_labelGameName.init(params->saveDetails->UTF16SaveName);
|
m_labelGameName.init(params->saveDetails->UTF16SaveName);
|
||||||
#else
|
#else
|
||||||
wchar_t wSaveName[128];
|
wchar_t wSaveName[128];
|
||||||
|
|
@ -246,6 +246,16 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
|
||||||
mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, strlen(params->saveDetails->UTF8SaveName)+1); // plus null
|
mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, strlen(params->saveDetails->UTF8SaveName)+1); // plus null
|
||||||
m_labelGameName.init(wSaveName);
|
m_labelGameName.init(wSaveName);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (params->saveDetails != NULL && params->saveDetails->UTF8SaveName[0] != '\0')
|
||||||
|
{
|
||||||
|
wchar_t wSaveName[128];
|
||||||
|
ZeroMemory(wSaveName, sizeof(wSaveName));
|
||||||
|
mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, 127);
|
||||||
|
m_levelName = wstring(wSaveName);
|
||||||
|
m_labelGameName.init(m_levelName);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1574,6 +1584,7 @@ void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocal
|
||||||
param->saveData = NULL;
|
param->saveData = NULL;
|
||||||
param->levelGen = pClass->m_levelGen;
|
param->levelGen = pClass->m_levelGen;
|
||||||
param->texturePackId = pClass->m_MoreOptionsParams.dwTexturePack;
|
param->texturePackId = pClass->m_MoreOptionsParams.dwTexturePack;
|
||||||
|
param->levelName = pClass->m_levelName;
|
||||||
|
|
||||||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
Minecraft *pMinecraft = Minecraft::GetInstance();
|
||||||
pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack);
|
pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack);
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ private:
|
||||||
bool m_bIsCorrupt;
|
bool m_bIsCorrupt;
|
||||||
bool m_bThumbnailGetFailed;
|
bool m_bThumbnailGetFailed;
|
||||||
__int64 m_seed;
|
__int64 m_seed;
|
||||||
|
wstring m_levelName;
|
||||||
|
|
||||||
#ifdef __PS3__
|
#ifdef __PS3__
|
||||||
std::vector<SonyCommerce::ProductInfo>*m_pvProductInfo;
|
std::vector<SonyCommerce::ProductInfo>*m_pvProductInfo;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,98 @@
|
||||||
#include "message_dialog.h"
|
#include "message_dialog.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
#include "..\..\..\Minecraft.World\NbtIo.h"
|
||||||
|
#include "..\..\..\Minecraft.World\compression.h"
|
||||||
|
|
||||||
|
static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
|
||||||
|
{
|
||||||
|
HANDLE hFile = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE) return L"";
|
||||||
|
|
||||||
|
DWORD fileSize = GetFileSize(hFile, NULL);
|
||||||
|
if (fileSize < 12 || fileSize == INVALID_FILE_SIZE) { CloseHandle(hFile); return L""; }
|
||||||
|
|
||||||
|
unsigned char *rawData = new unsigned char[fileSize];
|
||||||
|
DWORD bytesRead = 0;
|
||||||
|
if (!ReadFile(hFile, rawData, fileSize, &bytesRead, NULL) || bytesRead != fileSize)
|
||||||
|
{
|
||||||
|
CloseHandle(hFile);
|
||||||
|
delete[] rawData;
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
CloseHandle(hFile);
|
||||||
|
|
||||||
|
unsigned char *saveData = NULL;
|
||||||
|
unsigned int saveSize = 0;
|
||||||
|
bool freeSaveData = false;
|
||||||
|
|
||||||
|
if (*(unsigned int*)rawData == 0)
|
||||||
|
{
|
||||||
|
// Compressed format: bytes 0-3=0, bytes 4-7=decompressed size, bytes 8+=compressed data
|
||||||
|
unsigned int decompSize = *(unsigned int*)(rawData + 4);
|
||||||
|
if (decompSize == 0 || decompSize > 128 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
delete[] rawData;
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
saveData = new unsigned char[decompSize];
|
||||||
|
Compression::getCompression()->Decompress(saveData, &decompSize, rawData + 8, fileSize - 8);
|
||||||
|
saveSize = decompSize;
|
||||||
|
freeSaveData = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
saveData = rawData;
|
||||||
|
saveSize = fileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
wstring result = L"";
|
||||||
|
if (saveSize >= 12)
|
||||||
|
{
|
||||||
|
unsigned int headerOffset = *(unsigned int*)saveData;
|
||||||
|
unsigned int numEntries = *(unsigned int*)(saveData + 4);
|
||||||
|
const unsigned int entrySize = sizeof(FileEntrySaveData);
|
||||||
|
|
||||||
|
if (headerOffset < saveSize && numEntries > 0 && numEntries < 10000 &&
|
||||||
|
headerOffset + numEntries * entrySize <= saveSize)
|
||||||
|
{
|
||||||
|
FileEntrySaveData *table = (FileEntrySaveData *)(saveData + headerOffset);
|
||||||
|
for (unsigned int i = 0; i < numEntries; i++)
|
||||||
|
{
|
||||||
|
if (wcscmp(table[i].filename, L"level.dat") == 0)
|
||||||
|
{
|
||||||
|
unsigned int off = table[i].startOffset;
|
||||||
|
unsigned int len = table[i].length;
|
||||||
|
if (off >= 12 && off + len <= saveSize && len > 0 && len < 4 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
byteArray ba;
|
||||||
|
ba.data = (byte*)(saveData + off);
|
||||||
|
ba.length = len;
|
||||||
|
CompoundTag *root = NbtIo::decompress(ba);
|
||||||
|
if (root != NULL)
|
||||||
|
{
|
||||||
|
CompoundTag *dataTag = root->getCompound(L"Data");
|
||||||
|
if (dataTag != NULL)
|
||||||
|
result = dataTag->getString(L"LevelName");
|
||||||
|
delete root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (freeSaveData) delete[] saveData;
|
||||||
|
delete[] rawData;
|
||||||
|
// "world" is the engine default — it means no real name was ever set, so
|
||||||
|
// return empty to let the caller fall back to the save filename (timestamp).
|
||||||
|
if (result == L"world") result = L"";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
|
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
|
||||||
unsigned long UIScene_LoadOrJoinMenu::m_ulFileSize=0L;
|
unsigned long UIScene_LoadOrJoinMenu::m_ulFileSize=0L;
|
||||||
|
|
@ -159,7 +251,7 @@ UIScene_LoadOrJoinMenu::UIScene_LoadOrJoinMenu(int iPad, void *initData, UILayer
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) || defined(_DURANGO)
|
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) || defined(_DURANGO) || defined(_WINDOWS64)
|
||||||
// Always clear the saves when we enter this menu
|
// Always clear the saves when we enter this menu
|
||||||
StorageManager.ClearSavesInfo();
|
StorageManager.ClearSavesInfo();
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -614,6 +706,22 @@ void UIScene_LoadOrJoinMenu::tick()
|
||||||
m_saveDetails = new SaveListDetails[m_pSaveDetails->iSaveC];
|
m_saveDetails = new SaveListDetails[m_pSaveDetails->iSaveC];
|
||||||
|
|
||||||
m_iSaveDetailsCount = m_pSaveDetails->iSaveC;
|
m_iSaveDetailsCount = m_pSaveDetails->iSaveC;
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
// Build sorted index array (newest-first by filename timestamp YYYYMMDDHHMMSS)
|
||||||
|
int *sortedIdx = new int[m_pSaveDetails->iSaveC];
|
||||||
|
for (int si = 0; si < (int)m_pSaveDetails->iSaveC; ++si) sortedIdx[si] = si;
|
||||||
|
for (int si = 1; si < (int)m_pSaveDetails->iSaveC; ++si)
|
||||||
|
{
|
||||||
|
int key = sortedIdx[si];
|
||||||
|
int sj = si - 1;
|
||||||
|
while (sj >= 0 && strcmp(m_pSaveDetails->SaveInfoA[sortedIdx[sj]].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[key].UTF8SaveFilename) < 0)
|
||||||
|
{
|
||||||
|
sortedIdx[sj + 1] = sortedIdx[sj];
|
||||||
|
--sj;
|
||||||
|
}
|
||||||
|
sortedIdx[sj + 1] = key;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
for(unsigned int i = 0; i < m_pSaveDetails->iSaveC; ++i)
|
for(unsigned int i = 0; i < m_pSaveDetails->iSaveC; ++i)
|
||||||
{
|
{
|
||||||
#if defined(_XBOX_ONE)
|
#if defined(_XBOX_ONE)
|
||||||
|
|
@ -627,14 +735,40 @@ void UIScene_LoadOrJoinMenu::tick()
|
||||||
m_saveDetails[i].saveId = i;
|
m_saveDetails[i].saveId = i;
|
||||||
memcpy(m_saveDetails[i].UTF16SaveName, m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, 128);
|
memcpy(m_saveDetails[i].UTF16SaveName, m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, 128);
|
||||||
memcpy(m_saveDetails[i].UTF16SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF16SaveFilename, MAX_SAVEFILENAME_LENGTH);
|
memcpy(m_saveDetails[i].UTF16SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF16SaveFilename, MAX_SAVEFILENAME_LENGTH);
|
||||||
|
#else
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
{
|
||||||
|
int origIdx = sortedIdx[i];
|
||||||
|
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH];
|
||||||
|
ZeroMemory(wFilename, sizeof(wFilename));
|
||||||
|
mbstowcs(wFilename, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1);
|
||||||
|
wstring filePath = wstring(L"Windows64\\GameHDD\\") + wstring(wFilename) + wstring(L"\\saveData.ms");
|
||||||
|
wstring levelName = ReadLevelNameFromSaveFile(filePath);
|
||||||
|
if (!levelName.empty())
|
||||||
|
{
|
||||||
|
m_buttonListSaves.addItem(levelName, wstring(L""));
|
||||||
|
wcstombs(m_saveDetails[i].UTF8SaveName, levelName.c_str(), 127);
|
||||||
|
m_saveDetails[i].UTF8SaveName[127] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveTitle, L"");
|
||||||
|
memcpy(m_saveDetails[i].UTF8SaveName, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveTitle, 128);
|
||||||
|
}
|
||||||
|
m_saveDetails[i].saveId = origIdx;
|
||||||
|
memcpy(m_saveDetails[i].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, L"");
|
m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, L"");
|
||||||
|
|
||||||
m_saveDetails[i].saveId = i;
|
|
||||||
memcpy(m_saveDetails[i].UTF8SaveName, m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, 128);
|
memcpy(m_saveDetails[i].UTF8SaveName, m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, 128);
|
||||||
|
m_saveDetails[i].saveId = i;
|
||||||
memcpy(m_saveDetails[i].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH);
|
memcpy(m_saveDetails[i].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
delete[] sortedIdx;
|
||||||
|
#endif
|
||||||
m_controlSavesTimer.setVisible( false );
|
m_controlSavesTimer.setVisible( false );
|
||||||
|
|
||||||
// set focus on the first button
|
// set focus on the first button
|
||||||
|
|
@ -650,7 +784,11 @@ void UIScene_LoadOrJoinMenu::tick()
|
||||||
app.DebugPrintf("Requesting the first thumbnail\n");
|
app.DebugPrintf("Requesting the first thumbnail\n");
|
||||||
// set the save to load
|
// set the save to load
|
||||||
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
|
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[m_saveDetails[m_iRequestingThumbnailId].saveId],&LoadSaveDataThumbnailReturned,this);
|
||||||
|
#else
|
||||||
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this);
|
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail)
|
if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail)
|
||||||
{
|
{
|
||||||
|
|
@ -713,7 +851,11 @@ void UIScene_LoadOrJoinMenu::tick()
|
||||||
app.DebugPrintf("Requesting another thumbnail\n");
|
app.DebugPrintf("Requesting another thumbnail\n");
|
||||||
// set the save to load
|
// set the save to load
|
||||||
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
|
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[m_saveDetails[m_iRequestingThumbnailId].saveId],&LoadSaveDataThumbnailReturned,this);
|
||||||
|
#else
|
||||||
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this);
|
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this);
|
||||||
|
#endif
|
||||||
if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail)
|
if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail)
|
||||||
{
|
{
|
||||||
// something went wrong
|
// something went wrong
|
||||||
|
|
@ -1175,6 +1317,14 @@ void UIScene_LoadOrJoinMenu::handleInput(int iPad, int key, bool repeat, bool pr
|
||||||
sendInputToMovie(key, repeat, pressed, released);
|
sendInputToMovie(key, repeat, pressed, released);
|
||||||
handled = true;
|
handled = true;
|
||||||
break;
|
break;
|
||||||
|
case ACTION_MENU_OTHER_STICK_UP:
|
||||||
|
sendInputToMovie(ACTION_MENU_UP, repeat, pressed, released);
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
case ACTION_MENU_OTHER_STICK_DOWN:
|
||||||
|
sendInputToMovie(ACTION_MENU_DOWN, repeat, pressed, released);
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1323,7 +1473,7 @@ void UIScene_LoadOrJoinMenu::handlePress(F64 controlId, F64 childId)
|
||||||
LoadMenuInitData *params = new LoadMenuInitData();
|
LoadMenuInitData *params = new LoadMenuInitData();
|
||||||
params->iPad = m_iPad;
|
params->iPad = m_iPad;
|
||||||
// need to get the iIndex from the list item, since the position in the list doesn't correspond to the GetSaveGameInfo list because of sorting
|
// need to get the iIndex from the list item, since the position in the list doesn't correspond to the GetSaveGameInfo list because of sorting
|
||||||
params->iSaveGameInfoIndex=((int)childId)-m_iDefaultButtonsC;
|
params->iSaveGameInfoIndex=m_saveDetails[((int)childId)-m_iDefaultButtonsC].saveId;
|
||||||
//params->pbSaveRenamed=&m_bSaveRenamed;
|
//params->pbSaveRenamed=&m_bSaveRenamed;
|
||||||
params->levelGen = NULL;
|
params->levelGen = NULL;
|
||||||
params->saveDetails = &m_saveDetails[ ((int)childId)-m_iDefaultButtonsC ];
|
params->saveDetails = &m_saveDetails[ ((int)childId)-m_iDefaultButtonsC ];
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,41 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "UI.h"
|
#include "UI.h"
|
||||||
#include "UIScene_SettingsGraphicsMenu.h"
|
#include "UIScene_SettingsGraphicsMenu.h"
|
||||||
|
#include "..\..\Minecraft.h"
|
||||||
|
#include "..\..\GameRenderer.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const int FOV_MIN = 70;
|
||||||
|
const int FOV_MAX = 110;
|
||||||
|
const int FOV_SLIDER_MAX = 100;
|
||||||
|
|
||||||
|
int clampFov(int value)
|
||||||
|
{
|
||||||
|
if (value < FOV_MIN) return FOV_MIN;
|
||||||
|
if (value > FOV_MAX) return FOV_MAX;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fovToSliderValue(float fov)
|
||||||
|
{
|
||||||
|
int clampedFov = clampFov((int)(fov + 0.5f));
|
||||||
|
return ((clampedFov - FOV_MIN) * FOV_SLIDER_MAX) / (FOV_MAX - FOV_MIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sliderValueToFov(int sliderValue)
|
||||||
|
{
|
||||||
|
if (sliderValue < 0) sliderValue = 0;
|
||||||
|
if (sliderValue > FOV_SLIDER_MAX) sliderValue = FOV_SLIDER_MAX;
|
||||||
|
return FOV_MIN + ((sliderValue * (FOV_MAX - FOV_MIN)) / FOV_SLIDER_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
|
UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
|
||||||
{
|
{
|
||||||
// Setup all the Iggy references we need for this scene
|
// Setup all the Iggy references we need for this scene
|
||||||
initialiseMovie();
|
initialiseMovie();
|
||||||
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
||||||
|
|
||||||
m_bNotInGame=(Minecraft::GetInstance()->level==NULL);
|
m_bNotInGame=(Minecraft::GetInstance()->level==NULL);
|
||||||
|
|
||||||
|
|
@ -18,6 +48,10 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD
|
||||||
|
|
||||||
swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_GAMMA ),app.GetGameSettings(m_iPad,eGameSetting_Gamma));
|
swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_GAMMA ),app.GetGameSettings(m_iPad,eGameSetting_Gamma));
|
||||||
m_sliderGamma.init(TempString,eControl_Gamma,0,100,app.GetGameSettings(m_iPad,eGameSetting_Gamma));
|
m_sliderGamma.init(TempString,eControl_Gamma,0,100,app.GetGameSettings(m_iPad,eGameSetting_Gamma));
|
||||||
|
|
||||||
|
int initialFov = clampFov((int)(pMinecraft->gameRenderer->GetFovVal() + 0.5f));
|
||||||
|
swprintf((WCHAR*)TempString, 256, L"FOV: %d", initialFov);
|
||||||
|
m_sliderFOV.init(TempString, eControl_FOV, 0, FOV_SLIDER_MAX, fovToSliderValue((float)initialFov));
|
||||||
|
|
||||||
swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_INTERFACEOPACITY ),app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity));
|
swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_INTERFACEOPACITY ),app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity));
|
||||||
m_sliderInterfaceOpacity.init(TempString,eControl_InterfaceOpacity,0,100,app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity));
|
m_sliderInterfaceOpacity.init(TempString,eControl_InterfaceOpacity,0,100,app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity));
|
||||||
|
|
@ -141,6 +175,19 @@ void UIScene_SettingsGraphicsMenu::handleSliderMove(F64 sliderId, F64 currentVal
|
||||||
m_sliderGamma.setLabel(TempString);
|
m_sliderGamma.setLabel(TempString);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case eControl_FOV:
|
||||||
|
{
|
||||||
|
m_sliderFOV.handleSliderMove(value);
|
||||||
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
||||||
|
int fovValue = sliderValueToFov(value);
|
||||||
|
pMinecraft->gameRenderer->SetFovVal((float)fovValue);
|
||||||
|
WCHAR TempString[256];
|
||||||
|
swprintf((WCHAR*)TempString, 256, L"FOV: %d", fovValue);
|
||||||
|
m_sliderFOV.setLabel(TempString);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case eControl_InterfaceOpacity:
|
case eControl_InterfaceOpacity:
|
||||||
m_sliderInterfaceOpacity.handleSliderMove(value);
|
m_sliderInterfaceOpacity.handleSliderMove(value);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,16 +11,18 @@ private:
|
||||||
eControl_BedrockFog,
|
eControl_BedrockFog,
|
||||||
eControl_CustomSkinAnim,
|
eControl_CustomSkinAnim,
|
||||||
eControl_Gamma,
|
eControl_Gamma,
|
||||||
|
eControl_FOV,
|
||||||
eControl_InterfaceOpacity
|
eControl_InterfaceOpacity
|
||||||
};
|
};
|
||||||
|
|
||||||
UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim; // Checkboxes
|
UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim; // Checkboxes
|
||||||
UIControl_Slider m_sliderGamma, m_sliderInterfaceOpacity; // Sliders
|
UIControl_Slider m_sliderGamma, m_sliderFOV, m_sliderInterfaceOpacity; // Sliders
|
||||||
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
|
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
|
||||||
UI_MAP_ELEMENT( m_checkboxClouds, "Clouds")
|
UI_MAP_ELEMENT( m_checkboxClouds, "Clouds")
|
||||||
UI_MAP_ELEMENT( m_checkboxBedrockFog, "BedrockFog")
|
UI_MAP_ELEMENT( m_checkboxBedrockFog, "BedrockFog")
|
||||||
UI_MAP_ELEMENT( m_checkboxCustomSkinAnim, "CustomSkinAnim")
|
UI_MAP_ELEMENT( m_checkboxCustomSkinAnim, "CustomSkinAnim")
|
||||||
UI_MAP_ELEMENT( m_sliderGamma, "Gamma")
|
UI_MAP_ELEMENT( m_sliderGamma, "Gamma")
|
||||||
|
UI_MAP_ELEMENT(m_sliderFOV, "FOV")
|
||||||
UI_MAP_ELEMENT( m_sliderInterfaceOpacity, "InterfaceOpacity")
|
UI_MAP_ELEMENT( m_sliderInterfaceOpacity, "InterfaceOpacity")
|
||||||
UI_END_MAP_ELEMENTS_AND_NAMES()
|
UI_END_MAP_ELEMENTS_AND_NAMES()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,12 +77,7 @@ void EnderDragonRenderer::renderModel(shared_ptr<LivingEntity> _mob, float wp, f
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glColor4f(1, 0, 0, 0.5f);
|
glColor4f(1, 0, 0, 0.5f);
|
||||||
#ifdef __PSVITA__
|
|
||||||
// AP - not sure that the usecompiled flag is supposed to be false. This makes it really slow on vita. Making it true still seems to look the same
|
|
||||||
model->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, true);
|
model->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, true);
|
||||||
#else
|
|
||||||
model->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, false);
|
|
||||||
#endif
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
|
||||||
|
|
@ -199,11 +199,10 @@ DWORD IQNetPlayer::GetSendQueueSize(IQNetPlayer * player, DWORD dwFlags) { retur
|
||||||
DWORD IQNetPlayer::GetCurrentRtt() { return 0; }
|
DWORD IQNetPlayer::GetCurrentRtt() { return 0; }
|
||||||
bool IQNetPlayer::IsHost() { return m_isHostPlayer; }
|
bool IQNetPlayer::IsHost() { return m_isHostPlayer; }
|
||||||
bool IQNetPlayer::IsGuest() { return false; }
|
bool IQNetPlayer::IsGuest() { return false; }
|
||||||
bool IQNetPlayer::IsLocal() { return true; }
|
bool IQNetPlayer::IsLocal() { return !m_isRemote; }
|
||||||
PlayerUID IQNetPlayer::GetXuid() { return INVALID_XUID; }
|
PlayerUID IQNetPlayer::GetXuid() { return (PlayerUID)(0xe000d45248242f2e + m_smallId); } // todo: restore to INVALID_XUID once saves support this
|
||||||
extern wstring g_playerName;
|
LPCWSTR IQNetPlayer::GetGamertag() { return m_gamertag; }
|
||||||
LPCWSTR IQNetPlayer::GetGamertag() { return g_playerName.empty() ? L"Windows" : g_playerName.c_str(); }
|
int IQNetPlayer::GetSessionIndex() { return m_smallId; }
|
||||||
int IQNetPlayer::GetSessionIndex() { return 0; }
|
|
||||||
bool IQNetPlayer::IsTalking() { return false; }
|
bool IQNetPlayer::IsTalking() { return false; }
|
||||||
bool IQNetPlayer::IsMutedByLocalUser(DWORD dwUserIndex) { return false; }
|
bool IQNetPlayer::IsMutedByLocalUser(DWORD dwUserIndex) { return false; }
|
||||||
bool IQNetPlayer::HasVoice() { return false; }
|
bool IQNetPlayer::HasVoice() { return false; }
|
||||||
|
|
@ -232,13 +231,17 @@ void Win64_SetupRemoteQNetPlayer(IQNetPlayer * player, BYTE smallId, bool isHost
|
||||||
IQNet::s_playerCount = smallId + 1;
|
IQNet::s_playerCount = smallId + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool Win64_IsActivePlayer(IQNetPlayer* p, DWORD index);
|
||||||
|
|
||||||
HRESULT IQNet::AddLocalPlayerByUserIndex(DWORD dwUserIndex) { return S_OK; }
|
HRESULT IQNet::AddLocalPlayerByUserIndex(DWORD dwUserIndex) { return S_OK; }
|
||||||
IQNetPlayer* IQNet::GetHostPlayer() { return &m_player[0]; }
|
IQNetPlayer* IQNet::GetHostPlayer() { return &m_player[0]; }
|
||||||
IQNetPlayer* IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex)
|
IQNetPlayer* IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex)
|
||||||
{
|
{
|
||||||
if (s_isHosting)
|
if (s_isHosting)
|
||||||
{
|
{
|
||||||
if (dwUserIndex < MINECRAFT_NET_MAX_PLAYERS && !m_player[dwUserIndex].m_isRemote)
|
if (dwUserIndex < MINECRAFT_NET_MAX_PLAYERS &&
|
||||||
|
!m_player[dwUserIndex].m_isRemote &&
|
||||||
|
Win64_IsActivePlayer(&m_player[dwUserIndex], dwUserIndex))
|
||||||
return &m_player[dwUserIndex];
|
return &m_player[dwUserIndex];
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +249,7 @@ IQNetPlayer* IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex)
|
||||||
return NULL;
|
return NULL;
|
||||||
for (DWORD i = 0; i < s_playerCount; i++)
|
for (DWORD i = 0; i < s_playerCount; i++)
|
||||||
{
|
{
|
||||||
if (!m_player[i].m_isRemote)
|
if (!m_player[i].m_isRemote && Win64_IsActivePlayer(&m_player[i], i))
|
||||||
return &m_player[i];
|
return &m_player[i];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -299,15 +302,28 @@ QNET_STATE IQNet::GetState() { return _iQNetStubState; }
|
||||||
bool IQNet::IsHost() { return s_isHosting; }
|
bool IQNet::IsHost() { return s_isHosting; }
|
||||||
HRESULT IQNet::JoinGameFromInviteInfo(DWORD dwUserIndex, DWORD dwUserMask, const INVITE_INFO * pInviteInfo) { return S_OK; }
|
HRESULT IQNet::JoinGameFromInviteInfo(DWORD dwUserIndex, DWORD dwUserMask, const INVITE_INFO * pInviteInfo) { return S_OK; }
|
||||||
void IQNet::HostGame() { _iQNetStubState = QNET_STATE_SESSION_STARTING; s_isHosting = true; }
|
void IQNet::HostGame() { _iQNetStubState = QNET_STATE_SESSION_STARTING; s_isHosting = true; }
|
||||||
void IQNet::ClientJoinGame() { _iQNetStubState = QNET_STATE_SESSION_STARTING; s_isHosting = false; }
|
void IQNet::ClientJoinGame()
|
||||||
|
{
|
||||||
|
_iQNetStubState = QNET_STATE_SESSION_STARTING;
|
||||||
|
s_isHosting = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++)
|
||||||
|
{
|
||||||
|
m_player[i].m_smallId = (BYTE)i;
|
||||||
|
m_player[i].m_isRemote = true;
|
||||||
|
m_player[i].m_isHostPlayer = false;
|
||||||
|
m_player[i].m_gamertag[0] = 0;
|
||||||
|
m_player[i].SetCustomDataValue(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
void IQNet::EndGame()
|
void IQNet::EndGame()
|
||||||
{
|
{
|
||||||
_iQNetStubState = QNET_STATE_IDLE;
|
_iQNetStubState = QNET_STATE_IDLE;
|
||||||
s_isHosting = false;
|
s_isHosting = false;
|
||||||
s_playerCount = 1;
|
s_playerCount = 1;
|
||||||
for (int i = 1; i < MINECRAFT_NET_MAX_PLAYERS; i++)
|
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++)
|
||||||
{
|
{
|
||||||
m_player[i].m_smallId = 0;
|
m_player[i].m_smallId = (BYTE)i;
|
||||||
m_player[i].m_isRemote = false;
|
m_player[i].m_isRemote = false;
|
||||||
m_player[i].m_isHostPlayer = false;
|
m_player[i].m_isHostPlayer = false;
|
||||||
m_player[i].m_gamertag[0] = 0;
|
m_player[i].m_gamertag[0] = 0;
|
||||||
|
|
@ -587,7 +603,6 @@ void C_4JProfile::SetPrimaryPad(int iPad) {}
|
||||||
#ifdef _DURANGO
|
#ifdef _DURANGO
|
||||||
char fakeGamerTag[32] = "PlayerName";
|
char fakeGamerTag[32] = "PlayerName";
|
||||||
void SetFakeGamertag(char* name) { strcpy_s(fakeGamerTag, name); }
|
void SetFakeGamertag(char* name) { strcpy_s(fakeGamerTag, name); }
|
||||||
char* C_4JProfile::GetGamertag(int iPad) { return fakeGamerTag; }
|
|
||||||
#else
|
#else
|
||||||
char* C_4JProfile::GetGamertag(int iPad) { extern char g_Win64Username[17]; return g_Win64Username; }
|
char* C_4JProfile::GetGamertag(int iPad) { extern char g_Win64Username[17]; return g_Win64Username; }
|
||||||
wstring C_4JProfile::GetDisplayName(int iPad) { extern wchar_t g_Win64UsernameW[17]; return g_Win64UsernameW; }
|
wstring C_4JProfile::GetDisplayName(int iPad) { extern wchar_t g_Win64UsernameW[17]; return g_Win64UsernameW; }
|
||||||
|
|
|
||||||
|
|
@ -501,23 +501,26 @@ void GameRenderer::moveCameraToPlayer(float a)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 4J - corrected bug where this used to just take player->xRot & yRot directly and so wasn't taking into account interpolation, allowing camera to go through walls
|
// 4J - corrected bug where this used to just take player->xRot & yRot directly and so wasn't taking into account interpolation, allowing camera to go through walls
|
||||||
float playerYRot = player->yRotO + (player->yRot - player->yRotO) * a;
|
float yRot = player->yRotO + (player->yRot - player->yRotO) * a;
|
||||||
float playerXRot = player->xRotO + (player->xRot - player->xRotO) * a;
|
float xRot = player->xRotO + (player->xRot - player->xRotO) * a;
|
||||||
float yRot = playerYRot;
|
|
||||||
float xRot = playerXRot;
|
|
||||||
|
|
||||||
// Thirdperson view values are now 0 for disabled, 1 for original mode, 2 for reversed.
|
// Thirdperson view values are now 0 for disabled, 1 for original mode, 2 for reversed.
|
||||||
if( localplayer->ThirdPersonView() == 2 )
|
if( localplayer->ThirdPersonView() == 2 )
|
||||||
{
|
{
|
||||||
// Reverse x rotation - note that this is only used in doing collision to calculate our view
|
// Reverse y rotation - note that this is only used in doing collision to calculate our view
|
||||||
// distance, the actual rotation itself is just below this else {} block
|
// distance, the actual rotation itself is just below this else {} block
|
||||||
xRot += 180.0f;
|
yRot += 180.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
double xd = -Mth::sin(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist;
|
double xd = -Mth::sin(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist;
|
||||||
double zd = Mth::cos(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist;
|
double zd = Mth::cos(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist;
|
||||||
double yd = -Mth::sin(xRot / 180 * PI) * cameraDist;
|
double yd = -Mth::sin(xRot / 180 * PI) * cameraDist;
|
||||||
|
|
||||||
|
if (localplayer->ThirdPersonView() == 2)
|
||||||
|
{
|
||||||
|
yd = Mth::sin(xRot / 180 * PI) * cameraDist;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
float xo = (float)((i & 1) * 2 - 1);
|
float xo = (float)((i & 1) * 2 - 1);
|
||||||
|
|
@ -538,16 +541,7 @@ void GameRenderer::moveCameraToPlayer(float a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( localplayer->ThirdPersonView() == 2)
|
|
||||||
{
|
|
||||||
glRotatef(180, 0, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
glRotatef(playerXRot - xRot, 1, 0, 0);
|
|
||||||
glRotatef(playerYRot - yRot, 0, 1, 0);
|
|
||||||
glTranslatef(0, 0, (float) -cameraDist);
|
glTranslatef(0, 0, (float) -cameraDist);
|
||||||
glRotatef(yRot - playerYRot, 0, 1, 0);
|
|
||||||
glRotatef(xRot - playerXRot, 1, 0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -557,8 +551,21 @@ void GameRenderer::moveCameraToPlayer(float a)
|
||||||
|
|
||||||
if (!mc->options->fixedCamera)
|
if (!mc->options->fixedCamera)
|
||||||
{
|
{
|
||||||
glRotatef(player->xRotO + (player->xRot - player->xRotO) * a, 1, 0, 0);
|
float pitch = player->xRotO + (player->xRot - player->xRotO) * a;
|
||||||
glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, 1, 0);
|
if (localplayer->ThirdPersonView() == 2)
|
||||||
|
{
|
||||||
|
pitch = -pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
glRotatef(pitch, 1, 0, 0);
|
||||||
|
if (localplayer->ThirdPersonView() == 2)
|
||||||
|
{
|
||||||
|
glRotatef(player->yRotO + (player->yRot - player->yRotO) * a, 0, 1, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, 1, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glTranslatef(0, heightOffset, 0);
|
glTranslatef(0, heightOffset, 0);
|
||||||
|
|
|
||||||
|
|
@ -7,20 +7,21 @@
|
||||||
#include "Input.h"
|
#include "Input.h"
|
||||||
#include "LocalPlayer.h"
|
#include "LocalPlayer.h"
|
||||||
#include "Options.h"
|
#include "Options.h"
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
#include "Windows64\KeyboardMouseInput.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
Input::Input()
|
Input::Input()
|
||||||
{
|
{
|
||||||
xa = 0;
|
xa = 0;
|
||||||
ya = 0;
|
ya = 0;
|
||||||
sprintForward = 0;
|
|
||||||
wasJumping = false;
|
wasJumping = false;
|
||||||
jumping = false;
|
jumping = false;
|
||||||
sneaking = false;
|
sneaking = false;
|
||||||
usingKeyboardMovement = false;
|
sprinting = false;
|
||||||
|
|
||||||
lReset = false;
|
lReset = false;
|
||||||
rReset = false;
|
rReset = false;
|
||||||
m_gamepadSneaking = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::tick(LocalPlayer *player)
|
void Input::tick(LocalPlayer *player)
|
||||||
|
|
@ -32,43 +33,43 @@ void Input::tick(LocalPlayer *player)
|
||||||
Minecraft *pMinecraft=Minecraft::GetInstance();
|
Minecraft *pMinecraft=Minecraft::GetInstance();
|
||||||
int iPad=player->GetXboxPad();
|
int iPad=player->GetXboxPad();
|
||||||
|
|
||||||
|
float controllerXA = 0.0f;
|
||||||
|
float controllerYA = 0.0f;
|
||||||
|
|
||||||
// 4J-PB minecraft movement seems to be the wrong way round, so invert x!
|
// 4J-PB minecraft movement seems to be the wrong way round, so invert x!
|
||||||
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_RIGHT) )
|
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_RIGHT) )
|
||||||
xa = -InputManager.GetJoypadStick_LX(iPad);
|
controllerXA = -InputManager.GetJoypadStick_LX(iPad);
|
||||||
else
|
|
||||||
xa = 0.0f;
|
|
||||||
|
|
||||||
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_FORWARD) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_BACKWARD) )
|
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_FORWARD) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_BACKWARD) )
|
||||||
ya = InputManager.GetJoypadStick_LY(iPad);
|
controllerYA = InputManager.GetJoypadStick_LY(iPad);
|
||||||
else
|
|
||||||
ya = 0.0f;
|
|
||||||
sprintForward = ya;
|
|
||||||
usingKeyboardMovement = false;
|
|
||||||
|
|
||||||
|
float kbXA = 0.0f;
|
||||||
|
float kbYA = 0.0f;
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
// WASD movement (combine with gamepad)
|
if (iPad == 0 && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
|
||||||
if (iPad == 0 && KMInput.IsCaptured())
|
|
||||||
{
|
{
|
||||||
float kbX = 0.0f, kbY = 0.0f;
|
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_RIGHT) )
|
||||||
if (KMInput.IsKeyDown('W')) { kbY += 1.0f; sprintForward += 1.0f; usingKeyboardMovement = true; }
|
kbXA = g_KBMInput.GetMoveX();
|
||||||
if (KMInput.IsKeyDown('S')) { kbY -= 1.0f; sprintForward -= 1.0f; usingKeyboardMovement = true; }
|
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_FORWARD) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_BACKWARD) )
|
||||||
if (KMInput.IsKeyDown('A')) { kbX += 1.0f; usingKeyboardMovement = true; } // inverted like gamepad
|
kbYA = g_KBMInput.GetMoveY();
|
||||||
if (KMInput.IsKeyDown('D')) { kbX -= 1.0f; usingKeyboardMovement = true; }
|
|
||||||
// Normalize diagonal
|
|
||||||
if (kbX != 0.0f && kbY != 0.0f) { kbX *= 0.707f; kbY *= 0.707f; }
|
|
||||||
if (pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_RIGHT))
|
|
||||||
xa = max(min(xa + kbX, 1.0f), -1.0f);
|
|
||||||
if (pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_FORWARD) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_BACKWARD))
|
|
||||||
ya = max(min(ya + kbY, 1.0f), -1.0f);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sprintForward = max(min(sprintForward, 1.0f), -1.0f);
|
|
||||||
|
if (kbXA != 0.0f || kbYA != 0.0f)
|
||||||
|
{
|
||||||
|
xa = kbXA;
|
||||||
|
ya = kbYA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xa = controllerXA;
|
||||||
|
ya = controllerYA;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef _CONTENT_PACKAGE
|
#ifndef _CONTENT_PACKAGE
|
||||||
if (app.GetFreezePlayers())
|
if (app.GetFreezePlayers())
|
||||||
{
|
{
|
||||||
xa = ya = 0.0f;
|
xa = ya = 0.0f;
|
||||||
sprintForward = 0.0f;
|
|
||||||
player->abilities.flying = true;
|
player->abilities.flying = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -80,7 +81,6 @@ void Input::tick(LocalPlayer *player)
|
||||||
lReset = true;
|
lReset = true;
|
||||||
}
|
}
|
||||||
xa = ya = 0.0f;
|
xa = ya = 0.0f;
|
||||||
sprintForward = 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4J: In flying mode, don't actually toggle sneaking (unless we're riding in which case we need to sneak to dismount)
|
// 4J: In flying mode, don't actually toggle sneaking (unless we're riding in which case we need to sneak to dismount)
|
||||||
|
|
@ -88,15 +88,46 @@ void Input::tick(LocalPlayer *player)
|
||||||
{
|
{
|
||||||
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE)) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_SNEAK_TOGGLE))
|
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE)) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_SNEAK_TOGGLE))
|
||||||
{
|
{
|
||||||
m_gamepadSneaking=!m_gamepadSneaking;
|
sneaking=!sneaking;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sneaking = m_gamepadSneaking;
|
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
// Keyboard hold-to-sneak (overrides gamepad toggle)
|
if (iPad == 0 && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
|
||||||
if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsKeyDown(VK_SHIFT) && !player->abilities.flying)
|
{
|
||||||
sneaking = true;
|
// Left Shift = sneak (hold to crouch)
|
||||||
|
if (pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_SNEAK_TOGGLE))
|
||||||
|
{
|
||||||
|
if (!player->abilities.flying)
|
||||||
|
{
|
||||||
|
sneaking = g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_SNEAK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left Ctrl + forward = sprint (hold to sprint)
|
||||||
|
if (!player->abilities.flying)
|
||||||
|
{
|
||||||
|
bool ctrlHeld = g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_SPRINT);
|
||||||
|
bool movingForward = (kbYA > 0.0f);
|
||||||
|
|
||||||
|
if (ctrlHeld && movingForward)
|
||||||
|
{
|
||||||
|
sprinting = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprinting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprinting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (iPad == 0)
|
||||||
|
{
|
||||||
|
sprinting = false;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(sneaking)
|
if(sneaking)
|
||||||
|
|
@ -109,6 +140,7 @@ void Input::tick(LocalPlayer *player)
|
||||||
|
|
||||||
float tx = 0.0f;
|
float tx = 0.0f;
|
||||||
float ty = 0.0f;
|
float ty = 0.0f;
|
||||||
|
|
||||||
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_RIGHT) )
|
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_RIGHT) )
|
||||||
tx = InputManager.GetJoypadStick_RX(iPad)*(((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InGame))/100.0f); // apply sensitivity to look
|
tx = InputManager.GetJoypadStick_RX(iPad)*(((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InGame))/100.0f); // apply sensitivity to look
|
||||||
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_UP) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_DOWN) )
|
if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_UP) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_DOWN) )
|
||||||
|
|
@ -132,47 +164,52 @@ void Input::tick(LocalPlayer *player)
|
||||||
}
|
}
|
||||||
tx = ty = 0.0f;
|
tx = ty = 0.0f;
|
||||||
}
|
}
|
||||||
player->interpolateTurn(tx * abs(tx) * turnSpeed, ty * abs(ty) * turnSpeed);
|
|
||||||
|
float turnX = tx * abs(tx) * turnSpeed;
|
||||||
|
float turnY = ty * abs(ty) * turnSpeed;
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
// Mouse look is now handled per-frame in Minecraft::applyFrameMouseLook()
|
if (iPad == 0 && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
|
||||||
// to eliminate the 20Hz tick delay. Only flush any remaining delta here
|
|
||||||
// as a safety measure.
|
|
||||||
if (iPad == 0 && KMInput.IsCaptured())
|
|
||||||
{
|
{
|
||||||
float rawDx, rawDy;
|
float mouseSensitivity = ((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InGame)) / 100.0f;
|
||||||
KMInput.ConsumeMouseDelta(rawDx, rawDy);
|
float mouseLookScale = 5.0f;
|
||||||
// Delta should normally be 0 since applyFrameMouseLook() already consumed it
|
float mx = g_KBMInput.GetLookX(mouseSensitivity * mouseLookScale);
|
||||||
if (rawDx != 0.0f || rawDy != 0.0f)
|
float my = g_KBMInput.GetLookY(mouseSensitivity * mouseLookScale);
|
||||||
|
|
||||||
|
if ( app.GetGameSettings(iPad,eGameSetting_ControlInvertLook) )
|
||||||
{
|
{
|
||||||
float mouseSensitivity = 0.5f;
|
my = -my;
|
||||||
float mdx = rawDx * mouseSensitivity;
|
|
||||||
float mdy = -rawDy * mouseSensitivity;
|
|
||||||
if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
|
|
||||||
mdy = -mdy;
|
|
||||||
player->interpolateTurn(mdx, mdy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
turnX += mx;
|
||||||
|
turnY += my;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
player->interpolateTurn(turnX, turnY);
|
||||||
|
|
||||||
//jumping = controller.isButtonPressed(0);
|
//jumping = controller.isButtonPressed(0);
|
||||||
|
|
||||||
|
|
||||||
unsigned int jump = InputManager.GetValue(iPad, MINECRAFT_ACTION_JUMP);
|
unsigned int jump = InputManager.GetValue(iPad, MINECRAFT_ACTION_JUMP);
|
||||||
if( jump > 0 && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP) )
|
bool kbJump = false;
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
kbJump = (iPad == 0) && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive() && g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_JUMP);
|
||||||
|
#endif
|
||||||
|
if( (jump > 0 || kbJump) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP) )
|
||||||
jumping = true;
|
jumping = true;
|
||||||
else
|
else
|
||||||
jumping = false;
|
jumping = false;
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
|
||||||
// Keyboard jump (Space)
|
|
||||||
if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsKeyDown(VK_SPACE) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP))
|
|
||||||
jumping = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _CONTENT_PACKAGE
|
#ifndef _CONTENT_PACKAGE
|
||||||
if (app.GetFreezePlayers()) jumping = false;
|
if (app.GetFreezePlayers()) jumping = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (iPad == 0 && g_KBMInput.IsKeyPressed(VK_ESCAPE) && g_KBMInput.IsMouseGrabbed())
|
||||||
|
{
|
||||||
|
g_KBMInput.SetMouseGrabbed(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//OutputDebugString("INPUT: End input tick\n");
|
//OutputDebugString("INPUT: End input tick\n");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,17 @@ class Input
|
||||||
public:
|
public:
|
||||||
float xa;
|
float xa;
|
||||||
float ya;
|
float ya;
|
||||||
float sprintForward;
|
|
||||||
|
|
||||||
bool wasJumping;
|
bool wasJumping;
|
||||||
bool jumping;
|
bool jumping;
|
||||||
bool sneaking;
|
bool sneaking;
|
||||||
bool usingKeyboardMovement;
|
bool sprinting;
|
||||||
|
|
||||||
Input(); // 4J - added
|
Input();
|
||||||
|
|
||||||
virtual void tick(LocalPlayer *player);
|
virtual void tick(LocalPlayer *player);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool lReset;
|
bool lReset;
|
||||||
bool rReset;
|
bool rReset;
|
||||||
bool m_gamepadSneaking;
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1964,8 +1964,8 @@ bool LevelRenderer::updateDirtyChunks()
|
||||||
{
|
{
|
||||||
if( (!onlyRebuild) ||
|
if( (!onlyRebuild) ||
|
||||||
globalChunkFlags[ pClipChunk->globalIdx ] & CHUNK_FLAG_COMPILED ||
|
globalChunkFlags[ pClipChunk->globalIdx ] & CHUNK_FLAG_COMPILED ||
|
||||||
( distSq < 20 * 20 ) ) // Always rebuild really near things or else building (say) at tower up into empty blocks when we are low on memory will not create render data
|
( distSq < 96 * 96 ) ) // Always rebuild really near things or else building (say) at tower up into empty blocks when we are low on memory will not create render data
|
||||||
{
|
{ // distSq adjusted from 20 * 20 to 96 * 96 - updated by detectiveren
|
||||||
considered++;
|
considered++;
|
||||||
// Is this chunk nearer than our nearest?
|
// Is this chunk nearer than our nearest?
|
||||||
#ifdef _LARGE_WORLDS
|
#ifdef _LARGE_WORLDS
|
||||||
|
|
@ -2557,13 +2557,19 @@ void LevelRenderer::cull(Culler *culler, float a)
|
||||||
{
|
{
|
||||||
unsigned char flags = pClipChunk->globalIdx == -1 ? 0 : globalChunkFlags[ pClipChunk->globalIdx ];
|
unsigned char flags = pClipChunk->globalIdx == -1 ? 0 : globalChunkFlags[ pClipChunk->globalIdx ];
|
||||||
|
|
||||||
|
// Always perform frustum cull test
|
||||||
|
bool clipres = clip(pClipChunk->aabb, fdraw);
|
||||||
|
|
||||||
if ( (flags & CHUNK_FLAG_COMPILED ) && ( ( flags & CHUNK_FLAG_EMPTYBOTH ) != CHUNK_FLAG_EMPTYBOTH ) )
|
if ( (flags & CHUNK_FLAG_COMPILED ) && ( ( flags & CHUNK_FLAG_EMPTYBOTH ) != CHUNK_FLAG_EMPTYBOTH ) )
|
||||||
{
|
{
|
||||||
bool clipres = clip(pClipChunk->aabb, fdraw);
|
|
||||||
pClipChunk->visible = clipres;
|
pClipChunk->visible = clipres;
|
||||||
if( pClipChunk->visible ) vis++;
|
if( pClipChunk->visible ) vis++;
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
|
else if (clipres)
|
||||||
|
{
|
||||||
|
pClipChunk->visible = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pClipChunk->visible = false;
|
pClipChunk->visible = false;
|
||||||
|
|
@ -2572,6 +2578,7 @@ void LevelRenderer::cull(Culler *culler, float a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LevelRenderer::playStreamingMusic(const wstring& name, int x, int y, int z)
|
void LevelRenderer::playStreamingMusic(const wstring& name, int x, int y, int z)
|
||||||
{
|
{
|
||||||
if (name != L"")
|
if (name != L"")
|
||||||
|
|
|
||||||
|
|
@ -52,14 +52,16 @@ public:
|
||||||
static const int CHUNK_SIZE = 16;
|
static const int CHUNK_SIZE = 16;
|
||||||
#endif
|
#endif
|
||||||
static const int CHUNK_Y_COUNT = Level::maxBuildHeight / CHUNK_SIZE;
|
static const int CHUNK_Y_COUNT = Level::maxBuildHeight / CHUNK_SIZE;
|
||||||
#if defined _XBOX_ONE
|
#if defined _WINDOWS64
|
||||||
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 2047 * 1024 * 1024; // Changed to 2047. 4J had set to 512.
|
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 2047 * 1024 * 1024; // Changed to 2047. 4J had set to 512.
|
||||||
|
#elif defined _XBOX_ONE
|
||||||
|
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 512 * 1024 * 1024; // 4J - added
|
||||||
#elif defined __ORBIS__
|
#elif defined __ORBIS__
|
||||||
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 448 * 1024 * 1024; // 4J - added - hard limit is 512 so giving a lot of headroom here for fragmentation (have seen 16MB lost to fragmentation in multiplayer crash dump before)
|
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 448 * 1024 * 1024; // 4J - added - hard limit is 512 so giving a lot of headroom here for fragmentation (have seen 16MB lost to fragmentation in multiplayer crash dump before)
|
||||||
#elif defined __PS3__
|
#elif defined __PS3__
|
||||||
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 110 * 1024 * 1024; // 4J - added
|
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 110 * 1024 * 1024; // 4J - added
|
||||||
#else
|
#else
|
||||||
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 55 * 1024 * 1024; // 4J - added
|
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 55 * 1024 * 1024; // 4J - added
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
LevelRenderer(Minecraft *mc, Textures *textures);
|
LevelRenderer(Minecraft *mc, Textures *textures);
|
||||||
|
|
@ -270,10 +272,10 @@ public:
|
||||||
|
|
||||||
bool dirtyChunkPresent;
|
bool dirtyChunkPresent;
|
||||||
__int64 lastDirtyChunkFound;
|
__int64 lastDirtyChunkFound;
|
||||||
static const int FORCE_DIRTY_CHUNK_CHECK_PERIOD_MS = 250;
|
static const int FORCE_DIRTY_CHUNK_CHECK_PERIOD_MS = 125; // decreased from 250 to 125 - updated by detectiveren
|
||||||
|
|
||||||
#ifdef _LARGE_WORLDS
|
#ifdef _LARGE_WORLDS
|
||||||
static const int MAX_CONCURRENT_CHUNK_REBUILDS = 4;
|
static const int MAX_CONCURRENT_CHUNK_REBUILDS = 8; // increased from 4 to 8 - updated by detectiveren
|
||||||
static const int MAX_CHUNK_REBUILD_THREADS = MAX_CONCURRENT_CHUNK_REBUILDS - 1;
|
static const int MAX_CHUNK_REBUILD_THREADS = MAX_CONCURRENT_CHUNK_REBUILDS - 1;
|
||||||
static Chunk permaChunk[MAX_CONCURRENT_CHUNK_REBUILDS];
|
static Chunk permaChunk[MAX_CONCURRENT_CHUNK_REBUILDS];
|
||||||
static C4JThread *rebuildThreads[MAX_CHUNK_REBUILD_THREADS];
|
static C4JThread *rebuildThreads[MAX_CHUNK_REBUILD_THREADS];
|
||||||
|
|
|
||||||
|
|
@ -487,11 +487,11 @@ void LivingEntityRenderer::renderNameTag(shared_ptr<LivingEntity> mob, const wst
|
||||||
|
|
||||||
Font *font = getFont();
|
Font *font = getFont();
|
||||||
|
|
||||||
float size = 1.60f;
|
constexpr float size = 1.60f;
|
||||||
float s = 1 / 60.0f * size;
|
constexpr float s = 1 / 60.0f * size;
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef((float) x + 0, (float) y + 2.3f, (float) z);
|
glTranslatef(static_cast<float>(x) + 0, static_cast<float>(y) + mob->bbHeight + 0.5f, static_cast<float>(z));
|
||||||
glNormal3f(0, 1, 0);
|
glNormal3f(0, 1, 0);
|
||||||
|
|
||||||
glRotatef(-this->entityRenderDispatcher->playerRotY, 0, 1, 0);
|
glRotatef(-this->entityRenderDispatcher->playerRotY, 0, 1, 0);
|
||||||
|
|
|
||||||
|
|
@ -251,13 +251,10 @@ void LocalPlayer::aiStep()
|
||||||
if (changingDimensionDelay > 0) changingDimensionDelay--;
|
if (changingDimensionDelay > 0) changingDimensionDelay--;
|
||||||
bool wasJumping = input->jumping;
|
bool wasJumping = input->jumping;
|
||||||
float runTreshold = 0.8f;
|
float runTreshold = 0.8f;
|
||||||
float sprintForward = input->sprintForward;
|
bool wasRunning = input->ya >= runTreshold;
|
||||||
|
|
||||||
bool wasRunning = sprintForward >= runTreshold;
|
|
||||||
//input->tick( dynamic_pointer_cast<Player>( shared_from_this() ) );
|
//input->tick( dynamic_pointer_cast<Player>( shared_from_this() ) );
|
||||||
// 4J-PB - make it a localplayer
|
// 4J-PB - make it a localplayer
|
||||||
input->tick( this );
|
input->tick( this );
|
||||||
sprintForward = input->sprintForward;
|
|
||||||
if (isUsingItem() && !isRiding())
|
if (isUsingItem() && !isRiding())
|
||||||
{
|
{
|
||||||
input->xa *= 0.2f;
|
input->xa *= 0.2f;
|
||||||
|
|
@ -281,25 +278,9 @@ void LocalPlayer::aiStep()
|
||||||
// world with low food, then reload it in creative.
|
// world with low food, then reload it in creative.
|
||||||
if(abilities.mayfly || isAllowedToFly() ) enoughFoodToSprint = true;
|
if(abilities.mayfly || isAllowedToFly() ) enoughFoodToSprint = true;
|
||||||
|
|
||||||
bool forwardEnoughToTriggerSprint = sprintForward >= runTreshold;
|
bool forwardEnoughToTriggerSprint = input->ya >= runTreshold;
|
||||||
bool forwardReturnedToDeadzone = sprintForward == 0.0f;
|
bool forwardReturnedToDeadzone = input->ya == 0.0f;
|
||||||
bool forwardEnoughToContinueSprint = sprintForward >= runTreshold;
|
bool forwardEnoughToContinueSprint = input->ya >= runTreshold;
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
|
||||||
if (GetXboxPad() == 0 && input->usingKeyboardMovement)
|
|
||||||
{
|
|
||||||
forwardEnoughToContinueSprint = sprintForward > 0.0f;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
|
||||||
// Keyboard sprint: Ctrl held while moving forward
|
|
||||||
if (GetXboxPad() == 0 && input->usingKeyboardMovement && KMInput.IsKeyDown(VK_CONTROL) && sprintForward > 0.0f &&
|
|
||||||
enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness) && onGround)
|
|
||||||
{
|
|
||||||
if (!isSprinting()) setSprinting(true);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 4J - altered this slightly to make sure that the joypad returns to below returnTreshold in between registering two movements up to runThreshold
|
// 4J - altered this slightly to make sure that the joypad returns to below returnTreshold in between registering two movements up to runThreshold
|
||||||
if (onGround && !isSprinting() && enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness))
|
if (onGround && !isSprinting() && enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness))
|
||||||
|
|
@ -327,6 +308,12 @@ void LocalPlayer::aiStep()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isSneaking()) sprintTriggerTime = 0;
|
if (isSneaking()) sprintTriggerTime = 0;
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (input->sprinting && onGround && enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness) && !isSneaking())
|
||||||
|
{
|
||||||
|
setSprinting(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// 4J-PB - try not stopping sprint on collision
|
// 4J-PB - try not stopping sprint on collision
|
||||||
//if (isSprinting() && (input->ya < runTreshold || horizontalCollision || !enoughFoodToSprint))
|
//if (isSprinting() && (input->ya < runTreshold || horizontalCollision || !enoughFoodToSprint))
|
||||||
if (isSprinting() && (!forwardEnoughToContinueSprint || !enoughFoodToSprint || isSneaking() || isUsingItem()))
|
if (isSprinting() && (!forwardEnoughToContinueSprint || !enoughFoodToSprint || isSneaking() || isUsingItem()))
|
||||||
|
|
|
||||||
|
|
@ -310,6 +310,7 @@
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
|
@ -774,7 +775,7 @@
|
||||||
</CustomBuildBeforeTargets>
|
</CustomBuildBeforeTargets>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<ImageXexOutput>$(OutDir)$(ProjectName)_D.xex</ImageXexOutput>
|
<ImageXexOutput>$(OutDir)$(ProjectName)_D.xex</ImageXexOutput>
|
||||||
<IncludePath>$(ProjectDir)\..\Minecraft.World\x64headers;$(ProjectDir)\Xbox\Sentient\Include;$(IncludePath)</IncludePath>
|
<IncludePath>$(ProjectDir)\..\Minecraft.World\x64headers;$(ProjectDir)\Xbox\Sentient\Include;$(IncludePath)</IncludePath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
@ -1544,6 +1545,7 @@ if not exist "$(TargetDir)\savedata" mkdir "$(TargetDir)\savedata"</Command>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<ShowIncludes>false</ShowIncludes>
|
<ShowIncludes>false</ShowIncludes>
|
||||||
|
<AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
|
@ -1756,7 +1758,7 @@ xcopy /q /y /i /s /e $(ProjectDir)DurangoMedia\CU $(LayoutDir)Image\Loose\CU</C
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<Optimization>Full</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<ExceptionHandling>Sync</ExceptionHandling>
|
<ExceptionHandling>Sync</ExceptionHandling>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
|
<PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
|
||||||
|
|
@ -1769,6 +1771,10 @@ xcopy /q /y /i /s /e $(ProjectDir)DurangoMedia\CU $(LayoutDir)Image\Loose\CU</C
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<ShowIncludes>false</ShowIncludes>
|
<ShowIncludes>false</ShowIncludes>
|
||||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<AdditionalOptions>/FS /Ob3 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
|
@ -1776,6 +1782,7 @@ xcopy /q /y /i /s /e $(ProjectDir)DurangoMedia\CU $(LayoutDir)Image\Loose\CU</C
|
||||||
<AdditionalDependencies>legacy_stdio_definitions.lib;d3d11.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>legacy_stdio_definitions.lib;d3d11.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<ShowProgress>NotSet</ShowProgress>
|
<ShowProgress>NotSet</ShowProgress>
|
||||||
<SuppressStartupBanner>false</SuppressStartupBanner>
|
<SuppressStartupBanner>false</SuppressStartupBanner>
|
||||||
|
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Message>Run postbuild script</Message>
|
<Message>Run postbuild script</Message>
|
||||||
|
|
@ -48671,4 +48678,4 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -19,4 +19,4 @@
|
||||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory>
|
<LocalDebuggerWorkingDirectory>$(SolutionDir)$(Platform)\$(Configuration)\</LocalDebuggerWorkingDirectory>
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -502,6 +502,13 @@ void Minecraft::setScreen(Screen *screen)
|
||||||
this->screen->removed();
|
this->screen->removed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (screen != NULL && g_KBMInput.IsMouseGrabbed())
|
||||||
|
{
|
||||||
|
g_KBMInput.SetMouseGrabbed(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//4J Gordon: Do not force a stats save here
|
//4J Gordon: Do not force a stats save here
|
||||||
/*if (dynamic_cast<TitleScreen *>(screen)!=NULL)
|
/*if (dynamic_cast<TitleScreen *>(screen)!=NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -1184,14 +1191,14 @@ void Minecraft::applyFrameMouseLook()
|
||||||
int iPad = localplayers[i]->GetXboxPad();
|
int iPad = localplayers[i]->GetXboxPad();
|
||||||
if (iPad != 0) continue; // Mouse only applies to pad 0
|
if (iPad != 0) continue; // Mouse only applies to pad 0
|
||||||
|
|
||||||
if (!KMInput.IsCaptured()) continue;
|
if (!g_KBMInput.IsMouseGrabbed()) continue;
|
||||||
if (localgameModes[iPad] == NULL) continue;
|
if (localgameModes[iPad] == NULL) continue;
|
||||||
|
|
||||||
float rawDx, rawDy;
|
float rawDx, rawDy;
|
||||||
KMInput.ConsumeMouseDelta(rawDx, rawDy);
|
g_KBMInput.ConsumeMouseDelta(rawDx, rawDy);
|
||||||
if (rawDx == 0.0f && rawDy == 0.0f) continue;
|
if (rawDx == 0.0f && rawDy == 0.0f) continue;
|
||||||
|
|
||||||
float mouseSensitivity = 0.5f;
|
float mouseSensitivity = ((float)app.GetGameSettings(iPad, eGameSetting_Sensitivity_InGame)) / 100.0f;
|
||||||
float mdx = rawDx * mouseSensitivity;
|
float mdx = rawDx * mouseSensitivity;
|
||||||
float mdy = -rawDy * mouseSensitivity;
|
float mdy = -rawDy * mouseSensitivity;
|
||||||
if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
|
if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
|
||||||
|
|
@ -1450,14 +1457,54 @@ void Minecraft::run_middle()
|
||||||
// Keyboard/mouse button presses for player 0
|
// Keyboard/mouse button presses for player 0
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
if (KMInput.ConsumeKeyPress(VK_ESCAPE)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_PAUSEMENU;
|
if (g_KBMInput.IsKBMActive())
|
||||||
if (KMInput.ConsumeKeyPress('E')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_INVENTORY;
|
{
|
||||||
if (KMInput.ConsumeKeyPress('Q')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_DROP;
|
if(g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
|
||||||
if (KMInput.ConsumeKeyPress('C')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_CRAFTING;
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_ACTION;
|
||||||
if (KMInput.ConsumeKeyPress(VK_F5)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON;
|
|
||||||
|
if(g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT))
|
||||||
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_USE;
|
||||||
|
|
||||||
|
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_INVENTORY))
|
||||||
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_INVENTORY;
|
||||||
|
|
||||||
|
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DROP))
|
||||||
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_DROP;
|
||||||
|
|
||||||
|
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_CRAFTING) || g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_CRAFTING_ALT))
|
||||||
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_CRAFTING;
|
||||||
|
|
||||||
|
for (int slot = 0; slot < 9; slot++)
|
||||||
|
{
|
||||||
|
if (g_KBMInput.IsKeyPressed('1' + slot))
|
||||||
|
{
|
||||||
|
if (localplayers[i]->inventory)
|
||||||
|
localplayers[i]->inventory->selected = slot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility keys always work regardless of KBM active state
|
||||||
|
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_PAUSE) && !ui.IsTutorialVisible(i))
|
||||||
|
{
|
||||||
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_PAUSEMENU;
|
||||||
|
app.DebugPrintf("PAUSE PRESSED (keyboard) - ipad = %d\n",i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_THIRD_PERSON))
|
||||||
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON;
|
||||||
|
|
||||||
|
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DEBUG_INFO))
|
||||||
|
{
|
||||||
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_GAME_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
// In flying mode, Shift held = sneak/descend
|
// In flying mode, Shift held = sneak/descend
|
||||||
if (localplayers[i]->abilities.flying && KMInput.IsKeyDown(VK_SHIFT))
|
if(g_KBMInput.IsKBMActive() && g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_SNEAK))
|
||||||
localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE;
|
{
|
||||||
|
if (localplayers[i]->abilities.flying && !ui.GetMenuDisplayed(i))
|
||||||
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -2277,8 +2324,21 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if ((screen != NULL || ui.GetMenuDisplayed(iPad)) && g_KBMInput.IsMouseGrabbed())
|
||||||
|
{
|
||||||
|
g_KBMInput.SetMouseGrabbed(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (screen == NULL && !ui.GetMenuDisplayed(iPad) )
|
if (screen == NULL && !ui.GetMenuDisplayed(iPad) )
|
||||||
{
|
{
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsWindowFocused())
|
||||||
|
{
|
||||||
|
g_KBMInput.SetMouseGrabbed(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// 4J-PB - add some tooltips if required
|
// 4J-PB - add some tooltips if required
|
||||||
int iA=-1, iB=-1, iX, iY=IDS_CONTROLS_INVENTORY, iLT=-1, iRT=-1, iLB=-1, iRB=-1, iLS=-1, iRS=-1;
|
int iA=-1, iB=-1, iX, iY=IDS_CONTROLS_INVENTORY, iLT=-1, iRT=-1, iLB=-1, iRB=-1, iLS=-1, iRS=-1;
|
||||||
|
|
||||||
|
|
@ -3432,26 +3492,9 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
// Mouse scroll wheel for hotbar
|
if (iPad == 0 && wheel == 0 && g_KBMInput.IsKBMActive())
|
||||||
if (iPad == 0)
|
|
||||||
{
|
{
|
||||||
int kbWheel = KMInput.ConsumeScrollDelta();
|
wheel = g_KBMInput.GetMouseWheel();
|
||||||
if (kbWheel > 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL)) wheel += 1;
|
|
||||||
else if (kbWheel < 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_RIGHT_SCROLL)) wheel -= 1;
|
|
||||||
|
|
||||||
// 1-9 keys for direct hotbar selection
|
|
||||||
if (gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL))
|
|
||||||
{
|
|
||||||
for (int k = '1'; k <= '9'; k++)
|
|
||||||
{
|
|
||||||
if (KMInput.ConsumeKeyPress(k))
|
|
||||||
{
|
|
||||||
player->inventory->selected = k - '1';
|
|
||||||
app.SetOpacityTimer(iPad);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (wheel != 0)
|
if (wheel != 0)
|
||||||
|
|
@ -3485,33 +3528,20 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||||
player->handleMouseClick(0);
|
player->handleMouseClick(0);
|
||||||
player->lastClickTick[0] = ticks;
|
player->lastClickTick[0] = ticks;
|
||||||
}
|
}
|
||||||
#ifdef _WINDOWS64
|
|
||||||
else if (iPad == 0 && KMInput.IsCaptured() && KMInput.ConsumeMousePress(0))
|
|
||||||
{
|
|
||||||
player->handleMouseClick(0);
|
|
||||||
player->lastClickTick[0] = ticks;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) && ticks - player->lastClickTick[0] >= timer->ticksPerSecond / 4)
|
#ifdef _WINDOWS64
|
||||||
|
bool actionHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) || (iPad == 0 && g_KBMInput.IsKBMActive() && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT));
|
||||||
|
#else
|
||||||
|
bool actionHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION);
|
||||||
|
#endif
|
||||||
|
if (actionHeld && ticks - player->lastClickTick[0] >= timer->ticksPerSecond / 4)
|
||||||
{
|
{
|
||||||
//printf("MINECRAFT_ACTION_ACTION ButtonDown");
|
//printf("MINECRAFT_ACTION_ACTION ButtonDown");
|
||||||
player->handleMouseClick(0);
|
player->handleMouseClick(0);
|
||||||
player->lastClickTick[0] = ticks;
|
player->lastClickTick[0] = ticks;
|
||||||
}
|
}
|
||||||
#ifdef _WINDOWS64
|
|
||||||
else if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(0) && ticks - player->lastClickTick[0] >= timer->ticksPerSecond / 4)
|
|
||||||
{
|
|
||||||
player->handleMouseClick(0);
|
|
||||||
player->lastClickTick[0] = ticks;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION)
|
if(actionHeld)
|
||||||
#ifdef _WINDOWS64
|
|
||||||
|| (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(0))
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
player->handleMouseDown(0, true );
|
player->handleMouseDown(0, true );
|
||||||
}
|
}
|
||||||
|
|
@ -3530,25 +3560,21 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||||
lastClickTick = ticks;
|
lastClickTick = ticks;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
bool useHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) || (iPad == 0 && g_KBMInput.IsKBMActive() && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_RIGHT));
|
||||||
|
#else
|
||||||
|
bool useHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE);
|
||||||
|
#endif
|
||||||
if( player->isUsingItem() )
|
if( player->isUsingItem() )
|
||||||
{
|
{
|
||||||
if(!InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE)
|
if(!useHeld) gameMode->releaseUsingItem(player);
|
||||||
#ifdef _WINDOWS64
|
|
||||||
&& !(iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(1))
|
|
||||||
#endif
|
|
||||||
) gameMode->releaseUsingItem(player);
|
|
||||||
}
|
}
|
||||||
else if( gameMode->isInputAllowed(MINECRAFT_ACTION_USE) )
|
else if( gameMode->isInputAllowed(MINECRAFT_ACTION_USE) )
|
||||||
{
|
{
|
||||||
#ifdef _WINDOWS64
|
|
||||||
bool useButtonDown = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) || (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(1));
|
|
||||||
#else
|
|
||||||
bool useButtonDown = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE);
|
|
||||||
#endif
|
|
||||||
if( player->abilities.instabuild )
|
if( player->abilities.instabuild )
|
||||||
{
|
{
|
||||||
// 4J - attempt to handle click in special creative mode fashion if possible (used for placing blocks at regular intervals)
|
// 4J - attempt to handle click in special creative mode fashion if possible (used for placing blocks at regular intervals)
|
||||||
bool didClick = player->creativeModeHandleMouseClick(1, useButtonDown );
|
bool didClick = player->creativeModeHandleMouseClick(1, useHeld );
|
||||||
// If this handler has put us in lastClick_oldRepeat mode then it is because we aren't placing blocks - behave largely as the code used to
|
// If this handler has put us in lastClick_oldRepeat mode then it is because we aren't placing blocks - behave largely as the code used to
|
||||||
if( player->lastClickState == LocalPlayer::lastClick_oldRepeat )
|
if( player->lastClickState == LocalPlayer::lastClick_oldRepeat )
|
||||||
{
|
{
|
||||||
|
|
@ -3560,7 +3586,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Otherwise just the original game code for handling autorepeat
|
// Otherwise just the original game code for handling autorepeat
|
||||||
if (useButtonDown && ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4)
|
if (useHeld && ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4)
|
||||||
{
|
{
|
||||||
player->handleMouseClick(1);
|
player->handleMouseClick(1);
|
||||||
player->lastClickTick[1] = ticks;
|
player->lastClickTick[1] = ticks;
|
||||||
|
|
@ -3576,7 +3602,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||||
bool firstClick = ( player->lastClickTick[1] == 0 );
|
bool firstClick = ( player->lastClickTick[1] == 0 );
|
||||||
bool autoRepeat = ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4;
|
bool autoRepeat = ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4;
|
||||||
if ( player->isRiding() || player->isSprinting() || player->isSleeping() ) autoRepeat = false;
|
if ( player->isRiding() || player->isSprinting() || player->isSleeping() ) autoRepeat = false;
|
||||||
if (useButtonDown )
|
if (useHeld )
|
||||||
{
|
{
|
||||||
// If the player has just exited a bed, then delay the time before a repeat key is allowed without releasing
|
// If the player has just exited a bed, then delay the time before a repeat key is allowed without releasing
|
||||||
if(player->isSleeping() ) player->lastClickTick[1] = ticks + (timer->ticksPerSecond * 2);
|
if(player->isSleeping() ) player->lastClickTick[1] = ticks + (timer->ticksPerSecond * 2);
|
||||||
|
|
@ -3618,8 +3644,6 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||||
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_RENDER_DEBUG)) )
|
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_RENDER_DEBUG)) )
|
||||||
{
|
{
|
||||||
#ifndef _CONTENT_PACKAGE
|
#ifndef _CONTENT_PACKAGE
|
||||||
|
|
||||||
options->renderDebug = !options->renderDebug;
|
|
||||||
#ifdef _XBOX
|
#ifdef _XBOX
|
||||||
app.EnableDebugOverlay(options->renderDebug,iPad);
|
app.EnableDebugOverlay(options->renderDebug,iPad);
|
||||||
#else
|
#else
|
||||||
|
|
@ -3629,13 +3653,11 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_SPAWN_CREEPER)) && app.GetMobsDontAttackEnabled())
|
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_SPAWN_CREEPER)))
|
||||||
{
|
{
|
||||||
//shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(Creeper::_class->newInstance( level ));
|
#ifndef _CONTENT_PACKAGE
|
||||||
//shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(Wolf::_class->newInstance( level ));
|
options->renderDebug = !options->renderDebug;
|
||||||
shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(shared_ptr<Spider>(new Spider( level )));
|
#endif
|
||||||
mob->moveTo(player->x+1, player->y, player->z+1, level->random->nextFloat() * 360, 0);
|
|
||||||
level->addEntity(mob);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,14 @@
|
||||||
#include "Minecraft.World/Pos.h"
|
#include "Minecraft.World/Pos.h"
|
||||||
#include "Minecraft.World/System.h"
|
#include "Minecraft.World/System.h"
|
||||||
#include "Minecraft.World/StringHelpers.h"
|
#include "Minecraft.World/StringHelpers.h"
|
||||||
|
#include "Minecraft.World/net.minecraft.world.entity.item.h"
|
||||||
|
#include "Minecraft.World/net.minecraft.world.item.h"
|
||||||
|
#include "Minecraft.World/net.minecraft.world.item.enchantment.h"
|
||||||
|
#include "Minecraft.World/net.minecraft.world.damagesource.h"
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
#include "Windows64\Network\WinsockNetLayer.h"
|
||||||
|
#endif
|
||||||
|
#include <sstream>
|
||||||
#ifdef SPLIT_SAVES
|
#ifdef SPLIT_SAVES
|
||||||
#include "..\Minecraft.World\ConsoleSaveFileSplit.h"
|
#include "..\Minecraft.World\ConsoleSaveFileSplit.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -78,6 +86,462 @@ bool MinecraftServer::s_slowQueuePacketSent = false;
|
||||||
|
|
||||||
unordered_map<wstring, int> MinecraftServer::ironTimers;
|
unordered_map<wstring, int> MinecraftServer::ironTimers;
|
||||||
|
|
||||||
|
static bool ShouldUseDedicatedServerProperties()
|
||||||
|
{
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
return g_Win64DedicatedServer;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetDedicatedServerInt(Settings *settings, const wchar_t *key, int defaultValue)
|
||||||
|
{
|
||||||
|
return (ShouldUseDedicatedServerProperties() && settings != NULL) ? settings->getInt(key, defaultValue) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool GetDedicatedServerBool(Settings *settings, const wchar_t *key, bool defaultValue)
|
||||||
|
{
|
||||||
|
return (ShouldUseDedicatedServerProperties() && settings != NULL) ? settings->getBoolean(key, defaultValue) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wstring GetDedicatedServerString(Settings *settings, const wchar_t *key, const wstring &defaultValue)
|
||||||
|
{
|
||||||
|
return (ShouldUseDedicatedServerProperties() && settings != NULL) ? settings->getString(key, defaultValue) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrintConsoleLine(const wchar_t *prefix, const wstring &message)
|
||||||
|
{
|
||||||
|
wprintf(L"%ls%ls\n", prefix, message.c_str());
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParseIntValue(const wstring &text, int &value)
|
||||||
|
{
|
||||||
|
std::wistringstream stream(text);
|
||||||
|
stream >> value;
|
||||||
|
return !stream.fail() && stream.eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector<wstring> SplitConsoleCommand(const wstring &command)
|
||||||
|
{
|
||||||
|
vector<wstring> tokens;
|
||||||
|
std::wistringstream stream(command);
|
||||||
|
wstring token;
|
||||||
|
while (stream >> token)
|
||||||
|
{
|
||||||
|
tokens.push_back(token);
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wstring JoinConsoleCommandTokens(const vector<wstring> &tokens, size_t startIndex)
|
||||||
|
{
|
||||||
|
wstring joined;
|
||||||
|
for (size_t i = startIndex; i < tokens.size(); ++i)
|
||||||
|
{
|
||||||
|
if (!joined.empty()) joined += L" ";
|
||||||
|
joined += tokens[i];
|
||||||
|
}
|
||||||
|
return joined;
|
||||||
|
}
|
||||||
|
|
||||||
|
static shared_ptr<ServerPlayer> FindPlayerByName(PlayerList *playerList, const wstring &name)
|
||||||
|
{
|
||||||
|
if (playerList == NULL) return nullptr;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < playerList->players.size(); ++i)
|
||||||
|
{
|
||||||
|
shared_ptr<ServerPlayer> player = playerList->players[i];
|
||||||
|
if (player != NULL && equalsIgnoreCase(player->getName(), name))
|
||||||
|
{
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetAllLevelTimes(MinecraftServer *server, int value)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < server->levels.length; ++i)
|
||||||
|
{
|
||||||
|
if (server->levels[i] != NULL)
|
||||||
|
{
|
||||||
|
server->levels[i]->setDayTime(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ExecuteConsoleCommand(MinecraftServer *server, const wstring &rawCommand)
|
||||||
|
{
|
||||||
|
if (server == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wstring command = trimString(rawCommand);
|
||||||
|
if (command.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (command[0] == L'/')
|
||||||
|
{
|
||||||
|
command = trimString(command.substr(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<wstring> tokens = SplitConsoleCommand(command);
|
||||||
|
if (tokens.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const wstring action = toLower(tokens[0]);
|
||||||
|
PlayerList *playerList = server->getPlayers();
|
||||||
|
|
||||||
|
if (action == L"help" || action == L"?")
|
||||||
|
{
|
||||||
|
server->info(L"Commands: help, stop, list, say <message>, save-all, time <set day|night|ticks|add ticks>, weather <clear|rain|thunder> [seconds], tp <player> <target>, give <player> <itemId> [amount] [aux], enchant <player> <enchantId> [level], kill <player>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == L"stop")
|
||||||
|
{
|
||||||
|
server->info(L"Stopping server...");
|
||||||
|
MinecraftServer::HaltServer();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == L"list")
|
||||||
|
{
|
||||||
|
wstring playerNames = (playerList != NULL) ? playerList->getPlayerNames() : L"";
|
||||||
|
if (playerNames.empty()) playerNames = L"(none)";
|
||||||
|
server->info(L"Players (" + _toString((playerList != NULL) ? playerList->getPlayerCount() : 0) + L"): " + playerNames);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == L"say")
|
||||||
|
{
|
||||||
|
if (tokens.size() < 2)
|
||||||
|
{
|
||||||
|
server->warn(L"Usage: say <message>");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wstring message = L"[Server] " + JoinConsoleCommandTokens(tokens, 1);
|
||||||
|
if (playerList != NULL)
|
||||||
|
{
|
||||||
|
playerList->broadcastAll(shared_ptr<ChatPacket>(new ChatPacket(message)));
|
||||||
|
}
|
||||||
|
server->info(message);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == L"save-all")
|
||||||
|
{
|
||||||
|
if (playerList != NULL)
|
||||||
|
{
|
||||||
|
playerList->saveAll(NULL, false);
|
||||||
|
}
|
||||||
|
server->info(L"World saved.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == L"time")
|
||||||
|
{
|
||||||
|
if (tokens.size() < 2)
|
||||||
|
{
|
||||||
|
server->warn(L"Usage: time set <day|night|ticks> | time add <ticks>");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toLower(tokens[1]) == L"add")
|
||||||
|
{
|
||||||
|
if (tokens.size() < 3)
|
||||||
|
{
|
||||||
|
server->warn(L"Usage: time add <ticks>");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int delta = 0;
|
||||||
|
if (!TryParseIntValue(tokens[2], delta))
|
||||||
|
{
|
||||||
|
server->warn(L"Invalid tick value: " + tokens[2]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < server->levels.length; ++i)
|
||||||
|
{
|
||||||
|
if (server->levels[i] != NULL)
|
||||||
|
{
|
||||||
|
server->levels[i]->setDayTime(server->levels[i]->getDayTime() + delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server->info(L"Added " + _toString(delta) + L" ticks.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wstring timeValue = toLower(tokens[1]);
|
||||||
|
if (timeValue == L"set")
|
||||||
|
{
|
||||||
|
if (tokens.size() < 3)
|
||||||
|
{
|
||||||
|
server->warn(L"Usage: time set <day|night|ticks>");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
timeValue = toLower(tokens[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int targetTime = 0;
|
||||||
|
if (timeValue == L"day")
|
||||||
|
{
|
||||||
|
targetTime = 0;
|
||||||
|
}
|
||||||
|
else if (timeValue == L"night")
|
||||||
|
{
|
||||||
|
targetTime = 12500;
|
||||||
|
}
|
||||||
|
else if (!TryParseIntValue(timeValue, targetTime))
|
||||||
|
{
|
||||||
|
server->warn(L"Invalid time value: " + timeValue);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetAllLevelTimes(server, targetTime);
|
||||||
|
server->info(L"Time set to " + _toString(targetTime) + L".");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == L"weather")
|
||||||
|
{
|
||||||
|
if (tokens.size() < 2)
|
||||||
|
{
|
||||||
|
server->warn(L"Usage: weather <clear|rain|thunder> [seconds]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int durationSeconds = 600;
|
||||||
|
if (tokens.size() >= 3 && !TryParseIntValue(tokens[2], durationSeconds))
|
||||||
|
{
|
||||||
|
server->warn(L"Invalid duration: " + tokens[2]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server->levels[0] == NULL)
|
||||||
|
{
|
||||||
|
server->warn(L"The overworld is not loaded.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelData *levelData = server->levels[0]->getLevelData();
|
||||||
|
int duration = durationSeconds * SharedConstants::TICKS_PER_SECOND;
|
||||||
|
levelData->setRainTime(duration);
|
||||||
|
levelData->setThunderTime(duration);
|
||||||
|
|
||||||
|
wstring weather = toLower(tokens[1]);
|
||||||
|
if (weather == L"clear")
|
||||||
|
{
|
||||||
|
levelData->setRaining(false);
|
||||||
|
levelData->setThundering(false);
|
||||||
|
}
|
||||||
|
else if (weather == L"rain")
|
||||||
|
{
|
||||||
|
levelData->setRaining(true);
|
||||||
|
levelData->setThundering(false);
|
||||||
|
}
|
||||||
|
else if (weather == L"thunder")
|
||||||
|
{
|
||||||
|
levelData->setRaining(true);
|
||||||
|
levelData->setThundering(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
server->warn(L"Usage: weather <clear|rain|thunder> [seconds]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
server->info(L"Weather set to " + weather + L".");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == L"tp" || action == L"teleport")
|
||||||
|
{
|
||||||
|
if (tokens.size() < 3)
|
||||||
|
{
|
||||||
|
server->warn(L"Usage: tp <player> <target>");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<ServerPlayer> subject = FindPlayerByName(playerList, tokens[1]);
|
||||||
|
shared_ptr<ServerPlayer> destination = FindPlayerByName(playerList, tokens[2]);
|
||||||
|
if (subject == NULL)
|
||||||
|
{
|
||||||
|
server->warn(L"Unknown player: " + tokens[1]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (destination == NULL)
|
||||||
|
{
|
||||||
|
server->warn(L"Unknown player: " + tokens[2]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (subject->level->dimension->id != destination->level->dimension->id || !subject->isAlive())
|
||||||
|
{
|
||||||
|
server->warn(L"Teleport failed because the players are not in the same dimension or the source player is dead.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
subject->ride(nullptr);
|
||||||
|
subject->connection->teleport(destination->x, destination->y, destination->z, destination->yRot, destination->xRot);
|
||||||
|
server->info(L"Teleported " + subject->getName() + L" to " + destination->getName() + L".");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == L"give")
|
||||||
|
{
|
||||||
|
if (tokens.size() < 3)
|
||||||
|
{
|
||||||
|
server->warn(L"Usage: give <player> <itemId> [amount] [aux]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<ServerPlayer> player = FindPlayerByName(playerList, tokens[1]);
|
||||||
|
if (player == NULL)
|
||||||
|
{
|
||||||
|
server->warn(L"Unknown player: " + tokens[1]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int itemId = 0;
|
||||||
|
int amount = 1;
|
||||||
|
int aux = 0;
|
||||||
|
if (!TryParseIntValue(tokens[2], itemId))
|
||||||
|
{
|
||||||
|
server->warn(L"Invalid item id: " + tokens[2]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (tokens.size() >= 4 && !TryParseIntValue(tokens[3], amount))
|
||||||
|
{
|
||||||
|
server->warn(L"Invalid amount: " + tokens[3]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (tokens.size() >= 5 && !TryParseIntValue(tokens[4], aux))
|
||||||
|
{
|
||||||
|
server->warn(L"Invalid aux value: " + tokens[4]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (itemId <= 0 || Item::items[itemId] == NULL)
|
||||||
|
{
|
||||||
|
server->warn(L"Unknown item id: " + _toString(itemId));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amount <= 0)
|
||||||
|
{
|
||||||
|
server->warn(L"Amount must be positive.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<ItemInstance> itemInstance(new ItemInstance(itemId, amount, aux));
|
||||||
|
shared_ptr<ItemEntity> drop = player->drop(itemInstance);
|
||||||
|
if (drop != NULL)
|
||||||
|
{
|
||||||
|
drop->throwTime = 0;
|
||||||
|
}
|
||||||
|
server->info(L"Gave item " + _toString(itemId) + L" x" + _toString(amount) + L" to " + player->getName() + L".");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == L"enchant")
|
||||||
|
{
|
||||||
|
if (tokens.size() < 3)
|
||||||
|
{
|
||||||
|
server->warn(L"Usage: enchant <player> <enchantId> [level]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<ServerPlayer> player = FindPlayerByName(playerList, tokens[1]);
|
||||||
|
if (player == NULL)
|
||||||
|
{
|
||||||
|
server->warn(L"Unknown player: " + tokens[1]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int enchantmentId = 0;
|
||||||
|
int enchantmentLevel = 1;
|
||||||
|
if (!TryParseIntValue(tokens[2], enchantmentId))
|
||||||
|
{
|
||||||
|
server->warn(L"Invalid enchantment id: " + tokens[2]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (tokens.size() >= 4 && !TryParseIntValue(tokens[3], enchantmentLevel))
|
||||||
|
{
|
||||||
|
server->warn(L"Invalid enchantment level: " + tokens[3]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<ItemInstance> selectedItem = player->getSelectedItem();
|
||||||
|
if (selectedItem == NULL)
|
||||||
|
{
|
||||||
|
server->warn(L"The player is not holding an item.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Enchantment *enchantment = Enchantment::enchantments[enchantmentId];
|
||||||
|
if (enchantment == NULL)
|
||||||
|
{
|
||||||
|
server->warn(L"Unknown enchantment id: " + _toString(enchantmentId));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!enchantment->canEnchant(selectedItem))
|
||||||
|
{
|
||||||
|
server->warn(L"That enchantment cannot be applied to the selected item.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enchantmentLevel < enchantment->getMinLevel()) enchantmentLevel = enchantment->getMinLevel();
|
||||||
|
if (enchantmentLevel > enchantment->getMaxLevel()) enchantmentLevel = enchantment->getMaxLevel();
|
||||||
|
|
||||||
|
if (selectedItem->hasTag())
|
||||||
|
{
|
||||||
|
ListTag<CompoundTag> *enchantmentTags = selectedItem->getEnchantmentTags();
|
||||||
|
if (enchantmentTags != NULL)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < enchantmentTags->size(); i++)
|
||||||
|
{
|
||||||
|
int type = enchantmentTags->get(i)->getShort((wchar_t *)ItemInstance::TAG_ENCH_ID);
|
||||||
|
if (Enchantment::enchantments[type] != NULL && !Enchantment::enchantments[type]->isCompatibleWith(enchantment))
|
||||||
|
{
|
||||||
|
server->warn(L"That enchantment conflicts with an existing enchantment on the selected item.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedItem->enchant(enchantment, enchantmentLevel);
|
||||||
|
server->info(L"Enchanted " + player->getName() + L"'s held item with " + _toString(enchantmentId) + L" " + _toString(enchantmentLevel) + L".");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == L"kill")
|
||||||
|
{
|
||||||
|
if (tokens.size() < 2)
|
||||||
|
{
|
||||||
|
server->warn(L"Usage: kill <player>");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<ServerPlayer> player = FindPlayerByName(playerList, tokens[1]);
|
||||||
|
if (player == NULL)
|
||||||
|
{
|
||||||
|
server->warn(L"Unknown player: " + tokens[1]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
player->hurt(DamageSource::outOfWorld, 3.4e38f);
|
||||||
|
server->info(L"Killed " + player->getName() + L".");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
server->warn(L"Unknown command: " + command);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
MinecraftServer::MinecraftServer()
|
MinecraftServer::MinecraftServer()
|
||||||
{
|
{
|
||||||
// 4J - added initialisers
|
// 4J - added initialisers
|
||||||
|
|
@ -107,12 +571,14 @@ MinecraftServer::MinecraftServer()
|
||||||
forceGameType = false;
|
forceGameType = false;
|
||||||
|
|
||||||
commandDispatcher = new ServerCommandDispatcher();
|
commandDispatcher = new ServerCommandDispatcher();
|
||||||
|
InitializeCriticalSection(&m_consoleInputCS);
|
||||||
|
|
||||||
DispenserBootstrap::bootStrap();
|
DispenserBootstrap::bootStrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
MinecraftServer::~MinecraftServer()
|
MinecraftServer::~MinecraftServer()
|
||||||
{
|
{
|
||||||
|
DeleteCriticalSection(&m_consoleInputCS);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DWORD initSettings, bool findSeed)
|
bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DWORD initSettings, bool findSeed)
|
||||||
|
|
@ -150,6 +616,15 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW
|
||||||
#endif
|
#endif
|
||||||
settings = new Settings(new File(L"server.properties"));
|
settings = new Settings(new File(L"server.properties"));
|
||||||
|
|
||||||
|
app.SetGameHostOption(eGameHostOption_Difficulty, GetDedicatedServerInt(settings, L"difficulty", app.GetGameHostOption(eGameHostOption_Difficulty)));
|
||||||
|
app.SetGameHostOption(eGameHostOption_GameType, GetDedicatedServerInt(settings, L"gamemode", app.GetGameHostOption(eGameHostOption_GameType)));
|
||||||
|
app.SetGameHostOption(eGameHostOption_Structures, GetDedicatedServerBool(settings, L"generate-structures", app.GetGameHostOption(eGameHostOption_Structures) > 0) ? 1 : 0);
|
||||||
|
app.SetGameHostOption(eGameHostOption_BonusChest, GetDedicatedServerBool(settings, L"bonus-chest", app.GetGameHostOption(eGameHostOption_BonusChest) > 0) ? 1 : 0);
|
||||||
|
app.SetGameHostOption(eGameHostOption_PvP, GetDedicatedServerBool(settings, L"pvp", app.GetGameHostOption(eGameHostOption_PvP) > 0) ? 1 : 0);
|
||||||
|
app.SetGameHostOption(eGameHostOption_TrustPlayers, GetDedicatedServerBool(settings, L"trust-players", app.GetGameHostOption(eGameHostOption_TrustPlayers) > 0) ? 1 : 0);
|
||||||
|
app.SetGameHostOption(eGameHostOption_FireSpreads, GetDedicatedServerBool(settings, L"fire-spreads", app.GetGameHostOption(eGameHostOption_FireSpreads) > 0) ? 1 : 0);
|
||||||
|
app.SetGameHostOption(eGameHostOption_TNT, GetDedicatedServerBool(settings, L"tnt", app.GetGameHostOption(eGameHostOption_TNT) > 0) ? 1 : 0);
|
||||||
|
|
||||||
app.DebugPrintf("\n*** SERVER SETTINGS ***\n");
|
app.DebugPrintf("\n*** SERVER SETTINGS ***\n");
|
||||||
app.DebugPrintf("ServerSettings: host-friends-only is %s\n",(app.GetGameHostOption(eGameHostOption_FriendsOfFriends)>0)?"on":"off");
|
app.DebugPrintf("ServerSettings: host-friends-only is %s\n",(app.GetGameHostOption(eGameHostOption_FriendsOfFriends)>0)?"on":"off");
|
||||||
app.DebugPrintf("ServerSettings: game-type is %s\n",(app.GetGameHostOption(eGameHostOption_GameType)==0)?"Survival Mode":"Creative Mode");
|
app.DebugPrintf("ServerSettings: game-type is %s\n",(app.GetGameHostOption(eGameHostOption_GameType)==0)?"Survival Mode":"Creative Mode");
|
||||||
|
|
@ -167,13 +642,13 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW
|
||||||
//motd = settings->getString(L"motd", L"A Minecraft Server");
|
//motd = settings->getString(L"motd", L"A Minecraft Server");
|
||||||
//motd.replace('', '$');
|
//motd.replace('', '$');
|
||||||
|
|
||||||
setAnimals(settings->getBoolean(L"spawn-animals", true));
|
setAnimals(GetDedicatedServerBool(settings, L"spawn-animals", true));
|
||||||
setNpcsEnabled(settings->getBoolean(L"spawn-npcs", true));
|
setNpcsEnabled(GetDedicatedServerBool(settings, L"spawn-npcs", true));
|
||||||
setPvpAllowed(app.GetGameHostOption( eGameHostOption_PvP )>0?true:false); // settings->getBoolean(L"pvp", true);
|
setPvpAllowed(app.GetGameHostOption( eGameHostOption_PvP )>0?true:false);
|
||||||
|
|
||||||
// 4J Stu - We should never have hacked clients flying when they shouldn't be like the PC version, so enable flying always
|
// 4J Stu - We should never have hacked clients flying when they shouldn't be like the PC version, so enable flying always
|
||||||
// Fix for #46612 - TU5: Code: Multiplayer: A client can be banned for flying when accidentaly being blown by dynamite
|
// Fix for #46612 - TU5: Code: Multiplayer: A client can be banned for flying when accidentaly being blown by dynamite
|
||||||
setFlightAllowed(true); //settings->getBoolean(L"allow-flight", false);
|
setFlightAllowed(GetDedicatedServerBool(settings, L"allow-flight", true));
|
||||||
|
|
||||||
// 4J Stu - Enabling flight to stop it kicking us when we use it
|
// 4J Stu - Enabling flight to stop it kicking us when we use it
|
||||||
#ifdef _DEBUG_MENUS_ENABLED
|
#ifdef _DEBUG_MENUS_ENABLED
|
||||||
|
|
@ -219,8 +694,8 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW
|
||||||
|
|
||||||
__int64 levelNanoTime = System::nanoTime();
|
__int64 levelNanoTime = System::nanoTime();
|
||||||
|
|
||||||
wstring levelName = settings->getString(L"level-name", L"world");
|
wstring levelName = (initData && !initData->levelName.empty()) ? initData->levelName : GetDedicatedServerString(settings, L"level-name", L"world");
|
||||||
wstring levelTypeString;
|
wstring levelTypeString;
|
||||||
|
|
||||||
bool gameRuleUseFlatWorld = false;
|
bool gameRuleUseFlatWorld = false;
|
||||||
if(app.getLevelGenerationOptions() != NULL)
|
if(app.getLevelGenerationOptions() != NULL)
|
||||||
|
|
@ -229,11 +704,11 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW
|
||||||
}
|
}
|
||||||
if(gameRuleUseFlatWorld || app.GetGameHostOption(eGameHostOption_LevelType)>0)
|
if(gameRuleUseFlatWorld || app.GetGameHostOption(eGameHostOption_LevelType)>0)
|
||||||
{
|
{
|
||||||
levelTypeString = settings->getString(L"level-type", L"flat");
|
levelTypeString = GetDedicatedServerString(settings, L"level-type", L"flat");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
levelTypeString = settings->getString(L"level-type",L"default");
|
levelTypeString = GetDedicatedServerString(settings, L"level-type",L"default");
|
||||||
}
|
}
|
||||||
|
|
||||||
LevelType *pLevelType = LevelType::getLevelType(levelTypeString);
|
LevelType *pLevelType = LevelType::getLevelType(levelTypeString);
|
||||||
|
|
@ -254,7 +729,7 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
setMaxBuildHeight(settings->getInt(L"max-build-height", Level::maxBuildHeight));
|
setMaxBuildHeight(GetDedicatedServerInt(settings, L"max-build-height", Level::maxBuildHeight));
|
||||||
setMaxBuildHeight(((getMaxBuildHeight() + 8) / 16) * 16);
|
setMaxBuildHeight(((getMaxBuildHeight() + 8) / 16) * 16);
|
||||||
setMaxBuildHeight(Mth::clamp(getMaxBuildHeight(), 64, Level::maxBuildHeight));
|
setMaxBuildHeight(Mth::clamp(getMaxBuildHeight(), 64, Level::maxBuildHeight));
|
||||||
//settings->setProperty(L"max-build-height", maxBuildHeight);
|
//settings->setProperty(L"max-build-height", maxBuildHeight);
|
||||||
|
|
@ -403,7 +878,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
|
||||||
// 4J TODO - free levels here if there are already some?
|
// 4J TODO - free levels here if there are already some?
|
||||||
levels = ServerLevelArray(3);
|
levels = ServerLevelArray(3);
|
||||||
|
|
||||||
int gameTypeId = settings->getInt(L"gamemode", app.GetGameHostOption(eGameHostOption_GameType));//LevelSettings::GAMETYPE_SURVIVAL);
|
int gameTypeId = GetDedicatedServerInt(settings, L"gamemode", app.GetGameHostOption(eGameHostOption_GameType));//LevelSettings::GAMETYPE_SURVIVAL);
|
||||||
GameType *gameType = LevelSettings::validateGameType(gameTypeId);
|
GameType *gameType = LevelSettings::validateGameType(gameTypeId);
|
||||||
app.DebugPrintf("Default game type: %d\n" , gameTypeId);
|
app.DebugPrintf("Default game type: %d\n" , gameTypeId);
|
||||||
|
|
||||||
|
|
@ -502,7 +977,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
|
||||||
#if DEBUG_SERVER_DONT_SPAWN_MOBS
|
#if DEBUG_SERVER_DONT_SPAWN_MOBS
|
||||||
levels[i]->setSpawnSettings(false, false);
|
levels[i]->setSpawnSettings(false, false);
|
||||||
#else
|
#else
|
||||||
levels[i]->setSpawnSettings(settings->getBoolean(L"spawn-monsters", true), animals);
|
levels[i]->setSpawnSettings(GetDedicatedServerBool(settings, L"spawn-monsters", true), animals);
|
||||||
#endif
|
#endif
|
||||||
levels[i]->getLevelData()->setGameType(gameType);
|
levels[i]->getLevelData()->setGameType(gameType);
|
||||||
|
|
||||||
|
|
@ -590,7 +1065,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
|
||||||
for (int i = 0; i < levels.length ; i++)
|
for (int i = 0; i < levels.length ; i++)
|
||||||
{
|
{
|
||||||
// logger.info("Preparing start region for level " + i);
|
// logger.info("Preparing start region for level " + i);
|
||||||
if (i == 0 || settings->getBoolean(L"allow-nether", true))
|
if (i == 0 || GetDedicatedServerBool(settings, L"allow-nether", true))
|
||||||
{
|
{
|
||||||
ServerLevel *level = levels[i];
|
ServerLevel *level = levels[i];
|
||||||
if(levelChunksNeedConverted)
|
if(levelChunksNeedConverted)
|
||||||
|
|
@ -1332,7 +1807,7 @@ void MinecraftServer::run(__int64 seed, void *lpParameter)
|
||||||
MinecraftServer::setTimeOfDayAtEndOfTick = false;
|
MinecraftServer::setTimeOfDayAtEndOfTick = false;
|
||||||
for (unsigned int i = 0; i < levels.length; i++)
|
for (unsigned int i = 0; i < levels.length; i++)
|
||||||
{
|
{
|
||||||
if (i == 0 || settings->getBoolean(L"allow-nether", true))
|
if (i == 0 || GetDedicatedServerBool(settings, L"allow-nether", true))
|
||||||
{
|
{
|
||||||
ServerLevel *level = levels[i];
|
ServerLevel *level = levels[i];
|
||||||
level->setDayTime( MinecraftServer::setTimeOfDay );
|
level->setDayTime( MinecraftServer::setTimeOfDay );
|
||||||
|
|
@ -1707,17 +2182,23 @@ void MinecraftServer::tick()
|
||||||
|
|
||||||
void MinecraftServer::handleConsoleInput(const wstring& msg, ConsoleInputSource *source)
|
void MinecraftServer::handleConsoleInput(const wstring& msg, ConsoleInputSource *source)
|
||||||
{
|
{
|
||||||
|
EnterCriticalSection(&m_consoleInputCS);
|
||||||
consoleInput.push_back(new ConsoleInput(msg, source));
|
consoleInput.push_back(new ConsoleInput(msg, source));
|
||||||
|
LeaveCriticalSection(&m_consoleInputCS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftServer::handleConsoleInputs()
|
void MinecraftServer::handleConsoleInputs()
|
||||||
{
|
{
|
||||||
while (consoleInput.size() > 0)
|
vector<ConsoleInput *> pendingInputs;
|
||||||
|
EnterCriticalSection(&m_consoleInputCS);
|
||||||
|
pendingInputs.swap(consoleInput);
|
||||||
|
LeaveCriticalSection(&m_consoleInputCS);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < pendingInputs.size(); ++i)
|
||||||
{
|
{
|
||||||
AUTO_VAR(it, consoleInput.begin());
|
ConsoleInput *input = pendingInputs[i];
|
||||||
ConsoleInput *input = *it;
|
ExecuteConsoleCommand(this, input->msg);
|
||||||
consoleInput.erase(it);
|
delete input;
|
||||||
// commands->handleCommand(input); // 4J - removed - TODO - do we want equivalent of console commands?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1750,10 +2231,12 @@ File *MinecraftServer::getFile(const wstring& name)
|
||||||
|
|
||||||
void MinecraftServer::info(const wstring& string)
|
void MinecraftServer::info(const wstring& string)
|
||||||
{
|
{
|
||||||
|
PrintConsoleLine(L"[INFO] ", string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftServer::warn(const wstring& string)
|
void MinecraftServer::warn(const wstring& string)
|
||||||
{
|
{
|
||||||
|
PrintConsoleLine(L"[WARN] ", string);
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring MinecraftServer::getConsoleName()
|
wstring MinecraftServer::getConsoleName()
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ typedef struct _NetworkGameInitData
|
||||||
unsigned int xzSize;
|
unsigned int xzSize;
|
||||||
unsigned char hellScale;
|
unsigned char hellScale;
|
||||||
ESavePlatform savePlatform;
|
ESavePlatform savePlatform;
|
||||||
|
wstring levelName;
|
||||||
|
|
||||||
_NetworkGameInitData()
|
_NetworkGameInitData()
|
||||||
{
|
{
|
||||||
|
|
@ -103,6 +104,7 @@ private:
|
||||||
// vector<Tickable *> tickables = new ArrayList<Tickable>(); // 4J - removed
|
// vector<Tickable *> tickables = new ArrayList<Tickable>(); // 4J - removed
|
||||||
CommandDispatcher *commandDispatcher;
|
CommandDispatcher *commandDispatcher;
|
||||||
vector<ConsoleInput *> consoleInput; // 4J - was synchronizedList - TODO - investigate
|
vector<ConsoleInput *> consoleInput; // 4J - was synchronizedList - TODO - investigate
|
||||||
|
CRITICAL_SECTION m_consoleInputCS;
|
||||||
public:
|
public:
|
||||||
bool onlineMode;
|
bool onlineMode;
|
||||||
bool animals;
|
bool animals;
|
||||||
|
|
|
||||||
|
|
@ -370,7 +370,9 @@ bool MultiPlayerGameMode::useItemOn(shared_ptr<Player> player, Level *level, sha
|
||||||
// are meant to be directly caused by this. If we don't do this, then the sounds never happen as the tile's use method is only called on the
|
// are meant to be directly caused by this. If we don't do this, then the sounds never happen as the tile's use method is only called on the
|
||||||
// server, and that won't allow any sounds that are directly made, or broadcast back level events to us that would make the sound, since we are
|
// server, and that won't allow any sounds that are directly made, or broadcast back level events to us that would make the sound, since we are
|
||||||
// the source of the event.
|
// the source of the event.
|
||||||
if( ( t > 0 ) && ( !bTestUseOnly ) && player->isAllowedToUse(Tile::tiles[t]) )
|
// ---------------------------------------------------------------------------------
|
||||||
|
// Only call soundOnly version if we didn't already call the tile's use method above
|
||||||
|
if( !didSomething && ( t > 0 ) && ( !bTestUseOnly ) && player->isAllowedToUse(Tile::tiles[t]) )
|
||||||
{
|
{
|
||||||
Tile::tiles[t]->use(level, x, y, z, player, face, clickX, clickY, clickZ, true);
|
Tile::tiles[t]->use(level, x, y, z, player, face, clickX, clickY, clickZ, true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,12 @@ PlayerList::PlayerList(MinecraftServer *server)
|
||||||
|
|
||||||
//int viewDistance = server->settings->getInt(L"view-distance", 10);
|
//int viewDistance = server->settings->getInt(L"view-distance", 10);
|
||||||
|
|
||||||
maxPlayers = server->settings->getInt(L"max-players", 20);
|
|
||||||
doWhiteList = false;
|
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
maxPlayers = MINECRAFT_NET_MAX_PLAYERS;
|
maxPlayers = MINECRAFT_NET_MAX_PLAYERS;
|
||||||
#else
|
#else
|
||||||
maxPlayers = server->settings->getInt(L"max-players", 20);
|
maxPlayers = server->settings->getInt(L"max-players", 20);
|
||||||
#endif
|
#endif
|
||||||
|
doWhiteList = false;
|
||||||
InitializeCriticalSection(&m_kickPlayersCS);
|
InitializeCriticalSection(&m_kickPlayersCS);
|
||||||
InitializeCriticalSection(&m_closePlayersCS);
|
InitializeCriticalSection(&m_closePlayersCS);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,13 +110,13 @@ void Screen::updateEvents()
|
||||||
// Poll mouse button state and dispatch click/release events
|
// Poll mouse button state and dispatch click/release events
|
||||||
for (int btn = 0; btn < 3; btn++)
|
for (int btn = 0; btn < 3; btn++)
|
||||||
{
|
{
|
||||||
if (KMInput.ConsumeMousePress(btn))
|
if (g_KBMInput.IsMouseButtonPressed(btn))
|
||||||
{
|
{
|
||||||
int xm = Mouse::getX() * width / minecraft->width;
|
int xm = Mouse::getX() * width / minecraft->width;
|
||||||
int ym = height - Mouse::getY() * height / minecraft->height - 1;
|
int ym = height - Mouse::getY() * height / minecraft->height - 1;
|
||||||
mouseClicked(xm, ym, btn);
|
mouseClicked(xm, ym, btn);
|
||||||
}
|
}
|
||||||
if (KMInput.ConsumeMouseRelease(btn))
|
if (g_KBMInput.IsMouseButtonReleased(btn))
|
||||||
{
|
{
|
||||||
int xm = Mouse::getX() * width / minecraft->width;
|
int xm = Mouse::getX() * width / minecraft->width;
|
||||||
int ym = height - Mouse::getY() * height / minecraft->height - 1;
|
int ym = height - Mouse::getY() * height / minecraft->height - 1;
|
||||||
|
|
@ -127,7 +127,7 @@ void Screen::updateEvents()
|
||||||
// Poll keyboard events
|
// Poll keyboard events
|
||||||
for (int vk = 0; vk < 256; vk++)
|
for (int vk = 0; vk < 256; vk++)
|
||||||
{
|
{
|
||||||
if (KMInput.ConsumeKeyPress(vk))
|
if (g_KBMInput.IsKeyPressed(vk))
|
||||||
{
|
{
|
||||||
// Map Windows virtual key to the Keyboard constants used by Screen::keyPressed
|
// Map Windows virtual key to the Keyboard constants used by Screen::keyPressed
|
||||||
int mappedKey = -1;
|
int mappedKey = -1;
|
||||||
|
|
@ -144,7 +144,7 @@ void Screen::updateEvents()
|
||||||
else if (vk >= 'A' && vk <= 'Z')
|
else if (vk >= 'A' && vk <= 'Z')
|
||||||
{
|
{
|
||||||
ch = (wchar_t)(vk - 'A' + L'a');
|
ch = (wchar_t)(vk - 'A' + L'a');
|
||||||
if (KMInput.IsKeyDown(VK_SHIFT)) ch = (wchar_t)vk;
|
if (g_KBMInput.IsKeyDown(VK_LSHIFT) || g_KBMInput.IsKeyDown(VK_RSHIFT)) ch = (wchar_t)vk;
|
||||||
}
|
}
|
||||||
else if (vk >= '0' && vk <= '9') ch = (wchar_t)vk;
|
else if (vk >= '0' && vk <= '9') ch = (wchar_t)vk;
|
||||||
else if (vk == VK_SPACE) ch = L' ';
|
else if (vk == VK_SPACE) ch = L' ';
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,90 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
#include "Minecraft.World/File.h"
|
||||||
#include "Minecraft.World/StringHelpers.h"
|
#include "Minecraft.World/StringHelpers.h"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
static wstring ParsePropertyText(const string &text)
|
||||||
|
{
|
||||||
|
return trimString(convStringToWstring(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParseBoolean(const wstring &text, bool defaultValue)
|
||||||
|
{
|
||||||
|
wstring lowered = toLower(trimString(text));
|
||||||
|
if (lowered == L"true" || lowered == L"1" || lowered == L"yes" || lowered == L"on")
|
||||||
|
return true;
|
||||||
|
if (lowered == L"false" || lowered == L"0" || lowered == L"no" || lowered == L"off")
|
||||||
|
return false;
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
// 4J - TODO - serialise/deserialise from file
|
|
||||||
Settings::Settings(File *file)
|
Settings::Settings(File *file)
|
||||||
{
|
{
|
||||||
|
if (file != NULL)
|
||||||
|
{
|
||||||
|
filePath = file->getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePath.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::ifstream stream(wstringtofilename(filePath), std::ios::in | std::ios::binary);
|
||||||
|
if (!stream.is_open())
|
||||||
|
return;
|
||||||
|
|
||||||
|
string line;
|
||||||
|
while (std::getline(stream, line))
|
||||||
|
{
|
||||||
|
if (!line.empty() && line[line.size() - 1] == '\r')
|
||||||
|
line.erase(line.size() - 1);
|
||||||
|
|
||||||
|
if (line.size() >= 3 &&
|
||||||
|
(unsigned char)line[0] == 0xEF &&
|
||||||
|
(unsigned char)line[1] == 0xBB &&
|
||||||
|
(unsigned char)line[2] == 0xBF)
|
||||||
|
{
|
||||||
|
line.erase(0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t commentPos = line.find_first_of("#;");
|
||||||
|
if (commentPos != string::npos && line.find_first_not_of(" \t") == commentPos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
size_t separatorPos = line.find('=');
|
||||||
|
if (separatorPos == string::npos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wstring key = ParsePropertyText(line.substr(0, separatorPos));
|
||||||
|
if (key.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wstring value = ParsePropertyText(line.substr(separatorPos + 1));
|
||||||
|
properties[key] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::generateNewProperties()
|
void Settings::generateNewProperties()
|
||||||
{
|
{
|
||||||
|
saveProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::saveProperties()
|
void Settings::saveProperties()
|
||||||
{
|
{
|
||||||
|
if (filePath.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::ofstream stream(wstringtofilename(filePath), std::ios::out | std::ios::binary | std::ios::trunc);
|
||||||
|
if (!stream.is_open())
|
||||||
|
return;
|
||||||
|
|
||||||
|
stream << "# MinecraftConsoles dedicated server properties\r\n";
|
||||||
|
for (unordered_map<wstring, wstring>::const_iterator it = properties.begin(); it != properties.end(); ++it)
|
||||||
|
{
|
||||||
|
string key = string(wstringtochararray(it->first));
|
||||||
|
string value = string(wstringtochararray(it->second));
|
||||||
|
stream << key << "=" << value << "\r\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring Settings::getString(const wstring& key, const wstring& defaultValue)
|
wstring Settings::getString(const wstring& key, const wstring& defaultValue)
|
||||||
|
|
@ -39,17 +111,17 @@ bool Settings::getBoolean(const wstring& key, bool defaultValue)
|
||||||
{
|
{
|
||||||
if(properties.find(key) == properties.end())
|
if(properties.find(key) == properties.end())
|
||||||
{
|
{
|
||||||
properties[key] = _toString<bool>(defaultValue);
|
properties[key] = defaultValue ? L"true" : L"false";
|
||||||
saveProperties();
|
saveProperties();
|
||||||
}
|
}
|
||||||
MemSect(35);
|
MemSect(35);
|
||||||
bool retval = _fromString<bool>(properties[key]);
|
bool retval = TryParseBoolean(properties[key], defaultValue);
|
||||||
MemSect(0);
|
MemSect(0);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setBooleanAndSave(const wstring& key, bool value)
|
void Settings::setBooleanAndSave(const wstring& key, bool value)
|
||||||
{
|
{
|
||||||
properties[key] = _toString<bool>(value);
|
properties[key] = value ? L"true" : L"false";
|
||||||
saveProperties();
|
saveProperties();
|
||||||
}
|
}
|
||||||
|
|
@ -7,8 +7,8 @@ class Settings
|
||||||
// public static Logger logger = Logger.getLogger("Minecraft");
|
// public static Logger logger = Logger.getLogger("Minecraft");
|
||||||
// private Properties properties = new Properties();
|
// private Properties properties = new Properties();
|
||||||
private:
|
private:
|
||||||
unordered_map<wstring,wstring> properties; // 4J - TODO was Properties type, will need to implement something we can serialise/deserialise too
|
unordered_map<wstring,wstring> properties;
|
||||||
//File *file;
|
wstring filePath;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Settings(File *file);
|
Settings(File *file);
|
||||||
|
|
@ -18,4 +18,4 @@ public:
|
||||||
int getInt(const wstring& key, int defaultValue);
|
int getInt(const wstring& key, int defaultValue);
|
||||||
bool getBoolean(const wstring& key, bool defaultValue);
|
bool getBoolean(const wstring& key, bool defaultValue);
|
||||||
void setBooleanAndSave(const wstring& key, bool value);
|
void setBooleanAndSave(const wstring& key, bool value);
|
||||||
};
|
};
|
||||||
|
|
@ -424,12 +424,109 @@ void Textures::bindTextureLayers(ResourceLocation *resource)
|
||||||
{
|
{
|
||||||
assert(resource->isPreloaded());
|
assert(resource->isPreloaded());
|
||||||
|
|
||||||
|
// Hack: 4JLibs on Windows does not currently reproduce Minecraft's layered horse texture path reliably.
|
||||||
|
// Merge the layers on the CPU and bind the cached result as a normal single texture instead.
|
||||||
|
wstring cacheKey = L"%layered%";
|
||||||
int layers = resource->getTextureCount();
|
int layers = resource->getTextureCount();
|
||||||
|
|
||||||
for( int i = 0; i < layers; i++ )
|
for( int i = 0; i < layers; i++ )
|
||||||
{
|
{
|
||||||
RenderManager.TextureBind(loadTexture(resource->getTexture(i)));
|
cacheKey += std::to_wstring(resource->getTexture(i));
|
||||||
|
cacheKey += L"/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int id = -1;
|
||||||
|
bool inMap = ( idMap.find(cacheKey) != idMap.end() );
|
||||||
|
if( inMap )
|
||||||
|
{
|
||||||
|
id = idMap[cacheKey];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Cache by layer signature so the merge cost is only paid once per horse texture combination.
|
||||||
|
intArray mergedPixels;
|
||||||
|
int mergedWidth = 0;
|
||||||
|
int mergedHeight = 0;
|
||||||
|
bool hasMergedPixels = false;
|
||||||
|
|
||||||
|
for( int i = 0; i < layers; i++ )
|
||||||
|
{
|
||||||
|
TEXTURE_NAME textureName = resource->getTexture(i);
|
||||||
|
if( textureName == (_TEXTURE_NAME)-1 )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wstring resourceName = wstring(preLoaded[textureName]) + L".png";
|
||||||
|
BufferedImage *image = readImage(textureName, resourceName);
|
||||||
|
if( image == NULL )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = image->getWidth();
|
||||||
|
int height = image->getHeight();
|
||||||
|
intArray layerPixels = loadTexturePixels(image);
|
||||||
|
delete image;
|
||||||
|
|
||||||
|
if( !hasMergedPixels )
|
||||||
|
{
|
||||||
|
mergedWidth = width;
|
||||||
|
mergedHeight = height;
|
||||||
|
mergedPixels = intArray(width * height);
|
||||||
|
memcpy(mergedPixels.data, layerPixels.data, width * height * sizeof(int));
|
||||||
|
hasMergedPixels = true;
|
||||||
|
}
|
||||||
|
else if( width == mergedWidth && height == mergedHeight )
|
||||||
|
{
|
||||||
|
for( int p = 0; p < width * height; p++ )
|
||||||
|
{
|
||||||
|
int dst = mergedPixels[p];
|
||||||
|
int src = layerPixels[p];
|
||||||
|
|
||||||
|
float srcAlpha = ((src >> 24) & 0xff) / 255.0f;
|
||||||
|
if( srcAlpha <= 0.0f )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float dstAlpha = ((dst >> 24) & 0xff) / 255.0f;
|
||||||
|
float outAlpha = srcAlpha + dstAlpha * (1.0f - srcAlpha);
|
||||||
|
if( outAlpha <= 0.0f )
|
||||||
|
{
|
||||||
|
mergedPixels[p] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float srcFactor = srcAlpha / outAlpha;
|
||||||
|
float dstFactor = (dstAlpha * (1.0f - srcAlpha)) / outAlpha;
|
||||||
|
|
||||||
|
int outA = (int)(outAlpha * 255.0f + 0.5f);
|
||||||
|
int outR = (int)((((src >> 16) & 0xff) * srcFactor) + (((dst >> 16) & 0xff) * dstFactor) + 0.5f);
|
||||||
|
int outG = (int)((((src >> 8) & 0xff) * srcFactor) + (((dst >> 8) & 0xff) * dstFactor) + 0.5f);
|
||||||
|
int outB = (int)(((src & 0xff) * srcFactor) + ((dst & 0xff) * dstFactor) + 0.5f);
|
||||||
|
mergedPixels[p] = (outA << 24) | (outR << 16) | (outG << 8) | outB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] layerPixels.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( hasMergedPixels )
|
||||||
|
{
|
||||||
|
BufferedImage *mergedImage = new BufferedImage(mergedWidth, mergedHeight, BufferedImage::TYPE_INT_ARGB);
|
||||||
|
memcpy(mergedImage->getData(), mergedPixels.data, mergedWidth * mergedHeight * sizeof(int));
|
||||||
|
delete[] mergedPixels.data;
|
||||||
|
id = getTexture(mergedImage, C4JRender::TEXTURE_FORMAT_RxGyBzAw, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
idMap[cacheKey] = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderManager.TextureBind(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Textures::bind(int id)
|
void Textures::bind(int id)
|
||||||
|
|
|
||||||
|
|
@ -3,117 +3,161 @@
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
|
|
||||||
#include "KeyboardMouseInput.h"
|
#include "KeyboardMouseInput.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
KeyboardMouseInput KMInput;
|
KeyboardMouseInput g_KBMInput;
|
||||||
|
|
||||||
KeyboardMouseInput::KeyboardMouseInput()
|
extern HWND g_hWnd;
|
||||||
: m_mouseDeltaXAccum(0.0f)
|
|
||||||
, m_mouseDeltaYAccum(0.0f)
|
// Forward declaration
|
||||||
, m_scrollDeltaAccum(0)
|
static void ClipCursorToWindow(HWND hWnd);
|
||||||
, m_captured(false)
|
|
||||||
, m_hWnd(NULL)
|
void KeyboardMouseInput::Init()
|
||||||
, m_initialized(false)
|
|
||||||
, m_mouseX(0)
|
|
||||||
, m_mouseY(0)
|
|
||||||
{
|
{
|
||||||
memset(m_keyState, 0, sizeof(m_keyState));
|
memset(m_keyDown, 0, sizeof(m_keyDown));
|
||||||
memset(m_keyStatePrev, 0, sizeof(m_keyStatePrev));
|
memset(m_keyDownPrev, 0, sizeof(m_keyDownPrev));
|
||||||
memset(m_mouseButtons, 0, sizeof(m_mouseButtons));
|
|
||||||
memset(m_mouseButtonsPrev, 0, sizeof(m_mouseButtonsPrev));
|
|
||||||
memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum));
|
memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum));
|
||||||
memset(m_mousePressedAccum, 0, sizeof(m_mousePressedAccum));
|
memset(m_keyReleasedAccum, 0, sizeof(m_keyReleasedAccum));
|
||||||
memset(m_mouseReleasedAccum, 0, sizeof(m_mouseReleasedAccum));
|
memset(m_keyPressed, 0, sizeof(m_keyPressed));
|
||||||
}
|
memset(m_keyReleased, 0, sizeof(m_keyReleased));
|
||||||
|
memset(m_mouseButtonDown, 0, sizeof(m_mouseButtonDown));
|
||||||
|
memset(m_mouseButtonDownPrev, 0, sizeof(m_mouseButtonDownPrev));
|
||||||
|
memset(m_mouseBtnPressedAccum, 0, sizeof(m_mouseBtnPressedAccum));
|
||||||
|
memset(m_mouseBtnReleasedAccum, 0, sizeof(m_mouseBtnReleasedAccum));
|
||||||
|
memset(m_mouseBtnPressed, 0, sizeof(m_mouseBtnPressed));
|
||||||
|
memset(m_mouseBtnReleased, 0, sizeof(m_mouseBtnReleased));
|
||||||
|
m_mouseX = 0;
|
||||||
|
m_mouseY = 0;
|
||||||
|
m_mouseDeltaX = 0;
|
||||||
|
m_mouseDeltaY = 0;
|
||||||
|
m_mouseDeltaAccumX = 0;
|
||||||
|
m_mouseDeltaAccumY = 0;
|
||||||
|
m_mouseWheelAccum = 0;
|
||||||
|
m_mouseWheelConsumed = false;
|
||||||
|
m_mouseGrabbed = false;
|
||||||
|
m_cursorHiddenForUI = false;
|
||||||
|
m_windowFocused = true;
|
||||||
|
m_hasInput = false;
|
||||||
|
m_kbmActive = true;
|
||||||
|
m_screenWantsCursorHidden = false;
|
||||||
|
|
||||||
KeyboardMouseInput::~KeyboardMouseInput()
|
|
||||||
{
|
|
||||||
if (m_captured)
|
|
||||||
{
|
|
||||||
SetCapture(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyboardMouseInput::Init(HWND hWnd)
|
|
||||||
{
|
|
||||||
m_hWnd = hWnd;
|
|
||||||
m_initialized = true;
|
|
||||||
|
|
||||||
// Register for raw mouse input
|
|
||||||
RAWINPUTDEVICE rid;
|
RAWINPUTDEVICE rid;
|
||||||
rid.usUsagePage = HID_USAGE_PAGE_GENERIC;
|
rid.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
|
||||||
rid.usUsage = HID_USAGE_GENERIC_MOUSE;
|
rid.usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE
|
||||||
rid.dwFlags = 0;
|
rid.dwFlags = 0;
|
||||||
rid.hwndTarget = hWnd;
|
rid.hwndTarget = g_hWnd;
|
||||||
RegisterRawInputDevices(&rid, 1, sizeof(rid));
|
RegisterRawInputDevices(&rid, 1, sizeof(rid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyboardMouseInput::ClearAllState()
|
||||||
|
{
|
||||||
|
memset(m_keyDown, 0, sizeof(m_keyDown));
|
||||||
|
memset(m_keyDownPrev, 0, sizeof(m_keyDownPrev));
|
||||||
|
memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum));
|
||||||
|
memset(m_keyReleasedAccum, 0, sizeof(m_keyReleasedAccum));
|
||||||
|
memset(m_keyPressed, 0, sizeof(m_keyPressed));
|
||||||
|
memset(m_keyReleased, 0, sizeof(m_keyReleased));
|
||||||
|
memset(m_mouseButtonDown, 0, sizeof(m_mouseButtonDown));
|
||||||
|
memset(m_mouseButtonDownPrev, 0, sizeof(m_mouseButtonDownPrev));
|
||||||
|
memset(m_mouseBtnPressedAccum, 0, sizeof(m_mouseBtnPressedAccum));
|
||||||
|
memset(m_mouseBtnReleasedAccum, 0, sizeof(m_mouseBtnReleasedAccum));
|
||||||
|
memset(m_mouseBtnPressed, 0, sizeof(m_mouseBtnPressed));
|
||||||
|
memset(m_mouseBtnReleased, 0, sizeof(m_mouseBtnReleased));
|
||||||
|
m_mouseDeltaX = 0;
|
||||||
|
m_mouseDeltaY = 0;
|
||||||
|
m_mouseDeltaAccumX = 0;
|
||||||
|
m_mouseDeltaAccumY = 0;
|
||||||
|
m_mouseWheelAccum = 0;
|
||||||
|
m_mouseWheelConsumed = false;
|
||||||
|
}
|
||||||
|
|
||||||
void KeyboardMouseInput::Tick()
|
void KeyboardMouseInput::Tick()
|
||||||
{
|
{
|
||||||
// Keep cursor pinned to center while captured
|
memcpy(m_keyDownPrev, m_keyDown, sizeof(m_keyDown));
|
||||||
if (m_captured)
|
memcpy(m_mouseButtonDownPrev, m_mouseButtonDown, sizeof(m_mouseButtonDown));
|
||||||
CenterCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyboardMouseInput::EndFrame()
|
memcpy(m_keyPressed, m_keyPressedAccum, sizeof(m_keyPressedAccum));
|
||||||
{
|
memcpy(m_keyReleased, m_keyReleasedAccum, sizeof(m_keyReleasedAccum));
|
||||||
// Advance previous state for next frame's edge detection.
|
memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum));
|
||||||
// Must be called AFTER all per-frame consumers have read IsKeyPressed/Released etc.
|
memset(m_keyReleasedAccum, 0, sizeof(m_keyReleasedAccum));
|
||||||
memcpy(m_keyStatePrev, m_keyState, sizeof(m_keyState));
|
|
||||||
memcpy(m_mouseButtonsPrev, m_mouseButtons, sizeof(m_mouseButtons));
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyboardMouseInput::OnKeyDown(WPARAM vk)
|
memcpy(m_mouseBtnPressed, m_mouseBtnPressedAccum, sizeof(m_mouseBtnPressedAccum));
|
||||||
{
|
memcpy(m_mouseBtnReleased, m_mouseBtnReleasedAccum, sizeof(m_mouseBtnReleasedAccum));
|
||||||
if (vk < 256)
|
memset(m_mouseBtnPressedAccum, 0, sizeof(m_mouseBtnPressedAccum));
|
||||||
|
memset(m_mouseBtnReleasedAccum, 0, sizeof(m_mouseBtnReleasedAccum));
|
||||||
|
|
||||||
|
m_mouseDeltaX = m_mouseDeltaAccumX;
|
||||||
|
m_mouseDeltaY = m_mouseDeltaAccumY;
|
||||||
|
m_mouseDeltaAccumX = 0;
|
||||||
|
m_mouseDeltaAccumY = 0;
|
||||||
|
m_mouseWheelConsumed = false;
|
||||||
|
|
||||||
|
m_hasInput = (m_mouseDeltaX != 0 || m_mouseDeltaY != 0 || m_mouseWheelAccum != 0);
|
||||||
|
if (!m_hasInput)
|
||||||
{
|
{
|
||||||
if (!m_keyState[vk]) m_keyPressedAccum[vk] = true;
|
for (int i = 0; i < MAX_KEYS; i++)
|
||||||
m_keyState[vk] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyboardMouseInput::OnKeyUp(WPARAM vk)
|
|
||||||
{
|
|
||||||
if (vk < 256)
|
|
||||||
{
|
|
||||||
m_keyState[vk] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyboardMouseInput::OnRawMouseInput(LPARAM lParam)
|
|
||||||
{
|
|
||||||
if (!m_captured) return;
|
|
||||||
|
|
||||||
UINT dwSize = 0;
|
|
||||||
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
|
|
||||||
|
|
||||||
BYTE* lpb = (BYTE*)alloca(dwSize);
|
|
||||||
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RAWINPUT* raw = (RAWINPUT*)lpb;
|
|
||||||
if (raw->header.dwType == RIM_TYPEMOUSE)
|
|
||||||
{
|
|
||||||
if (raw->data.mouse.usFlags == MOUSE_MOVE_RELATIVE)
|
|
||||||
{
|
{
|
||||||
m_mouseDeltaXAccum += (float)raw->data.mouse.lLastX;
|
if (m_keyDown[i]) { m_hasInput = true; break; }
|
||||||
m_mouseDeltaYAccum += (float)raw->data.mouse.lLastY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!m_hasInput)
|
||||||
|
|
||||||
void KeyboardMouseInput::OnMouseButton(int button, bool down)
|
|
||||||
{
|
|
||||||
if (button >= 0 && button < 3)
|
|
||||||
{
|
{
|
||||||
if (down && !m_mouseButtons[button]) m_mousePressedAccum[button] = true;
|
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++)
|
||||||
if (!down && m_mouseButtons[button]) m_mouseReleasedAccum[button] = true;
|
{
|
||||||
m_mouseButtons[button] = down;
|
if (m_mouseButtonDown[i]) { m_hasInput = true; break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_mouseGrabbed || m_cursorHiddenForUI) && g_hWnd)
|
||||||
|
{
|
||||||
|
RECT rc;
|
||||||
|
GetClientRect(g_hWnd, &rc);
|
||||||
|
POINT center;
|
||||||
|
center.x = (rc.right - rc.left) / 2;
|
||||||
|
center.y = (rc.bottom - rc.top) / 2;
|
||||||
|
ClientToScreen(g_hWnd, ¢er);
|
||||||
|
SetCursorPos(center.x, center.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardMouseInput::OnMouseWheel(int delta)
|
void KeyboardMouseInput::OnKeyDown(int vkCode)
|
||||||
{
|
{
|
||||||
m_scrollDeltaAccum += delta;
|
if (vkCode >= 0 && vkCode < MAX_KEYS)
|
||||||
|
{
|
||||||
|
if (!m_keyDown[vkCode])
|
||||||
|
m_keyPressedAccum[vkCode] = true;
|
||||||
|
m_keyDown[vkCode] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardMouseInput::OnKeyUp(int vkCode)
|
||||||
|
{
|
||||||
|
if (vkCode >= 0 && vkCode < MAX_KEYS)
|
||||||
|
{
|
||||||
|
if (m_keyDown[vkCode])
|
||||||
|
m_keyReleasedAccum[vkCode] = true;
|
||||||
|
m_keyDown[vkCode] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardMouseInput::OnMouseButtonDown(int button)
|
||||||
|
{
|
||||||
|
if (button >= 0 && button < MAX_MOUSE_BUTTONS)
|
||||||
|
{
|
||||||
|
if (!m_mouseButtonDown[button])
|
||||||
|
m_mouseBtnPressedAccum[button] = true;
|
||||||
|
m_mouseButtonDown[button] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardMouseInput::OnMouseButtonUp(int button)
|
||||||
|
{
|
||||||
|
if (button >= 0 && button < MAX_MOUSE_BUTTONS)
|
||||||
|
{
|
||||||
|
if (m_mouseButtonDown[button])
|
||||||
|
m_mouseBtnReleasedAccum[button] = true;
|
||||||
|
m_mouseButtonDown[button] = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardMouseInput::OnMouseMove(int x, int y)
|
void KeyboardMouseInput::OnMouseMove(int x, int y)
|
||||||
|
|
@ -122,139 +166,195 @@ void KeyboardMouseInput::OnMouseMove(int x, int y)
|
||||||
m_mouseY = y;
|
m_mouseY = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
int KeyboardMouseInput::GetMouseX() const { return m_mouseX; }
|
void KeyboardMouseInput::OnMouseWheel(int delta)
|
||||||
int KeyboardMouseInput::GetMouseY() const { return m_mouseY; }
|
|
||||||
HWND KeyboardMouseInput::GetHWnd() const { return m_hWnd; }
|
|
||||||
|
|
||||||
void KeyboardMouseInput::ClearAllState()
|
|
||||||
{
|
{
|
||||||
memset(m_keyState, 0, sizeof(m_keyState));
|
// Normalize from raw Windows delta (multiples of WHEEL_DELTA=120) to discrete notch counts
|
||||||
memset(m_mouseButtons, 0, sizeof(m_mouseButtons));
|
m_mouseWheelAccum += delta / WHEEL_DELTA;
|
||||||
memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum));
|
|
||||||
memset(m_mousePressedAccum, 0, sizeof(m_mousePressedAccum));
|
|
||||||
memset(m_mouseReleasedAccum, 0, sizeof(m_mouseReleasedAccum));
|
|
||||||
m_mouseDeltaXAccum = 0.0f;
|
|
||||||
m_mouseDeltaYAccum = 0.0f;
|
|
||||||
m_scrollDeltaAccum = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per-frame key queries
|
int KeyboardMouseInput::GetMouseWheel()
|
||||||
bool KeyboardMouseInput::IsKeyDown(int vk) const
|
|
||||||
{
|
{
|
||||||
if (vk < 0 || vk >= 256) return false;
|
int val = m_mouseWheelAccum;
|
||||||
return m_keyState[vk];
|
if (val != 0)
|
||||||
|
m_mouseWheelConsumed = true;
|
||||||
|
m_mouseWheelAccum = 0;
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouseInput::IsKeyPressed(int vk) const
|
void KeyboardMouseInput::OnRawMouseDelta(int dx, int dy)
|
||||||
{
|
{
|
||||||
if (vk < 0 || vk >= 256) return false;
|
m_mouseDeltaAccumX += dx;
|
||||||
return m_keyState[vk] && !m_keyStatePrev[vk];
|
m_mouseDeltaAccumY += dy;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouseInput::IsKeyReleased(int vk) const
|
bool KeyboardMouseInput::IsKeyDown(int vkCode) const
|
||||||
{
|
{
|
||||||
if (vk < 0 || vk >= 256) return false;
|
if (vkCode >= 0 && vkCode < MAX_KEYS)
|
||||||
return !m_keyState[vk] && m_keyStatePrev[vk];
|
return m_keyDown[vkCode];
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per-frame mouse button queries
|
bool KeyboardMouseInput::IsKeyPressed(int vkCode) const
|
||||||
bool KeyboardMouseInput::IsMouseDown(int btn) const
|
|
||||||
{
|
{
|
||||||
if (btn < 0 || btn >= 3) return false;
|
if (vkCode >= 0 && vkCode < MAX_KEYS)
|
||||||
return m_mouseButtons[btn];
|
return m_keyPressed[vkCode];
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouseInput::IsMousePressed(int btn) const
|
bool KeyboardMouseInput::IsKeyReleased(int vkCode) const
|
||||||
{
|
{
|
||||||
if (btn < 0 || btn >= 3) return false;
|
if (vkCode >= 0 && vkCode < MAX_KEYS)
|
||||||
return m_mouseButtons[btn] && !m_mouseButtonsPrev[btn];
|
return m_keyReleased[vkCode];
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouseInput::IsMouseReleased(int btn) const
|
bool KeyboardMouseInput::IsMouseButtonDown(int button) const
|
||||||
{
|
{
|
||||||
if (btn < 0 || btn >= 3) return false;
|
if (button >= 0 && button < MAX_MOUSE_BUTTONS)
|
||||||
return !m_mouseButtons[btn] && m_mouseButtonsPrev[btn];
|
return m_mouseButtonDown[button];
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Game-tick consume methods
|
bool KeyboardMouseInput::IsMouseButtonPressed(int button) const
|
||||||
bool KeyboardMouseInput::ConsumeKeyPress(int vk)
|
|
||||||
{
|
{
|
||||||
if (vk < 0 || vk >= 256) return false;
|
if (button >= 0 && button < MAX_MOUSE_BUTTONS)
|
||||||
bool pressed = m_keyPressedAccum[vk];
|
return m_mouseBtnPressed[button];
|
||||||
m_keyPressedAccum[vk] = false;
|
return false;
|
||||||
return pressed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouseInput::ConsumeMousePress(int btn)
|
bool KeyboardMouseInput::IsMouseButtonReleased(int button) const
|
||||||
{
|
{
|
||||||
if (btn < 0 || btn >= 3) return false;
|
if (button >= 0 && button < MAX_MOUSE_BUTTONS)
|
||||||
bool pressed = m_mousePressedAccum[btn];
|
return m_mouseBtnReleased[button];
|
||||||
m_mousePressedAccum[btn] = false;
|
return false;
|
||||||
return pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KeyboardMouseInput::ConsumeMouseRelease(int btn)
|
|
||||||
{
|
|
||||||
if (btn < 0 || btn >= 3) return false;
|
|
||||||
bool released = m_mouseReleasedAccum[btn];
|
|
||||||
m_mouseReleasedAccum[btn] = false;
|
|
||||||
return released;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardMouseInput::ConsumeMouseDelta(float &dx, float &dy)
|
void KeyboardMouseInput::ConsumeMouseDelta(float &dx, float &dy)
|
||||||
{
|
{
|
||||||
dx = m_mouseDeltaXAccum;
|
dx = (float)m_mouseDeltaAccumX;
|
||||||
dy = m_mouseDeltaYAccum;
|
dy = (float)m_mouseDeltaAccumY;
|
||||||
m_mouseDeltaXAccum = 0.0f;
|
m_mouseDeltaAccumX = 0;
|
||||||
m_mouseDeltaYAccum = 0.0f;
|
m_mouseDeltaAccumY = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int KeyboardMouseInput::ConsumeScrollDelta()
|
void KeyboardMouseInput::SetMouseGrabbed(bool grabbed)
|
||||||
{
|
{
|
||||||
int delta = m_scrollDeltaAccum;
|
if (m_mouseGrabbed == grabbed)
|
||||||
m_scrollDeltaAccum = 0;
|
return;
|
||||||
return delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mouse capture
|
m_mouseGrabbed = grabbed;
|
||||||
void KeyboardMouseInput::SetCapture(bool capture)
|
if (grabbed && g_hWnd)
|
||||||
{
|
|
||||||
if (capture == m_captured) return;
|
|
||||||
m_captured = capture;
|
|
||||||
|
|
||||||
if (capture)
|
|
||||||
{
|
{
|
||||||
ShowCursor(FALSE);
|
while (ShowCursor(FALSE) >= 0) {}
|
||||||
RECT rect;
|
ClipCursorToWindow(g_hWnd);
|
||||||
GetClientRect(m_hWnd, &rect);
|
|
||||||
POINT topLeft = { rect.left, rect.top };
|
|
||||||
POINT bottomRight = { rect.right, rect.bottom };
|
|
||||||
ClientToScreen(m_hWnd, &topLeft);
|
|
||||||
ClientToScreen(m_hWnd, &bottomRight);
|
|
||||||
RECT screenRect = { topLeft.x, topLeft.y, bottomRight.x, bottomRight.y };
|
|
||||||
ClipCursor(&screenRect);
|
|
||||||
CenterCursor();
|
|
||||||
|
|
||||||
// Flush accumulated deltas so the snap-to-center doesn't cause a jump
|
RECT rc;
|
||||||
m_mouseDeltaXAccum = 0.0f;
|
GetClientRect(g_hWnd, &rc);
|
||||||
m_mouseDeltaYAccum = 0.0f;
|
POINT center;
|
||||||
|
center.x = (rc.right - rc.left) / 2;
|
||||||
|
center.y = (rc.bottom - rc.top) / 2;
|
||||||
|
ClientToScreen(g_hWnd, ¢er);
|
||||||
|
SetCursorPos(center.x, center.y);
|
||||||
|
|
||||||
|
m_mouseDeltaAccumX = 0;
|
||||||
|
m_mouseDeltaAccumY = 0;
|
||||||
}
|
}
|
||||||
else
|
else if (!grabbed && !m_cursorHiddenForUI && g_hWnd)
|
||||||
{
|
{
|
||||||
ShowCursor(TRUE);
|
while (ShowCursor(TRUE) < 0) {}
|
||||||
ClipCursor(NULL);
|
ClipCursor(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouseInput::IsCaptured() const { return m_captured; }
|
void KeyboardMouseInput::SetCursorHiddenForUI(bool hidden)
|
||||||
|
|
||||||
void KeyboardMouseInput::CenterCursor()
|
|
||||||
{
|
{
|
||||||
RECT rect;
|
if (m_cursorHiddenForUI == hidden)
|
||||||
GetClientRect(m_hWnd, &rect);
|
return;
|
||||||
POINT center = { (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 };
|
|
||||||
ClientToScreen(m_hWnd, ¢er);
|
m_cursorHiddenForUI = hidden;
|
||||||
SetCursorPos(center.x, center.y);
|
if (hidden && g_hWnd)
|
||||||
|
{
|
||||||
|
while (ShowCursor(FALSE) >= 0) {}
|
||||||
|
ClipCursorToWindow(g_hWnd);
|
||||||
|
|
||||||
|
RECT rc;
|
||||||
|
GetClientRect(g_hWnd, &rc);
|
||||||
|
POINT center;
|
||||||
|
center.x = (rc.right - rc.left) / 2;
|
||||||
|
center.y = (rc.bottom - rc.top) / 2;
|
||||||
|
ClientToScreen(g_hWnd, ¢er);
|
||||||
|
SetCursorPos(center.x, center.y);
|
||||||
|
|
||||||
|
m_mouseDeltaAccumX = 0;
|
||||||
|
m_mouseDeltaAccumY = 0;
|
||||||
|
}
|
||||||
|
else if (!hidden && !m_mouseGrabbed && g_hWnd)
|
||||||
|
{
|
||||||
|
while (ShowCursor(TRUE) < 0) {}
|
||||||
|
ClipCursor(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ClipCursorToWindow(HWND hWnd)
|
||||||
|
{
|
||||||
|
if (!hWnd) return;
|
||||||
|
RECT rc;
|
||||||
|
GetClientRect(hWnd, &rc);
|
||||||
|
POINT topLeft = { rc.left, rc.top };
|
||||||
|
POINT bottomRight = { rc.right, rc.bottom };
|
||||||
|
ClientToScreen(hWnd, &topLeft);
|
||||||
|
ClientToScreen(hWnd, &bottomRight);
|
||||||
|
RECT clipRect = { topLeft.x, topLeft.y, bottomRight.x, bottomRight.y };
|
||||||
|
ClipCursor(&clipRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardMouseInput::SetWindowFocused(bool focused)
|
||||||
|
{
|
||||||
|
m_windowFocused = focused;
|
||||||
|
if (focused)
|
||||||
|
{
|
||||||
|
if (m_mouseGrabbed || m_cursorHiddenForUI)
|
||||||
|
{
|
||||||
|
while (ShowCursor(FALSE) >= 0) {}
|
||||||
|
ClipCursorToWindow(g_hWnd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (ShowCursor(TRUE) < 0) {}
|
||||||
|
ClipCursor(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (ShowCursor(TRUE) < 0) {}
|
||||||
|
ClipCursor(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float KeyboardMouseInput::GetMoveX() const
|
||||||
|
{
|
||||||
|
float x = 0.0f;
|
||||||
|
if (m_keyDown[KEY_LEFT]) x += 1.0f;
|
||||||
|
if (m_keyDown[KEY_RIGHT]) x -= 1.0f;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float KeyboardMouseInput::GetMoveY() const
|
||||||
|
{
|
||||||
|
float y = 0.0f;
|
||||||
|
if (m_keyDown[KEY_FORWARD]) y += 1.0f;
|
||||||
|
if (m_keyDown[KEY_BACKWARD]) y -= 1.0f;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
float KeyboardMouseInput::GetLookX(float sensitivity) const
|
||||||
|
{
|
||||||
|
return (float)m_mouseDeltaX * sensitivity;
|
||||||
|
}
|
||||||
|
|
||||||
|
float KeyboardMouseInput::GetLookY(float sensitivity) const
|
||||||
|
{
|
||||||
|
return (float)(-m_mouseDeltaY) * sensitivity;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _WINDOWS64
|
#endif // _WINDOWS64
|
||||||
|
|
|
||||||
|
|
@ -4,88 +4,132 @@
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
// HID usage page and usage for raw input registration
|
|
||||||
#ifndef HID_USAGE_PAGE_GENERIC
|
|
||||||
#define HID_USAGE_PAGE_GENERIC ((USHORT)0x01)
|
|
||||||
#endif
|
|
||||||
#ifndef HID_USAGE_GENERIC_MOUSE
|
|
||||||
#define HID_USAGE_GENERIC_MOUSE ((USHORT)0x02)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class KeyboardMouseInput
|
class KeyboardMouseInput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
KeyboardMouseInput();
|
static const int MAX_KEYS = 256;
|
||||||
~KeyboardMouseInput();
|
|
||||||
|
|
||||||
void Init(HWND hWnd);
|
static const int MOUSE_LEFT = 0;
|
||||||
|
static const int MOUSE_RIGHT = 1;
|
||||||
|
static const int MOUSE_MIDDLE = 2;
|
||||||
|
static const int MAX_MOUSE_BUTTONS = 3;
|
||||||
|
|
||||||
|
static const int KEY_FORWARD = 'W';
|
||||||
|
static const int KEY_BACKWARD = 'S';
|
||||||
|
static const int KEY_LEFT = 'A';
|
||||||
|
static const int KEY_RIGHT = 'D';
|
||||||
|
static const int KEY_JUMP = VK_SPACE;
|
||||||
|
static const int KEY_SNEAK = VK_LSHIFT;
|
||||||
|
static const int KEY_SPRINT = VK_LCONTROL;
|
||||||
|
static const int KEY_INVENTORY = 'E';
|
||||||
|
static const int KEY_DROP = 'Q';
|
||||||
|
static const int KEY_CRAFTING = 'C';
|
||||||
|
static const int KEY_CRAFTING_ALT = 'R';
|
||||||
|
static const int KEY_CONFIRM = VK_RETURN;
|
||||||
|
static const int KEY_CANCEL = VK_ESCAPE;
|
||||||
|
static const int KEY_PAUSE = VK_ESCAPE;
|
||||||
|
static const int KEY_THIRD_PERSON = VK_F5;
|
||||||
|
static const int KEY_DEBUG_INFO = VK_F3;
|
||||||
|
|
||||||
|
void Init();
|
||||||
void Tick();
|
void Tick();
|
||||||
void EndFrame();
|
|
||||||
|
|
||||||
// Called from WndProc
|
|
||||||
void OnKeyDown(WPARAM vk);
|
|
||||||
void OnKeyUp(WPARAM vk);
|
|
||||||
void OnRawMouseInput(LPARAM lParam);
|
|
||||||
void OnMouseButton(int button, bool down);
|
|
||||||
void OnMouseWheel(int delta);
|
|
||||||
void ClearAllState();
|
void ClearAllState();
|
||||||
|
|
||||||
// Per-frame edge detection (for UI / per-frame logic like Alt toggle)
|
void OnKeyDown(int vkCode);
|
||||||
bool IsKeyDown(int vk) const;
|
void OnKeyUp(int vkCode);
|
||||||
bool IsKeyPressed(int vk) const;
|
void OnMouseButtonDown(int button);
|
||||||
bool IsKeyReleased(int vk) const;
|
void OnMouseButtonUp(int button);
|
||||||
bool IsMouseDown(int btn) const;
|
|
||||||
bool IsMousePressed(int btn) const;
|
|
||||||
bool IsMouseReleased(int btn) const;
|
|
||||||
|
|
||||||
// Game-tick consume methods: accumulate across frames, clear on read.
|
|
||||||
// Use these from code that runs at game tick rate (20Hz).
|
|
||||||
bool ConsumeKeyPress(int vk);
|
|
||||||
bool ConsumeMousePress(int btn);
|
|
||||||
bool ConsumeMouseRelease(int btn);
|
|
||||||
void ConsumeMouseDelta(float &dx, float &dy);
|
|
||||||
int ConsumeScrollDelta();
|
|
||||||
|
|
||||||
// Absolute cursor position (client-area coordinates, for GUI when not captured)
|
|
||||||
void OnMouseMove(int x, int y);
|
void OnMouseMove(int x, int y);
|
||||||
int GetMouseX() const;
|
void OnMouseWheel(int delta);
|
||||||
int GetMouseY() const;
|
void OnRawMouseDelta(int dx, int dy);
|
||||||
HWND GetHWnd() const;
|
|
||||||
|
|
||||||
// Mouse capture for FPS look
|
bool IsKeyDown(int vkCode) const;
|
||||||
void SetCapture(bool capture);
|
bool IsKeyPressed(int vkCode) const;
|
||||||
bool IsCaptured() const;
|
bool IsKeyReleased(int vkCode) const;
|
||||||
|
|
||||||
|
bool IsMouseButtonDown(int button) const;
|
||||||
|
bool IsMouseButtonPressed(int button) const;
|
||||||
|
bool IsMouseButtonReleased(int button) const;
|
||||||
|
|
||||||
|
int GetMouseX() const { return m_mouseX; }
|
||||||
|
int GetMouseY() const { return m_mouseY; }
|
||||||
|
|
||||||
|
int GetMouseDeltaX() const { return m_mouseDeltaX; }
|
||||||
|
int GetMouseDeltaY() const { return m_mouseDeltaY; }
|
||||||
|
|
||||||
|
int GetMouseWheel();
|
||||||
|
int PeekMouseWheel() const { return m_mouseWheelAccum; }
|
||||||
|
void ConsumeMouseWheel() { if (m_mouseWheelAccum != 0) m_mouseWheelConsumed = true; m_mouseWheelAccum = 0; }
|
||||||
|
bool WasMouseWheelConsumed() const { return m_mouseWheelConsumed; }
|
||||||
|
|
||||||
|
// Per-frame delta consumption for low-latency mouse look.
|
||||||
|
// Reads and clears the raw accumulators (not the per-tick snapshot).
|
||||||
|
void ConsumeMouseDelta(float &dx, float &dy);
|
||||||
|
|
||||||
|
void SetMouseGrabbed(bool grabbed);
|
||||||
|
bool IsMouseGrabbed() const { return m_mouseGrabbed; }
|
||||||
|
|
||||||
|
void SetCursorHiddenForUI(bool hidden);
|
||||||
|
bool IsCursorHiddenForUI() const { return m_cursorHiddenForUI; }
|
||||||
|
|
||||||
|
void SetWindowFocused(bool focused);
|
||||||
|
bool IsWindowFocused() const { return m_windowFocused; }
|
||||||
|
|
||||||
|
bool HasAnyInput() const { return m_hasInput; }
|
||||||
|
|
||||||
|
void SetKBMActive(bool active) { m_kbmActive = active; }
|
||||||
|
bool IsKBMActive() const { return m_kbmActive; }
|
||||||
|
|
||||||
|
void SetScreenCursorHidden(bool hidden) { m_screenWantsCursorHidden = hidden; }
|
||||||
|
bool IsScreenCursorHidden() const { return m_screenWantsCursorHidden; }
|
||||||
|
|
||||||
|
float GetMoveX() const;
|
||||||
|
float GetMoveY() const;
|
||||||
|
|
||||||
|
float GetLookX(float sensitivity) const;
|
||||||
|
float GetLookY(float sensitivity) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CenterCursor();
|
bool m_keyDown[MAX_KEYS];
|
||||||
|
bool m_keyDownPrev[MAX_KEYS];
|
||||||
|
|
||||||
// Per-frame double-buffered state (for IsKeyPressed/Released per-frame edge detection)
|
bool m_keyPressedAccum[MAX_KEYS];
|
||||||
bool m_keyState[256];
|
bool m_keyReleasedAccum[MAX_KEYS];
|
||||||
bool m_keyStatePrev[256];
|
bool m_keyPressed[MAX_KEYS];
|
||||||
bool m_mouseButtons[3];
|
bool m_keyReleased[MAX_KEYS];
|
||||||
bool m_mouseButtonsPrev[3];
|
|
||||||
|
|
||||||
// Sticky press accumulators (persist until consumed by game tick)
|
bool m_mouseButtonDown[MAX_MOUSE_BUTTONS];
|
||||||
bool m_keyPressedAccum[256];
|
bool m_mouseButtonDownPrev[MAX_MOUSE_BUTTONS];
|
||||||
bool m_mousePressedAccum[3];
|
|
||||||
bool m_mouseReleasedAccum[3];
|
|
||||||
|
|
||||||
// Mouse delta accumulators (persist until consumed by game tick)
|
bool m_mouseBtnPressedAccum[MAX_MOUSE_BUTTONS];
|
||||||
float m_mouseDeltaXAccum;
|
bool m_mouseBtnReleasedAccum[MAX_MOUSE_BUTTONS];
|
||||||
float m_mouseDeltaYAccum;
|
bool m_mouseBtnPressed[MAX_MOUSE_BUTTONS];
|
||||||
|
bool m_mouseBtnReleased[MAX_MOUSE_BUTTONS];
|
||||||
|
|
||||||
// Scroll accumulator (persists until consumed by game tick)
|
|
||||||
int m_scrollDeltaAccum;
|
|
||||||
|
|
||||||
bool m_captured;
|
|
||||||
HWND m_hWnd;
|
|
||||||
bool m_initialized;
|
|
||||||
|
|
||||||
// Absolute cursor position in client coordinates
|
|
||||||
int m_mouseX;
|
int m_mouseX;
|
||||||
int m_mouseY;
|
int m_mouseY;
|
||||||
|
|
||||||
|
int m_mouseDeltaX;
|
||||||
|
int m_mouseDeltaY;
|
||||||
|
int m_mouseDeltaAccumX;
|
||||||
|
int m_mouseDeltaAccumY;
|
||||||
|
|
||||||
|
int m_mouseWheelAccum;
|
||||||
|
bool m_mouseWheelConsumed;
|
||||||
|
|
||||||
|
bool m_mouseGrabbed;
|
||||||
|
|
||||||
|
bool m_cursorHiddenForUI;
|
||||||
|
|
||||||
|
bool m_windowFocused;
|
||||||
|
|
||||||
|
bool m_hasInput;
|
||||||
|
|
||||||
|
bool m_kbmActive;
|
||||||
|
|
||||||
|
bool m_screenWantsCursorHidden;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern KeyboardMouseInput KMInput;
|
extern KeyboardMouseInput g_KBMInput;
|
||||||
|
|
||||||
#endif // _WINDOWS64
|
#endif // _WINDOWS64
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// Code implemented by LCEMP, credit if used on other repos
|
||||||
|
// https://github.com/LCEMP/LCEMP
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
|
|
@ -48,6 +51,9 @@ bool g_Win64MultiplayerHost = false;
|
||||||
bool g_Win64MultiplayerJoin = false;
|
bool g_Win64MultiplayerJoin = false;
|
||||||
int g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT;
|
int g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT;
|
||||||
char g_Win64MultiplayerIP[256] = "127.0.0.1";
|
char g_Win64MultiplayerIP[256] = "127.0.0.1";
|
||||||
|
bool g_Win64DedicatedServer = false;
|
||||||
|
int g_Win64DedicatedServerPort = WIN64_NET_DEFAULT_PORT;
|
||||||
|
char g_Win64DedicatedServerBindIP[256] = "";
|
||||||
|
|
||||||
bool WinsockNetLayer::Initialize()
|
bool WinsockNetLayer::Initialize()
|
||||||
{
|
{
|
||||||
|
|
@ -136,7 +142,7 @@ void WinsockNetLayer::Shutdown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WinsockNetLayer::HostGame(int port)
|
bool WinsockNetLayer::HostGame(int port, const char* bindIp)
|
||||||
{
|
{
|
||||||
if (!s_initialized && !Initialize()) return false;
|
if (!s_initialized && !Initialize()) return false;
|
||||||
|
|
||||||
|
|
@ -151,20 +157,24 @@ bool WinsockNetLayer::HostGame(int port)
|
||||||
LeaveCriticalSection(&s_freeSmallIdLock);
|
LeaveCriticalSection(&s_freeSmallIdLock);
|
||||||
|
|
||||||
struct addrinfo hints = {};
|
struct addrinfo hints = {};
|
||||||
struct addrinfo *result = NULL;
|
struct addrinfo* result = NULL;
|
||||||
|
|
||||||
hints.ai_family = AF_INET;
|
hints.ai_family = AF_INET;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
hints.ai_flags = AI_PASSIVE;
|
hints.ai_flags = (bindIp == NULL || bindIp[0] == 0) ? AI_PASSIVE : 0;
|
||||||
|
|
||||||
char portStr[16];
|
char portStr[16];
|
||||||
sprintf_s(portStr, "%d", port);
|
sprintf_s(portStr, "%d", port);
|
||||||
|
|
||||||
int iResult = getaddrinfo(NULL, portStr, &hints, &result);
|
const char* resolvedBindIp = (bindIp != NULL && bindIp[0] != 0) ? bindIp : NULL;
|
||||||
|
int iResult = getaddrinfo(resolvedBindIp, portStr, &hints, &result);
|
||||||
if (iResult != 0)
|
if (iResult != 0)
|
||||||
{
|
{
|
||||||
app.DebugPrintf("getaddrinfo failed: %d\n", iResult);
|
app.DebugPrintf("getaddrinfo failed for %s:%d - %d\n",
|
||||||
|
resolvedBindIp != NULL ? resolvedBindIp : "*",
|
||||||
|
port,
|
||||||
|
iResult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,7 +187,7 @@ bool WinsockNetLayer::HostGame(int port)
|
||||||
}
|
}
|
||||||
|
|
||||||
int opt = 1;
|
int opt = 1;
|
||||||
setsockopt(s_listenSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt));
|
setsockopt(s_listenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt));
|
||||||
|
|
||||||
iResult = ::bind(s_listenSocket, result->ai_addr, (int)result->ai_addrlen);
|
iResult = ::bind(s_listenSocket, result->ai_addr, (int)result->ai_addrlen);
|
||||||
freeaddrinfo(result);
|
freeaddrinfo(result);
|
||||||
|
|
@ -203,19 +213,29 @@ bool WinsockNetLayer::HostGame(int port)
|
||||||
|
|
||||||
s_acceptThread = CreateThread(NULL, 0, AcceptThreadProc, NULL, 0, NULL);
|
s_acceptThread = CreateThread(NULL, 0, AcceptThreadProc, NULL, 0, NULL);
|
||||||
|
|
||||||
app.DebugPrintf("Win64 LAN: Hosting on port %d\n", port);
|
app.DebugPrintf("Win64 LAN: Hosting on %s:%d\n",
|
||||||
|
resolvedBindIp != NULL ? resolvedBindIp : "*",
|
||||||
|
port);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WinsockNetLayer::JoinGame(const char *ip, int port)
|
bool WinsockNetLayer::JoinGame(const char* ip, int port)
|
||||||
{
|
{
|
||||||
if (!s_initialized && !Initialize()) return false;
|
if (!s_initialized && !Initialize()) return false;
|
||||||
|
|
||||||
s_isHost = false;
|
s_isHost = false;
|
||||||
s_hostSmallId = 0;
|
s_hostSmallId = 0;
|
||||||
|
s_connected = false;
|
||||||
|
s_active = false;
|
||||||
|
|
||||||
|
if (s_hostConnectionSocket != INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
closesocket(s_hostConnectionSocket);
|
||||||
|
s_hostConnectionSocket = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
struct addrinfo hints = {};
|
struct addrinfo hints = {};
|
||||||
struct addrinfo *result = NULL;
|
struct addrinfo* result = NULL;
|
||||||
|
|
||||||
hints.ai_family = AF_INET;
|
hints.ai_family = AF_INET;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
@ -231,37 +251,55 @@ bool WinsockNetLayer::JoinGame(const char *ip, int port)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_hostConnectionSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
bool connected = false;
|
||||||
if (s_hostConnectionSocket == INVALID_SOCKET)
|
BYTE assignedSmallId = 0;
|
||||||
|
const int maxAttempts = 12;
|
||||||
|
|
||||||
|
for (int attempt = 0; attempt < maxAttempts; ++attempt)
|
||||||
{
|
{
|
||||||
app.DebugPrintf("socket() failed: %d\n", WSAGetLastError());
|
s_hostConnectionSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||||
freeaddrinfo(result);
|
if (s_hostConnectionSocket == INVALID_SOCKET)
|
||||||
return false;
|
{
|
||||||
|
app.DebugPrintf("socket() failed: %d\n", WSAGetLastError());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int noDelay = 1;
|
||||||
|
setsockopt(s_hostConnectionSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&noDelay, sizeof(noDelay));
|
||||||
|
|
||||||
|
iResult = connect(s_hostConnectionSocket, result->ai_addr, (int)result->ai_addrlen);
|
||||||
|
if (iResult == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
int err = WSAGetLastError();
|
||||||
|
app.DebugPrintf("connect() to %s:%d failed (attempt %d/%d): %d\n", ip, port, attempt + 1, maxAttempts, err);
|
||||||
|
closesocket(s_hostConnectionSocket);
|
||||||
|
s_hostConnectionSocket = INVALID_SOCKET;
|
||||||
|
Sleep(200);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE assignBuf[1];
|
||||||
|
int bytesRecv = recv(s_hostConnectionSocket, (char*)assignBuf, 1, 0);
|
||||||
|
if (bytesRecv != 1)
|
||||||
|
{
|
||||||
|
app.DebugPrintf("Failed to receive small ID assignment from host (attempt %d/%d)\n", attempt + 1, maxAttempts);
|
||||||
|
closesocket(s_hostConnectionSocket);
|
||||||
|
s_hostConnectionSocket = INVALID_SOCKET;
|
||||||
|
Sleep(200);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
assignedSmallId = assignBuf[0];
|
||||||
|
connected = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int noDelay = 1;
|
|
||||||
setsockopt(s_hostConnectionSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&noDelay, sizeof(noDelay));
|
|
||||||
|
|
||||||
iResult = connect(s_hostConnectionSocket, result->ai_addr, (int)result->ai_addrlen);
|
|
||||||
freeaddrinfo(result);
|
freeaddrinfo(result);
|
||||||
if (iResult == SOCKET_ERROR)
|
|
||||||
{
|
|
||||||
app.DebugPrintf("connect() to %s:%d failed: %d\n", ip, port, WSAGetLastError());
|
|
||||||
closesocket(s_hostConnectionSocket);
|
|
||||||
s_hostConnectionSocket = INVALID_SOCKET;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BYTE assignBuf[1];
|
if (!connected)
|
||||||
int bytesRecv = recv(s_hostConnectionSocket, (char *)assignBuf, 1, 0);
|
|
||||||
if (bytesRecv != 1)
|
|
||||||
{
|
{
|
||||||
app.DebugPrintf("Failed to receive small ID assignment from host\n");
|
|
||||||
closesocket(s_hostConnectionSocket);
|
|
||||||
s_hostConnectionSocket = INVALID_SOCKET;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
s_localSmallId = assignBuf[0];
|
s_localSmallId = assignedSmallId;
|
||||||
|
|
||||||
app.DebugPrintf("Win64 LAN: Connected to %s:%d, assigned smallId=%d\n", ip, port, s_localSmallId);
|
app.DebugPrintf("Win64 LAN: Connected to %s:%d, assigned smallId=%d\n", ip, port, s_localSmallId);
|
||||||
|
|
||||||
|
|
@ -273,7 +311,7 @@ bool WinsockNetLayer::JoinGame(const char *ip, int port)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void *data, int dataSize)
|
bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void* data, int dataSize)
|
||||||
{
|
{
|
||||||
if (sock == INVALID_SOCKET || dataSize <= 0) return false;
|
if (sock == INVALID_SOCKET || dataSize <= 0) return false;
|
||||||
|
|
||||||
|
|
@ -289,7 +327,7 @@ bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void *data, int dataSize)
|
||||||
int toSend = 4;
|
int toSend = 4;
|
||||||
while (totalSent < toSend)
|
while (totalSent < toSend)
|
||||||
{
|
{
|
||||||
int sent = send(sock, (const char *)header + totalSent, toSend - totalSent, 0);
|
int sent = send(sock, (const char*)header + totalSent, toSend - totalSent, 0);
|
||||||
if (sent == SOCKET_ERROR || sent == 0)
|
if (sent == SOCKET_ERROR || sent == 0)
|
||||||
{
|
{
|
||||||
LeaveCriticalSection(&s_sendLock);
|
LeaveCriticalSection(&s_sendLock);
|
||||||
|
|
@ -301,7 +339,7 @@ bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void *data, int dataSize)
|
||||||
totalSent = 0;
|
totalSent = 0;
|
||||||
while (totalSent < dataSize)
|
while (totalSent < dataSize)
|
||||||
{
|
{
|
||||||
int sent = send(sock, (const char *)data + totalSent, dataSize - totalSent, 0);
|
int sent = send(sock, (const char*)data + totalSent, dataSize - totalSent, 0);
|
||||||
if (sent == SOCKET_ERROR || sent == 0)
|
if (sent == SOCKET_ERROR || sent == 0)
|
||||||
{
|
{
|
||||||
LeaveCriticalSection(&s_sendLock);
|
LeaveCriticalSection(&s_sendLock);
|
||||||
|
|
@ -314,7 +352,7 @@ bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void *data, int dataSize)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WinsockNetLayer::SendToSmallId(BYTE targetSmallId, const void *data, int dataSize)
|
bool WinsockNetLayer::SendToSmallId(BYTE targetSmallId, const void* data, int dataSize)
|
||||||
{
|
{
|
||||||
if (!s_active) return false;
|
if (!s_active) return false;
|
||||||
|
|
||||||
|
|
@ -346,34 +384,34 @@ SOCKET WinsockNetLayer::GetSocketForSmallId(BYTE smallId)
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool RecvExact(SOCKET sock, BYTE *buf, int len)
|
static bool RecvExact(SOCKET sock, BYTE* buf, int len)
|
||||||
{
|
{
|
||||||
int totalRecv = 0;
|
int totalRecv = 0;
|
||||||
while (totalRecv < len)
|
while (totalRecv < len)
|
||||||
{
|
{
|
||||||
int r = recv(sock, (char *)buf + totalRecv, len - totalRecv, 0);
|
int r = recv(sock, (char*)buf + totalRecv, len - totalRecv, 0);
|
||||||
if (r <= 0) return false;
|
if (r <= 0) return false;
|
||||||
totalRecv += r;
|
totalRecv += r;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WinsockNetLayer::HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsigned char *data, unsigned int dataSize)
|
void WinsockNetLayer::HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsigned char* data, unsigned int dataSize)
|
||||||
{
|
{
|
||||||
INetworkPlayer *pPlayerFrom = g_NetworkManager.GetPlayerBySmallId(fromSmallId);
|
INetworkPlayer* pPlayerFrom = g_NetworkManager.GetPlayerBySmallId(fromSmallId);
|
||||||
INetworkPlayer *pPlayerTo = g_NetworkManager.GetPlayerBySmallId(toSmallId);
|
INetworkPlayer* pPlayerTo = g_NetworkManager.GetPlayerBySmallId(toSmallId);
|
||||||
|
|
||||||
if (pPlayerFrom == NULL || pPlayerTo == NULL) return;
|
if (pPlayerFrom == NULL || pPlayerTo == NULL) return;
|
||||||
|
|
||||||
if (s_isHost)
|
if (s_isHost)
|
||||||
{
|
{
|
||||||
::Socket *pSocket = pPlayerFrom->GetSocket();
|
::Socket* pSocket = pPlayerFrom->GetSocket();
|
||||||
if (pSocket != NULL)
|
if (pSocket != NULL)
|
||||||
pSocket->pushDataToQueue(data, dataSize, false);
|
pSocket->pushDataToQueue(data, dataSize, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
::Socket *pSocket = pPlayerTo->GetSocket();
|
::Socket* pSocket = pPlayerTo->GetSocket();
|
||||||
if (pSocket != NULL)
|
if (pSocket != NULL)
|
||||||
pSocket->pushDataToQueue(data, dataSize, true);
|
pSocket->pushDataToQueue(data, dataSize, true);
|
||||||
}
|
}
|
||||||
|
|
@ -392,7 +430,7 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
|
||||||
}
|
}
|
||||||
|
|
||||||
int noDelay = 1;
|
int noDelay = 1;
|
||||||
setsockopt(clientSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&noDelay, sizeof(noDelay));
|
setsockopt(clientSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&noDelay, sizeof(noDelay));
|
||||||
|
|
||||||
extern QNET_STATE _iQNetStubState;
|
extern QNET_STATE _iQNetStubState;
|
||||||
if (_iQNetStubState != QNET_STATE_GAME_PLAY)
|
if (_iQNetStubState != QNET_STATE_GAME_PLAY)
|
||||||
|
|
@ -423,7 +461,7 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
|
||||||
LeaveCriticalSection(&s_freeSmallIdLock);
|
LeaveCriticalSection(&s_freeSmallIdLock);
|
||||||
|
|
||||||
BYTE assignBuf[1] = { assignedSmallId };
|
BYTE assignBuf[1] = { assignedSmallId };
|
||||||
int sent = send(clientSocket, (const char *)assignBuf, 1, 0);
|
int sent = send(clientSocket, (const char*)assignBuf, 1, 0);
|
||||||
if (sent != 1)
|
if (sent != 1)
|
||||||
{
|
{
|
||||||
app.DebugPrintf("Failed to send small ID to client\n");
|
app.DebugPrintf("Failed to send small ID to client\n");
|
||||||
|
|
@ -444,15 +482,15 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
|
||||||
|
|
||||||
app.DebugPrintf("Win64 LAN: Client connected, assigned smallId=%d\n", assignedSmallId);
|
app.DebugPrintf("Win64 LAN: Client connected, assigned smallId=%d\n", assignedSmallId);
|
||||||
|
|
||||||
IQNetPlayer *qnetPlayer = &IQNet::m_player[assignedSmallId];
|
IQNetPlayer* qnetPlayer = &IQNet::m_player[assignedSmallId];
|
||||||
|
|
||||||
extern void Win64_SetupRemoteQNetPlayer(IQNetPlayer *player, BYTE smallId, bool isHost, bool isLocal);
|
extern void Win64_SetupRemoteQNetPlayer(IQNetPlayer * player, BYTE smallId, bool isHost, bool isLocal);
|
||||||
Win64_SetupRemoteQNetPlayer(qnetPlayer, assignedSmallId, false, false);
|
Win64_SetupRemoteQNetPlayer(qnetPlayer, assignedSmallId, false, false);
|
||||||
|
|
||||||
extern CPlatformNetworkManagerStub *g_pPlatformNetworkManager;
|
extern CPlatformNetworkManagerStub* g_pPlatformNetworkManager;
|
||||||
g_pPlatformNetworkManager->NotifyPlayerJoined(qnetPlayer);
|
g_pPlatformNetworkManager->NotifyPlayerJoined(qnetPlayer);
|
||||||
|
|
||||||
DWORD *threadParam = new DWORD;
|
DWORD* threadParam = new DWORD;
|
||||||
*threadParam = connIdx;
|
*threadParam = connIdx;
|
||||||
HANDLE hThread = CreateThread(NULL, 0, RecvThreadProc, threadParam, 0, NULL);
|
HANDLE hThread = CreateThread(NULL, 0, RecvThreadProc, threadParam, 0, NULL);
|
||||||
|
|
||||||
|
|
@ -466,8 +504,8 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
|
||||||
|
|
||||||
DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param)
|
DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param)
|
||||||
{
|
{
|
||||||
DWORD connIdx = *(DWORD *)param;
|
DWORD connIdx = *(DWORD*)param;
|
||||||
delete (DWORD *)param;
|
delete (DWORD*)param;
|
||||||
|
|
||||||
EnterCriticalSection(&s_connectionsLock);
|
EnterCriticalSection(&s_connectionsLock);
|
||||||
if (connIdx >= (DWORD)s_connections.size())
|
if (connIdx >= (DWORD)s_connections.size())
|
||||||
|
|
@ -479,7 +517,8 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param)
|
||||||
BYTE clientSmallId = s_connections[connIdx].smallId;
|
BYTE clientSmallId = s_connections[connIdx].smallId;
|
||||||
LeaveCriticalSection(&s_connectionsLock);
|
LeaveCriticalSection(&s_connectionsLock);
|
||||||
|
|
||||||
BYTE *recvBuf = new BYTE[WIN64_NET_RECV_BUFFER_SIZE];
|
std::vector<BYTE> recvBuf;
|
||||||
|
recvBuf.resize(WIN64_NET_RECV_BUFFER_SIZE);
|
||||||
|
|
||||||
while (s_active)
|
while (s_active)
|
||||||
{
|
{
|
||||||
|
|
@ -490,33 +529,47 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int packetSize = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3];
|
int packetSize =
|
||||||
|
((uint32_t)header[0] << 24) |
|
||||||
|
((uint32_t)header[1] << 16) |
|
||||||
|
((uint32_t)header[2] << 8) |
|
||||||
|
((uint32_t)header[3]);
|
||||||
|
|
||||||
if (packetSize <= 0 || packetSize > WIN64_NET_RECV_BUFFER_SIZE)
|
if (packetSize <= 0 || packetSize > WIN64_NET_MAX_PACKET_SIZE)
|
||||||
{
|
{
|
||||||
app.DebugPrintf("Win64 LAN: Invalid packet size %d from client smallId=%d\n", packetSize, clientSmallId);
|
app.DebugPrintf("Win64 LAN: Invalid packet size %d from client smallId=%d (max=%d)\n",
|
||||||
|
packetSize,
|
||||||
|
clientSmallId,
|
||||||
|
(int)WIN64_NET_MAX_PACKET_SIZE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RecvExact(sock, recvBuf, packetSize))
|
if ((int)recvBuf.size() < packetSize)
|
||||||
|
{
|
||||||
|
recvBuf.resize(packetSize);
|
||||||
|
app.DebugPrintf("Win64 LAN: Resized host recv buffer to %d bytes for client smallId=%d\n", packetSize, clientSmallId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RecvExact(sock, &recvBuf[0], packetSize))
|
||||||
{
|
{
|
||||||
app.DebugPrintf("Win64 LAN: Client smallId=%d disconnected (body)\n", clientSmallId);
|
app.DebugPrintf("Win64 LAN: Client smallId=%d disconnected (body)\n", clientSmallId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleDataReceived(clientSmallId, s_hostSmallId, recvBuf, packetSize);
|
HandleDataReceived(clientSmallId, s_hostSmallId, &recvBuf[0], packetSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] recvBuf;
|
|
||||||
|
|
||||||
EnterCriticalSection(&s_connectionsLock);
|
EnterCriticalSection(&s_connectionsLock);
|
||||||
for (size_t i = 0; i < s_connections.size(); i++)
|
for (size_t i = 0; i < s_connections.size(); i++)
|
||||||
{
|
{
|
||||||
if (s_connections[i].smallId == clientSmallId)
|
if (s_connections[i].smallId == clientSmallId)
|
||||||
{
|
{
|
||||||
s_connections[i].active = false;
|
s_connections[i].active = false;
|
||||||
closesocket(s_connections[i].tcpSocket);
|
if (s_connections[i].tcpSocket != INVALID_SOCKET)
|
||||||
s_connections[i].tcpSocket = INVALID_SOCKET;
|
{
|
||||||
|
closesocket(s_connections[i].tcpSocket);
|
||||||
|
s_connections[i].tcpSocket = INVALID_SOCKET;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -529,7 +582,7 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WinsockNetLayer::PopDisconnectedSmallId(BYTE *outSmallId)
|
bool WinsockNetLayer::PopDisconnectedSmallId(BYTE* outSmallId)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
EnterCriticalSection(&s_disconnectLock);
|
EnterCriticalSection(&s_disconnectLock);
|
||||||
|
|
@ -550,9 +603,26 @@ void WinsockNetLayer::PushFreeSmallId(BYTE smallId)
|
||||||
LeaveCriticalSection(&s_freeSmallIdLock);
|
LeaveCriticalSection(&s_freeSmallIdLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WinsockNetLayer::CloseConnectionBySmallId(BYTE smallId)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&s_connectionsLock);
|
||||||
|
for (size_t i = 0; i < s_connections.size(); i++)
|
||||||
|
{
|
||||||
|
if (s_connections[i].smallId == smallId && s_connections[i].active && s_connections[i].tcpSocket != INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
closesocket(s_connections[i].tcpSocket);
|
||||||
|
s_connections[i].tcpSocket = INVALID_SOCKET;
|
||||||
|
app.DebugPrintf("Win64 LAN: Force-closed TCP connection for smallId=%d\n", smallId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&s_connectionsLock);
|
||||||
|
}
|
||||||
|
|
||||||
DWORD WINAPI WinsockNetLayer::ClientRecvThreadProc(LPVOID param)
|
DWORD WINAPI WinsockNetLayer::ClientRecvThreadProc(LPVOID param)
|
||||||
{
|
{
|
||||||
BYTE *recvBuf = new BYTE[WIN64_NET_RECV_BUFFER_SIZE];
|
std::vector<BYTE> recvBuf;
|
||||||
|
recvBuf.resize(WIN64_NET_RECV_BUFFER_SIZE);
|
||||||
|
|
||||||
while (s_active && s_hostConnectionSocket != INVALID_SOCKET)
|
while (s_active && s_hostConnectionSocket != INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
|
|
@ -565,28 +635,34 @@ DWORD WINAPI WinsockNetLayer::ClientRecvThreadProc(LPVOID param)
|
||||||
|
|
||||||
int packetSize = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3];
|
int packetSize = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3];
|
||||||
|
|
||||||
if (packetSize <= 0 || packetSize > WIN64_NET_RECV_BUFFER_SIZE)
|
if (packetSize <= 0 || packetSize > WIN64_NET_MAX_PACKET_SIZE)
|
||||||
{
|
{
|
||||||
app.DebugPrintf("Win64 LAN: Invalid packet size %d from host\n", packetSize);
|
app.DebugPrintf("Win64 LAN: Invalid packet size %d from host (max=%d)\n",
|
||||||
|
packetSize,
|
||||||
|
(int)WIN64_NET_MAX_PACKET_SIZE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RecvExact(s_hostConnectionSocket, recvBuf, packetSize))
|
if ((int)recvBuf.size() < packetSize)
|
||||||
|
{
|
||||||
|
recvBuf.resize(packetSize);
|
||||||
|
app.DebugPrintf("Win64 LAN: Resized client recv buffer to %d bytes\n", packetSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RecvExact(s_hostConnectionSocket, &recvBuf[0], packetSize))
|
||||||
{
|
{
|
||||||
app.DebugPrintf("Win64 LAN: Disconnected from host (body)\n");
|
app.DebugPrintf("Win64 LAN: Disconnected from host (body)\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleDataReceived(s_hostSmallId, s_localSmallId, recvBuf, packetSize);
|
HandleDataReceived(s_hostSmallId, s_localSmallId, &recvBuf[0], packetSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] recvBuf;
|
|
||||||
|
|
||||||
s_connected = false;
|
s_connected = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WinsockNetLayer::StartAdvertising(int gamePort, const wchar_t *hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer)
|
bool WinsockNetLayer::StartAdvertising(int gamePort, const wchar_t* hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer)
|
||||||
{
|
{
|
||||||
if (s_advertising) return true;
|
if (s_advertising) return true;
|
||||||
if (!s_initialized) return false;
|
if (!s_initialized) return false;
|
||||||
|
|
@ -614,7 +690,7 @@ bool WinsockNetLayer::StartAdvertising(int gamePort, const wchar_t *hostName, un
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL broadcast = TRUE;
|
BOOL broadcast = TRUE;
|
||||||
setsockopt(s_advertiseSock, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast));
|
setsockopt(s_advertiseSock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
|
||||||
|
|
||||||
s_advertising = true;
|
s_advertising = true;
|
||||||
s_advertiseThread = CreateThread(NULL, 0, AdvertiseThreadProc, NULL, 0, NULL);
|
s_advertiseThread = CreateThread(NULL, 0, AdvertiseThreadProc, NULL, 0, NULL);
|
||||||
|
|
@ -669,8 +745,8 @@ DWORD WINAPI WinsockNetLayer::AdvertiseThreadProc(LPVOID param)
|
||||||
Win64LANBroadcast data = s_advertiseData;
|
Win64LANBroadcast data = s_advertiseData;
|
||||||
LeaveCriticalSection(&s_advertiseLock);
|
LeaveCriticalSection(&s_advertiseLock);
|
||||||
|
|
||||||
int sent = sendto(s_advertiseSock, (const char *)&data, sizeof(data), 0,
|
int sent = sendto(s_advertiseSock, (const char*)&data, sizeof(data), 0,
|
||||||
(struct sockaddr *)&broadcastAddr, sizeof(broadcastAddr));
|
(struct sockaddr*)&broadcastAddr, sizeof(broadcastAddr));
|
||||||
|
|
||||||
if (sent == SOCKET_ERROR && s_advertising)
|
if (sent == SOCKET_ERROR && s_advertising)
|
||||||
{
|
{
|
||||||
|
|
@ -696,7 +772,7 @@ bool WinsockNetLayer::StartDiscovery()
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL reuseAddr = TRUE;
|
BOOL reuseAddr = TRUE;
|
||||||
setsockopt(s_discoverySock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuseAddr, sizeof(reuseAddr));
|
setsockopt(s_discoverySock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseAddr, sizeof(reuseAddr));
|
||||||
|
|
||||||
struct sockaddr_in bindAddr;
|
struct sockaddr_in bindAddr;
|
||||||
memset(&bindAddr, 0, sizeof(bindAddr));
|
memset(&bindAddr, 0, sizeof(bindAddr));
|
||||||
|
|
@ -704,7 +780,7 @@ bool WinsockNetLayer::StartDiscovery()
|
||||||
bindAddr.sin_port = htons(WIN64_LAN_DISCOVERY_PORT);
|
bindAddr.sin_port = htons(WIN64_LAN_DISCOVERY_PORT);
|
||||||
bindAddr.sin_addr.s_addr = INADDR_ANY;
|
bindAddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
if (::bind(s_discoverySock, (struct sockaddr *)&bindAddr, sizeof(bindAddr)) == SOCKET_ERROR)
|
if (::bind(s_discoverySock, (struct sockaddr*)&bindAddr, sizeof(bindAddr)) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
app.DebugPrintf("Win64 LAN: Discovery bind failed: %d\n", WSAGetLastError());
|
app.DebugPrintf("Win64 LAN: Discovery bind failed: %d\n", WSAGetLastError());
|
||||||
closesocket(s_discoverySock);
|
closesocket(s_discoverySock);
|
||||||
|
|
@ -713,7 +789,7 @@ bool WinsockNetLayer::StartDiscovery()
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD timeout = 500;
|
DWORD timeout = 500;
|
||||||
setsockopt(s_discoverySock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout));
|
setsockopt(s_discoverySock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
|
||||||
|
|
||||||
s_discovering = true;
|
s_discovering = true;
|
||||||
s_discoveryThread = CreateThread(NULL, 0, DiscoveryThreadProc, NULL, 0, NULL);
|
s_discoveryThread = CreateThread(NULL, 0, DiscoveryThreadProc, NULL, 0, NULL);
|
||||||
|
|
@ -763,7 +839,7 @@ DWORD WINAPI WinsockNetLayer::DiscoveryThreadProc(LPVOID param)
|
||||||
int senderLen = sizeof(senderAddr);
|
int senderLen = sizeof(senderAddr);
|
||||||
|
|
||||||
int recvLen = recvfrom(s_discoverySock, recvBuf, sizeof(recvBuf), 0,
|
int recvLen = recvfrom(s_discoverySock, recvBuf, sizeof(recvBuf), 0,
|
||||||
(struct sockaddr *)&senderAddr, &senderLen);
|
(struct sockaddr*)&senderAddr, &senderLen);
|
||||||
|
|
||||||
if (recvLen == SOCKET_ERROR)
|
if (recvLen == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
|
|
@ -773,7 +849,7 @@ DWORD WINAPI WinsockNetLayer::DiscoveryThreadProc(LPVOID param)
|
||||||
if (recvLen < (int)sizeof(Win64LANBroadcast))
|
if (recvLen < (int)sizeof(Win64LANBroadcast))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Win64LANBroadcast *broadcast = (Win64LANBroadcast *)recvBuf;
|
Win64LANBroadcast* broadcast = (Win64LANBroadcast*)recvBuf;
|
||||||
if (broadcast->magic != WIN64_LAN_BROADCAST_MAGIC)
|
if (broadcast->magic != WIN64_LAN_BROADCAST_MAGIC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// Code implemented by LCEMP, credit if used on other repos
|
||||||
|
// https://github.com/LCEMP/LCEMP
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
|
|
@ -12,6 +14,7 @@
|
||||||
#define WIN64_NET_DEFAULT_PORT 25565
|
#define WIN64_NET_DEFAULT_PORT 25565
|
||||||
#define WIN64_NET_MAX_CLIENTS 7
|
#define WIN64_NET_MAX_CLIENTS 7
|
||||||
#define WIN64_NET_RECV_BUFFER_SIZE 65536
|
#define WIN64_NET_RECV_BUFFER_SIZE 65536
|
||||||
|
#define WIN64_NET_MAX_PACKET_SIZE (4 * 1024 * 1024)
|
||||||
#define WIN64_LAN_DISCOVERY_PORT 25566
|
#define WIN64_LAN_DISCOVERY_PORT 25566
|
||||||
#define WIN64_LAN_BROADCAST_MAGIC 0x4D434C4E
|
#define WIN64_LAN_BROADCAST_MAGIC 0x4D434C4E
|
||||||
|
|
||||||
|
|
@ -62,11 +65,11 @@ public:
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
|
||||||
static bool HostGame(int port);
|
static bool HostGame(int port, const char* bindIp = NULL);
|
||||||
static bool JoinGame(const char *ip, int port);
|
static bool JoinGame(const char* ip, int port);
|
||||||
|
|
||||||
static bool SendToSmallId(BYTE targetSmallId, const void *data, int dataSize);
|
static bool SendToSmallId(BYTE targetSmallId, const void* data, int dataSize);
|
||||||
static bool SendOnSocket(SOCKET sock, const void *data, int dataSize);
|
static bool SendOnSocket(SOCKET sock, const void* data, int dataSize);
|
||||||
|
|
||||||
static bool IsHosting() { return s_isHost; }
|
static bool IsHosting() { return s_isHost; }
|
||||||
static bool IsConnected() { return s_connected; }
|
static bool IsConnected() { return s_connected; }
|
||||||
|
|
@ -77,12 +80,13 @@ public:
|
||||||
|
|
||||||
static SOCKET GetSocketForSmallId(BYTE smallId);
|
static SOCKET GetSocketForSmallId(BYTE smallId);
|
||||||
|
|
||||||
static void HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsigned char *data, unsigned int dataSize);
|
static void HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsigned char* data, unsigned int dataSize);
|
||||||
|
|
||||||
static bool PopDisconnectedSmallId(BYTE *outSmallId);
|
static bool PopDisconnectedSmallId(BYTE* outSmallId);
|
||||||
static void PushFreeSmallId(BYTE smallId);
|
static void PushFreeSmallId(BYTE smallId);
|
||||||
|
static void CloseConnectionBySmallId(BYTE smallId);
|
||||||
|
|
||||||
static bool StartAdvertising(int gamePort, const wchar_t *hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer);
|
static bool StartAdvertising(int gamePort, const wchar_t* hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer);
|
||||||
static void StopAdvertising();
|
static void StopAdvertising();
|
||||||
static void UpdateAdvertisePlayerCount(BYTE count);
|
static void UpdateAdvertisePlayerCount(BYTE count);
|
||||||
static void UpdateAdvertiseJoinable(bool joinable);
|
static void UpdateAdvertiseJoinable(bool joinable);
|
||||||
|
|
@ -143,5 +147,8 @@ extern bool g_Win64MultiplayerHost;
|
||||||
extern bool g_Win64MultiplayerJoin;
|
extern bool g_Win64MultiplayerJoin;
|
||||||
extern int g_Win64MultiplayerPort;
|
extern int g_Win64MultiplayerPort;
|
||||||
extern char g_Win64MultiplayerIP[256];
|
extern char g_Win64MultiplayerIP[256];
|
||||||
|
extern bool g_Win64DedicatedServer;
|
||||||
|
extern int g_Win64DedicatedServerPort;
|
||||||
|
extern char g_Win64DedicatedServerBindIP[256];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -10,46 +10,11 @@
|
||||||
#include "Minecraft.World/BiomeSource.h"
|
#include "Minecraft.World/BiomeSource.h"
|
||||||
#include "Minecraft.World/LevelType.h"
|
#include "Minecraft.World/LevelType.h"
|
||||||
|
|
||||||
wstring g_playerName;
|
|
||||||
|
|
||||||
CConsoleMinecraftApp app;
|
CConsoleMinecraftApp app;
|
||||||
|
|
||||||
static void LoadPlayerName()
|
|
||||||
{
|
|
||||||
if (!g_playerName.empty()) return;
|
|
||||||
g_playerName = L"Windows";
|
|
||||||
|
|
||||||
char exePath[MAX_PATH] = {};
|
|
||||||
GetModuleFileNameA(NULL, exePath, MAX_PATH);
|
|
||||||
char *lastSlash = strrchr(exePath, '\\');
|
|
||||||
if (lastSlash) *(lastSlash + 1) = '\0';
|
|
||||||
char filePath[MAX_PATH] = {};
|
|
||||||
_snprintf_s(filePath, sizeof(filePath), _TRUNCATE, "%susername.txt", exePath);
|
|
||||||
|
|
||||||
FILE *f = NULL;
|
|
||||||
if (fopen_s(&f, filePath, "r") == 0 && f)
|
|
||||||
{
|
|
||||||
char buf[128] = {};
|
|
||||||
if (fgets(buf, sizeof(buf), f))
|
|
||||||
{
|
|
||||||
int len = (int)strlen(buf);
|
|
||||||
while (len > 0 && (buf[len-1] == '\n' || buf[len-1] == '\r' || buf[len-1] == ' '))
|
|
||||||
buf[--len] = '\0';
|
|
||||||
if (len > 0)
|
|
||||||
{
|
|
||||||
wchar_t wbuf[128] = {};
|
|
||||||
mbstowcs(wbuf, buf, 127);
|
|
||||||
g_playerName = wbuf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CConsoleMinecraftApp::CConsoleMinecraftApp() : CMinecraftApp()
|
CConsoleMinecraftApp::CConsoleMinecraftApp() : CMinecraftApp()
|
||||||
{
|
{
|
||||||
m_bShutdown = false;
|
m_bShutdown = false;
|
||||||
LoadPlayerName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConsoleMinecraftApp::SetRichPresenceContext(int iPad, int contextId)
|
void CConsoleMinecraftApp::SetRichPresenceContext(int iPad, int contextId)
|
||||||
|
|
@ -110,8 +75,8 @@ void CConsoleMinecraftApp::TemporaryCreateGameStart()
|
||||||
Minecraft *pMinecraft=Minecraft::GetInstance();
|
Minecraft *pMinecraft=Minecraft::GetInstance();
|
||||||
app.ReleaseSaveThumbnail();
|
app.ReleaseSaveThumbnail();
|
||||||
ProfileManager.SetLockedProfile(0);
|
ProfileManager.SetLockedProfile(0);
|
||||||
LoadPlayerName();
|
extern wchar_t g_Win64UsernameW[17];
|
||||||
pMinecraft->user->name = g_playerName;
|
pMinecraft->user->name = g_Win64UsernameW;
|
||||||
app.ApplyGameSettingsChanged(0);
|
app.ApplyGameSettingsChanged(0);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////// From CScene_MultiGameJoinLoad::OnInit
|
////////////////////////////////////////////////////////////////////////////////////////////// From CScene_MultiGameJoinLoad::OnInit
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
|
@ -1658,7 +1658,8 @@ HRESULT CConsoleMinecraftApp::NavigateToScene(int iPad,EUIScene eScene, void *in
|
||||||
|
|
||||||
// If you're navigating to the multigamejoinload, and the player hasn't seen the updates message yet, display it now
|
// If you're navigating to the multigamejoinload, and the player hasn't seen the updates message yet, display it now
|
||||||
// display this message the first 3 times
|
// display this message the first 3 times
|
||||||
if((eScene==eUIScene_LoadOrJoinMenu) && (bSeenUpdateTextThisSession==false) && ( app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplayUpdateMessage)!=0))
|
// todo: re-enable if we fix this menu, for now its just blank!
|
||||||
|
if(false && (eScene==eUIScene_LoadOrJoinMenu) && (bSeenUpdateTextThisSession==false) && ( app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplayUpdateMessage)!=0))
|
||||||
{
|
{
|
||||||
eScene=eUIScene_NewUpdateMessage;
|
eScene=eUIScene_NewUpdateMessage;
|
||||||
bSeenUpdateTextThisSession=true;
|
bSeenUpdateTextThisSession=true;
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,12 @@ void glLoadIdentity()
|
||||||
RenderManager.MatrixSetIdentity();
|
RenderManager.MatrixSetIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern UINT g_ScreenWidth;
|
extern int g_iScreenWidth;
|
||||||
extern UINT g_ScreenHeight;
|
extern int g_iScreenHeight;
|
||||||
|
|
||||||
void gluPerspective(float fovy, float aspect, float zNear, float zFar)
|
void gluPerspective(float fovy, float aspect, float zNear, float zFar)
|
||||||
{
|
{
|
||||||
float dynamicAspect = (float)g_ScreenWidth / (float)g_ScreenHeight;
|
float dynamicAspect = (float)g_iScreenWidth / (float)g_iScreenHeight;
|
||||||
RenderManager.MatrixPerspective(fovy, dynamicAspect, zNear, zFar);
|
RenderManager.MatrixPerspective(fovy, dynamicAspect, zNear, zFar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,41 +3,98 @@
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
#include "Windows64/KeyboardMouseInput.h"
|
#include "Windows64/KeyboardMouseInput.h"
|
||||||
|
|
||||||
|
static const int s_keyToVK[] = {
|
||||||
|
'A', // KEY_A = 0
|
||||||
|
'B', // KEY_B = 1
|
||||||
|
'C', // KEY_C = 2
|
||||||
|
'D', // KEY_D = 3
|
||||||
|
'E', // KEY_E = 4
|
||||||
|
'F', // KEY_F = 5
|
||||||
|
'G', // KEY_G = 6
|
||||||
|
'H', // KEY_H = 7
|
||||||
|
'I', // KEY_I = 8
|
||||||
|
'J', // KEY_J = 9
|
||||||
|
'K', // KEY_K = 10
|
||||||
|
'L', // KEY_L = 11
|
||||||
|
'M', // KEY_M = 12
|
||||||
|
'N', // KEY_N = 13
|
||||||
|
'O', // KEY_O = 14
|
||||||
|
'P', // KEY_P = 15
|
||||||
|
'Q', // KEY_Q = 16
|
||||||
|
'R', // KEY_R = 17
|
||||||
|
'S', // KEY_S = 18
|
||||||
|
'T', // KEY_T = 19
|
||||||
|
'U', // KEY_U = 20
|
||||||
|
'V', // KEY_V = 21
|
||||||
|
'W', // KEY_W = 22
|
||||||
|
'X', // KEY_X = 23
|
||||||
|
'Y', // KEY_Y = 24
|
||||||
|
'Z', // KEY_Z = 25
|
||||||
|
VK_SPACE, // KEY_SPACE = 26
|
||||||
|
VK_LSHIFT, // KEY_LSHIFT = 27
|
||||||
|
VK_ESCAPE, // KEY_ESCAPE = 28
|
||||||
|
VK_BACK, // KEY_BACK = 29
|
||||||
|
VK_RETURN, // KEY_RETURN = 30
|
||||||
|
VK_RSHIFT, // KEY_RSHIFT = 31
|
||||||
|
VK_UP, // KEY_UP = 32
|
||||||
|
VK_DOWN, // KEY_DOWN = 33
|
||||||
|
VK_TAB, // KEY_TAB = 34
|
||||||
|
'1', // KEY_1 = 35
|
||||||
|
'2', // KEY_2 = 36
|
||||||
|
'3', // KEY_3 = 37
|
||||||
|
'4', // KEY_4 = 38
|
||||||
|
'5', // KEY_5 = 39
|
||||||
|
'6', // KEY_6 = 40
|
||||||
|
'7', // KEY_7 = 41
|
||||||
|
'8', // KEY_8 = 42
|
||||||
|
'9', // KEY_9 = 43
|
||||||
|
VK_F1, // KEY_F1 = 44
|
||||||
|
VK_F3, // KEY_F3 = 45
|
||||||
|
VK_F4, // KEY_F4 = 46
|
||||||
|
VK_F5, // KEY_F5 = 47
|
||||||
|
VK_F6, // KEY_F6 = 48
|
||||||
|
VK_F8, // KEY_F8 = 49
|
||||||
|
VK_F9, // KEY_F9 = 50
|
||||||
|
VK_F11, // KEY_F11 = 51
|
||||||
|
VK_ADD, // KEY_ADD = 52
|
||||||
|
VK_SUBTRACT,// KEY_SUBTRACT = 53
|
||||||
|
VK_LEFT, // KEY_LEFT = 54
|
||||||
|
VK_RIGHT, // KEY_RIGHT = 55
|
||||||
|
};
|
||||||
|
static const int s_keyToVKCount = sizeof(s_keyToVK) / sizeof(s_keyToVK[0]);
|
||||||
|
|
||||||
|
int Keyboard::toVK(int keyConst)
|
||||||
|
{
|
||||||
|
if (keyConst >= 0 && keyConst < s_keyToVKCount)
|
||||||
|
return s_keyToVK[keyConst];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Keyboard::isKeyDown(int keyCode)
|
||||||
|
{
|
||||||
|
int vk = toVK(keyCode);
|
||||||
|
if (vk > 0)
|
||||||
|
return g_KBMInput.IsKeyDown(vk);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int Mouse::getX()
|
int Mouse::getX()
|
||||||
{
|
{
|
||||||
return KMInput.GetMouseX();
|
return g_KBMInput.GetMouseX();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Mouse::getY()
|
int Mouse::getY()
|
||||||
{
|
{
|
||||||
// Return Y in bottom-up coordinates (OpenGL convention, matching original Java LWJGL Mouse)
|
// Return Y in bottom-up coordinates (OpenGL convention, matching original Java LWJGL Mouse)
|
||||||
|
extern HWND g_hWnd;
|
||||||
RECT rect;
|
RECT rect;
|
||||||
GetClientRect(KMInput.GetHWnd(), &rect);
|
GetClientRect(g_hWnd, &rect);
|
||||||
return (rect.bottom - 1) - KMInput.GetMouseY();
|
return (rect.bottom - 1) - g_KBMInput.GetMouseY();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mouse::isButtonDown(int button)
|
bool Mouse::isButtonDown(int button)
|
||||||
{
|
{
|
||||||
return KMInput.IsMouseDown(button);
|
return g_KBMInput.IsMouseButtonDown(button);
|
||||||
}
|
|
||||||
|
|
||||||
bool Keyboard::isKeyDown(int key)
|
|
||||||
{
|
|
||||||
// Map Keyboard constants to Windows virtual key codes
|
|
||||||
if (key == Keyboard::KEY_LSHIFT) return KMInput.IsKeyDown(VK_LSHIFT);
|
|
||||||
if (key == Keyboard::KEY_RSHIFT) return KMInput.IsKeyDown(VK_RSHIFT);
|
|
||||||
if (key == Keyboard::KEY_ESCAPE) return KMInput.IsKeyDown(VK_ESCAPE);
|
|
||||||
if (key == Keyboard::KEY_RETURN) return KMInput.IsKeyDown(VK_RETURN);
|
|
||||||
if (key == Keyboard::KEY_BACK) return KMInput.IsKeyDown(VK_BACK);
|
|
||||||
if (key == Keyboard::KEY_SPACE) return KMInput.IsKeyDown(VK_SPACE);
|
|
||||||
if (key == Keyboard::KEY_TAB) return KMInput.IsKeyDown(VK_TAB);
|
|
||||||
if (key == Keyboard::KEY_UP) return KMInput.IsKeyDown(VK_UP);
|
|
||||||
if (key == Keyboard::KEY_DOWN) return KMInput.IsKeyDown(VK_DOWN);
|
|
||||||
if (key == Keyboard::KEY_LEFT) return KMInput.IsKeyDown(VK_LEFT);
|
|
||||||
if (key == Keyboard::KEY_RIGHT) return KMInput.IsKeyDown(VK_RIGHT);
|
|
||||||
if (key >= Keyboard::KEY_A && key <= Keyboard::KEY_Z)
|
|
||||||
return KMInput.IsKeyDown('A' + (key - Keyboard::KEY_A));
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -187,12 +187,13 @@ public:
|
||||||
static void create() {}
|
static void create() {}
|
||||||
static void destroy() {}
|
static void destroy() {}
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
static bool isKeyDown(int key);
|
static bool isKeyDown(int keyCode);
|
||||||
#else
|
#else
|
||||||
static bool isKeyDown(int) {return false;}
|
static bool isKeyDown(int) { return false; }
|
||||||
#endif
|
#endif
|
||||||
static wstring getKeyName(int) { return L"KEYNAME"; }
|
static wstring getKeyName(int) { return L"KEYNAME"; }
|
||||||
static void enableRepeatEvents(bool) {}
|
static void enableRepeatEvents(bool) {}
|
||||||
|
|
||||||
static const int KEY_A = 0;
|
static const int KEY_A = 0;
|
||||||
static const int KEY_B = 1;
|
static const int KEY_B = 1;
|
||||||
static const int KEY_C = 2;
|
static const int KEY_C = 2;
|
||||||
|
|
@ -228,8 +229,32 @@ public:
|
||||||
static const int KEY_UP = 32;
|
static const int KEY_UP = 32;
|
||||||
static const int KEY_DOWN = 33;
|
static const int KEY_DOWN = 33;
|
||||||
static const int KEY_TAB = 34;
|
static const int KEY_TAB = 34;
|
||||||
static const int KEY_LEFT = 35;
|
static const int KEY_1 = 35;
|
||||||
static const int KEY_RIGHT = 36;
|
static const int KEY_2 = 36;
|
||||||
|
static const int KEY_3 = 37;
|
||||||
|
static const int KEY_4 = 38;
|
||||||
|
static const int KEY_5 = 39;
|
||||||
|
static const int KEY_6 = 40;
|
||||||
|
static const int KEY_7 = 41;
|
||||||
|
static const int KEY_8 = 42;
|
||||||
|
static const int KEY_9 = 43;
|
||||||
|
static const int KEY_F1 = 44;
|
||||||
|
static const int KEY_F3 = 45;
|
||||||
|
static const int KEY_F4 = 46;
|
||||||
|
static const int KEY_F5 = 47;
|
||||||
|
static const int KEY_F6 = 48;
|
||||||
|
static const int KEY_F8 = 49;
|
||||||
|
static const int KEY_F9 = 50;
|
||||||
|
static const int KEY_F11 = 51;
|
||||||
|
static const int KEY_ADD = 52;
|
||||||
|
static const int KEY_SUBTRACT = 53;
|
||||||
|
static const int KEY_LEFT = 54;
|
||||||
|
static const int KEY_RIGHT = 55;
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
// Map LWJGL-style key constant to Windows VK code
|
||||||
|
static int toVK(int keyConst);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class Mouse
|
class Mouse
|
||||||
|
|
|
||||||
|
|
@ -749,7 +749,7 @@ void ConsoleSaveFileOriginal::Flush(bool autosave, bool updateThumbnail )
|
||||||
PBYTE pbDataSaveImage=NULL;
|
PBYTE pbDataSaveImage=NULL;
|
||||||
DWORD dwDataSizeSaveImage=0;
|
DWORD dwDataSizeSaveImage=0;
|
||||||
|
|
||||||
#if ( defined _XBOX || defined _DURANGO )
|
#if ( defined _XBOX || defined _DURANGO || defined _WINDOWS64 )
|
||||||
app.GetSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize);
|
app.GetSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize);
|
||||||
#elif ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ )
|
#elif ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ )
|
||||||
app.GetSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize,&pbDataSaveImage,&dwDataSizeSaveImage);
|
app.GetSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize,&pbDataSaveImage,&dwDataSizeSaveImage);
|
||||||
|
|
|
||||||
|
|
@ -479,7 +479,7 @@ void EntityHorse::createInventory()
|
||||||
|
|
||||||
void EntityHorse::updateEquipment()
|
void EntityHorse::updateEquipment()
|
||||||
{
|
{
|
||||||
if (!level->isClientSide)
|
if (level && !level->isClientSide)
|
||||||
{
|
{
|
||||||
setSaddled(inventory->getItem(INV_SLOT_SADDLE) != NULL);
|
setSaddled(inventory->getItem(INV_SLOT_SADDLE) != NULL);
|
||||||
if (canWearArmor())
|
if (canWearArmor())
|
||||||
|
|
|
||||||
|
|
@ -596,7 +596,14 @@ void MapItemSavedData::mergeInMapData(shared_ptr<MapItemSavedData> dataToAdd)
|
||||||
|
|
||||||
void MapItemSavedData::removeItemFrameDecoration(shared_ptr<ItemInstance> item)
|
void MapItemSavedData::removeItemFrameDecoration(shared_ptr<ItemInstance> item)
|
||||||
{
|
{
|
||||||
AUTO_VAR(frameDecoration, nonPlayerDecorations.find( item->getFrame()->entityId ) );
|
if ( !item )
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::shared_ptr<ItemFrame> frame = item->getFrame();
|
||||||
|
if ( !frame )
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto frameDecoration = nonPlayerDecorations.find(frame->entityId);
|
||||||
if ( frameDecoration != nonPlayerDecorations.end() )
|
if ( frameDecoration != nonPlayerDecorations.end() )
|
||||||
{
|
{
|
||||||
delete frameDecoration->second;
|
delete frameDecoration->second;
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,7 @@
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
<PlatformToolset>v143</PlatformToolset>
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'" Label="Configuration">
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
|
@ -1256,6 +1257,7 @@
|
||||||
<UseFullPaths>false</UseFullPaths>
|
<UseFullPaths>false</UseFullPaths>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
|
<AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
|
@ -1338,7 +1340,7 @@
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<Optimization>Full</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<ExceptionHandling>Sync</ExceptionHandling>
|
<ExceptionHandling>Sync</ExceptionHandling>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
|
<PrecompiledHeaderOutputFile>$(OutDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
|
||||||
|
|
@ -1351,6 +1353,10 @@
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
|
||||||
|
<StringPooling>true</StringPooling>
|
||||||
|
<AdditionalOptions>/FS /Ob3 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
|
@ -4952,4 +4958,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ bool NearestAttackableTargetGoal::DistComp::operator() (shared_ptr<Entity> e1, s
|
||||||
double distSqr2 = source->distanceToSqr(e2);
|
double distSqr2 = source->distanceToSqr(e2);
|
||||||
if (distSqr1 < distSqr2) return true;
|
if (distSqr1 < distSqr2) return true;
|
||||||
if (distSqr1 > distSqr2) return false;
|
if (distSqr1 > distSqr2) return false;
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NearestAttackableTargetGoal::NearestAttackableTargetGoal(PathfinderMob *mob, const type_info& targetType, int randomInterval, bool mustSee, bool mustReach /*= false*/, EntitySelector *entitySelector /* =NULL */)
|
NearestAttackableTargetGoal::NearestAttackableTargetGoal(PathfinderMob *mob, const type_info& targetType, int randomInterval, bool mustSee, bool mustReach /*= false*/, EntitySelector *entitySelector /* =NULL */)
|
||||||
|
|
|
||||||
|
|
@ -627,6 +627,7 @@ void Player::ride(shared_ptr<Entity> e)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this->abilities.flying = false;
|
||||||
LivingEntity::ride(e);
|
LivingEntity::ride(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
38
README.md
38
README.md
|
|
@ -1,6 +1,6 @@
|
||||||
# MinecraftConsoles
|
# MinecraftConsoles
|
||||||
|
|
||||||
[](https://discord.gg/5CSzhc9t)
|
[](https://discord.gg/jrum7HhegA)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
@ -20,10 +20,11 @@ This project contains the source code of Minecraft Legacy Console Edition v1.6.0
|
||||||
- Fixed compilation and execution in both Debug and Release mode on Windows using Visual Studio 2022
|
- Fixed compilation and execution in both Debug and Release mode on Windows using Visual Studio 2022
|
||||||
- Added support for keyboard and mouse input
|
- Added support for keyboard and mouse input
|
||||||
- Added fullscreen mode support (toggle using F11)
|
- Added fullscreen mode support (toggle using F11)
|
||||||
- Disabled V-Sync for better performance
|
- (WIP) Disabled V-Sync for better performance
|
||||||
- Added a high-resolution timer path on Windows for smoother high-FPS gameplay timing
|
- Added a high-resolution timer path on Windows for smoother high-FPS gameplay timing
|
||||||
- Device's screen resolution will be used as the game resolution instead of using a fixed resolution (1920x1080)
|
- Device's screen resolution will be used as the game resolution instead of using a fixed resolution (1920x1080)
|
||||||
- LAN Multiplayer & Discovery
|
- LAN Multiplayer & Discovery
|
||||||
|
- Added persistent username system via "username.txt"
|
||||||
|
|
||||||
## Multiplayer
|
## Multiplayer
|
||||||
|
|
||||||
|
|
@ -33,16 +34,30 @@ Basic LAN multiplayer is available on the Windows build
|
||||||
- Other players on the same LAN can discover the session from the in-game Join Game menu
|
- Other players on the same LAN can discover the session from the in-game Join Game menu
|
||||||
- Game connections use TCP port `25565` by default
|
- Game connections use TCP port `25565` by default
|
||||||
- LAN discovery uses UDP port `25566`
|
- LAN discovery uses UDP port `25566`
|
||||||
- You can override your in-game username at launch with `-name`
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
Minecraft.Client.exe -name Steve
|
|
||||||
```
|
|
||||||
|
|
||||||
This feature is based on [LCEMP](https://github.com/LCEMP/LCEMP/)
|
This feature is based on [LCEMP](https://github.com/LCEMP/LCEMP/)
|
||||||
|
|
||||||
|
### Launch Arguments
|
||||||
|
|
||||||
|
| Argument | Description |
|
||||||
|
|--------------------|-----------------------------------------------------------------------------------------------------|
|
||||||
|
| `-name <username>` | Sets your in-game username |
|
||||||
|
| `-server` | Launches a headless server instead of the client |
|
||||||
|
| `-ip <address>` | Client mode: manually connect to an IP. Server mode: override the bind IP from `server.properties` |
|
||||||
|
| `-port <port>` | Client mode: override the join port. Server mode: override the listen port from `server.properties` |
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
Minecraft.Client.exe -name Steve -ip 192.168.0.25 -port 25565
|
||||||
|
```
|
||||||
|
|
||||||
|
Headless server example:
|
||||||
|
```
|
||||||
|
Minecraft.Client.exe -server -ip 0.0.0.0 -port 25565
|
||||||
|
```
|
||||||
|
|
||||||
|
The headless server also reads and writes `server.properties` in the working directory. If `-ip` / `-port` are omitted in `-server` mode, it falls back to `server-ip` / `server-port` from that file. Dedicated-server host options such as `trust-players`, `pvp`, `fire-spreads`, `tnt`, `difficulty`, `gamemode`, `spawn-animals`, and `spawn-npcs` are persisted there as well.
|
||||||
|
|
||||||
## Controls (Keyboard & Mouse)
|
## Controls (Keyboard & Mouse)
|
||||||
|
|
||||||
- **Movement**: `W` `A` `S` `D`
|
- **Movement**: `W` `A` `S` `D`
|
||||||
|
|
@ -51,18 +66,19 @@ This feature is based on [LCEMP](https://github.com/LCEMP/LCEMP/)
|
||||||
- **Sprint**: `Ctrl` (Hold) or Double-tap `W`
|
- **Sprint**: `Ctrl` (Hold) or Double-tap `W`
|
||||||
- **Inventory**: `E`
|
- **Inventory**: `E`
|
||||||
- **Drop Item**: `Q`
|
- **Drop Item**: `Q`
|
||||||
- **Crafting**: `C`
|
- **Crafting**: `C` Use `Q` and `E` to move through tabs (cycles Left/Right)
|
||||||
- **Toggle View (FPS/TPS)**: `F5`
|
- **Toggle View (FPS/TPS)**: `F5`
|
||||||
- **Fullscreen**: `F11`
|
- **Fullscreen**: `F11`
|
||||||
- **Pause Menu**: `Esc`
|
- **Pause Menu**: `Esc`
|
||||||
- **Toggle Mouse Capture**: `Left Alt` (for debugging)
|
|
||||||
- **Attack / Destroy**: `Left Click`
|
- **Attack / Destroy**: `Left Click`
|
||||||
- **Use / Place**: `Right Click`
|
- **Use / Place**: `Right Click`
|
||||||
- **Select Item**: `Mouse Wheel` or keys `1` to `9`
|
- **Select Item**: `Mouse Wheel` or keys `1` to `9`
|
||||||
- **Accept or Decline Tutorial hints**: `Enter` to accept and `B` to decline
|
- **Accept or Decline Tutorial hints**: `Enter` to accept and `B` to decline
|
||||||
- **Game Info (Player list and Host Options)**: `TAB`
|
- **Game Info (Player list and Host Options)**: `TAB`
|
||||||
|
- **Toggle HUD**: `F1`
|
||||||
- **Toggle Debug Info**: `F3`
|
- **Toggle Debug Info**: `F3`
|
||||||
- **Open Debug Overlay**: `F4`
|
- **Open Debug Overlay**: `F4`
|
||||||
|
- **Toggle Debug Console**: `F6`
|
||||||
|
|
||||||
## Build & Run
|
## Build & Run
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue