Compare commits
13 Commits
main
...
feat/repla
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e50603e68f | ||
|
|
d2bc3342dc | ||
|
|
5422191ed4 | ||
|
|
7749d61daf | ||
|
|
62c2ed5cf6 | ||
|
|
3132ad122d | ||
|
|
f76a6a5e1c | ||
|
|
75d4afa783 | ||
|
|
a3588c5a6d | ||
|
|
323d4ec110 | ||
|
|
64909f236e | ||
|
|
f685015942 | ||
|
|
50d37cdd3c |
@@ -1,53 +0,0 @@
|
||||
---
|
||||
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 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
# 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.
|
||||
|
||||
## Description
|
||||
<!-- Briefly describe the changes this PR introduces. -->
|
||||
Briefly describe the changes this PR introduces.
|
||||
|
||||
## Changes
|
||||
|
||||
### Previous Behavior
|
||||
<!-- Describe how the code behaved before this change. -->
|
||||
*Describe how the code behaved before this change.*
|
||||
|
||||
### 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
|
||||
<!-- Describe how the code behaves after this change. -->
|
||||
*Describe how the code behaves after this change.*
|
||||
|
||||
### 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
|
||||
- Fixes #[issue-number]
|
||||
|
||||
8
.github/workflows/nightly.yml
vendored
8
.github/workflows/nightly.yml
vendored
@@ -8,7 +8,6 @@ on:
|
||||
paths-ignore:
|
||||
- '.gitignore'
|
||||
- '*.md'
|
||||
- '.github/*.md'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -36,8 +35,5 @@ jobs:
|
||||
with:
|
||||
tag_name: nightly
|
||||
name: Nightly Release
|
||||
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
|
||||
body: Compiled with MSVC v14.44.35207 in Release mode with Whole Program Optimization, as well as `/O2 /Ot /Oi /Ob3 /GF`. (So far the floating point model is `/fp:strict` to avoid undefined behavior before we refactor for performance). Requires at least Windows 7 and DirectX 11 compatible GPU to run.
|
||||
files: LCEWindows64.zip
|
||||
|
||||
@@ -79,12 +79,12 @@ target_link_libraries(MinecraftClient PRIVATE
|
||||
$<$<CONFIG:Debug>:
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC_d.lib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_d.lib"
|
||||
>
|
||||
$<$<NOT:$<CONFIG:Debug>>:
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Input.lib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage.lib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC.lib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render.lib"
|
||||
>
|
||||
)
|
||||
|
||||
|
||||
@@ -55,12 +55,6 @@
|
||||
#endif
|
||||
#include "DLCTexturePack.h"
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
#include "Xbox\Network\NetworkPlayerXbox.h"
|
||||
#include "Common\Network\PlatformNetworkManagerStub.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _DURANGO
|
||||
#include "..\Minecraft.World\DurangoStats.h"
|
||||
#include "..\Minecraft.World\GenericStats.h"
|
||||
@@ -427,6 +421,7 @@ void ClientConnection::handleAddEntity(shared_ptr<AddEntityPacket> packet)
|
||||
{
|
||||
case AddEntityPacket::MINECART:
|
||||
e = Minecart::createMinecart(level, x, y, z, packet->data);
|
||||
break;
|
||||
case AddEntityPacket::FISH_HOOK:
|
||||
{
|
||||
// 4J Stu - Brought forward from 1.4 to be able to drop XP from fishing
|
||||
@@ -449,7 +444,7 @@ void ClientConnection::handleAddEntity(shared_ptr<AddEntityPacket> packet)
|
||||
}
|
||||
}
|
||||
|
||||
if (owner != NULL && owner->instanceof(eTYPE_PLAYER))
|
||||
if (owner->instanceof(eTYPE_PLAYER))
|
||||
{
|
||||
shared_ptr<Player> player = dynamic_pointer_cast<Player>(owner);
|
||||
shared_ptr<FishingHook> hook = shared_ptr<FishingHook>( new FishingHook(level, x, y, z, player) );
|
||||
@@ -798,28 +793,7 @@ void ClientConnection::handleAddPlayer(shared_ptr<AddPlayerPacket> packet)
|
||||
if (networkPlayer != NULL) player->m_displayName = networkPlayer->GetDisplayName();
|
||||
#else
|
||||
// On all other platforms display name is just gamertag so don't check with the network manager
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
player->m_displayName = player->name;
|
||||
#endif
|
||||
|
||||
// printf("\t\t\t\t%d: Add player\n",packet->id,packet->yRot);
|
||||
@@ -964,39 +938,6 @@ void ClientConnection::handleMoveEntitySmall(shared_ptr<MoveEntityPacketSmall> p
|
||||
|
||||
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++)
|
||||
{
|
||||
level->removeEntity(packet->ids[i]);
|
||||
|
||||
@@ -829,7 +829,6 @@ enum EControllerActions
|
||||
ACTION_MENU_OTHER_STICK_LEFT,
|
||||
ACTION_MENU_OTHER_STICK_RIGHT,
|
||||
ACTION_MENU_PAUSEMENU,
|
||||
ACTION_MENU_QUICK_MOVE,
|
||||
|
||||
#ifdef _DURANGO
|
||||
ACTION_MENU_GTC_PAUSE,
|
||||
|
||||
@@ -1978,7 +1978,7 @@ bool CGameNetworkManager::AllowedToPlayMultiplayer(int playerIdx)
|
||||
return ProfileManager.AllowedToPlayMultiplayer(playerIdx);
|
||||
}
|
||||
|
||||
const char *CGameNetworkManager::GetOnlineName(int playerIdx)
|
||||
char *CGameNetworkManager::GetOnlineName(int playerIdx)
|
||||
{
|
||||
return ProfileManager.GetGamertag(playerIdx);
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ private:
|
||||
int GetLockedProfile();
|
||||
bool IsSignedInLive(int playerIdx);
|
||||
bool AllowedToPlayMultiplayer(int playerIdx);
|
||||
const char *GetOnlineName(int playerIdx);
|
||||
char *GetOnlineName(int playerIdx);
|
||||
|
||||
C4JThread::Event* m_hServerStoppedEvent;
|
||||
C4JThread::Event* m_hServerReadyEvent;
|
||||
|
||||
@@ -1304,60 +1304,42 @@ bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool b
|
||||
#endif
|
||||
|
||||
int buttonNum=0; // 0 = LeftMouse, 1 = RightMouse
|
||||
BOOL quickKeyHeld=false; // Represents shift key on PC
|
||||
BOOL quickKeyDown = false; // Represents shift key on PC
|
||||
BOOL validKeyPress = false;
|
||||
BOOL quickKeyHeld=FALSE; // Represents shift key on PC
|
||||
|
||||
BOOL validKeyPress = FALSE;
|
||||
bool itemEditorKeyPress = false;
|
||||
|
||||
// Ignore input from other players
|
||||
//if(pMinecraft->player->GetXboxPad()!=pInputData->UserIndex) return S_OK;
|
||||
|
||||
|
||||
switch(iAction)
|
||||
{
|
||||
#ifdef _DEBUG_MENUS_ENABLED
|
||||
case ACTION_MENU_OTHER_STICK_PRESS:
|
||||
itemEditorKeyPress = TRUE;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
case ACTION_MENU_A:
|
||||
#ifdef __ORBIS__
|
||||
case ACTION_MENU_TOUCHPAD_PRESS:
|
||||
#endif
|
||||
if (!bRepeat)
|
||||
if(!bRepeat)
|
||||
{
|
||||
validKeyPress = TRUE;
|
||||
|
||||
// Standard left click
|
||||
buttonNum = 0;
|
||||
if (KMInput.IsKeyDown(VK_SHIFT))
|
||||
quickKeyHeld = FALSE;
|
||||
|
||||
if( IsSectionSlotList( m_eCurrSection ) )
|
||||
{
|
||||
{
|
||||
validKeyPress = TRUE;
|
||||
int currentIndex = getCurrentIndex( m_eCurrSection ) - getSectionStartOffset(m_eCurrSection);
|
||||
|
||||
// Shift and left click
|
||||
buttonNum = 0;
|
||||
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);
|
||||
}
|
||||
//
|
||||
bool bSlotHasItem = !isSlotEmpty(m_eCurrSection, currentIndex);
|
||||
if ( bSlotHasItem )
|
||||
ui.PlayUISFX(eSFX_Press);
|
||||
}
|
||||
//
|
||||
}
|
||||
break;
|
||||
case ACTION_MENU_X:
|
||||
@@ -1379,7 +1361,6 @@ bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool b
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTION_MENU_Y:
|
||||
if(!bRepeat)
|
||||
{
|
||||
|
||||
@@ -1012,7 +1012,6 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
|
||||
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: kbDown = KMInput.IsKeyDown('Q'); kbPressed = KMInput.IsKeyPressed('Q'); kbReleased = KMInput.IsKeyReleased('Q'); break;
|
||||
case ACTION_MENU_RIGHT_SCROLL: kbDown = KMInput.IsKeyDown('E'); kbPressed = KMInput.IsKeyPressed('E'); kbReleased = KMInput.IsKeyReleased('E'); break;
|
||||
case ACTION_MENU_QUICK_MOVE: kbDown = KMInput.IsKeyDown(VK_SHIFT); kbPressed = KMInput.IsKeyPressed(VK_SHIFT); kbReleased = KMInput.IsKeyReleased(VK_SHIFT); break;
|
||||
}
|
||||
pressed = pressed || kbPressed;
|
||||
released = released || kbReleased;
|
||||
@@ -1445,7 +1444,7 @@ GDrawTexture * RADLINK UIController::TextureSubstitutionCreateCallback ( void *
|
||||
|
||||
// 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
|
||||
#if (defined __ORBIS__ || defined _DURANGO || defined _WINDOWS64 )
|
||||
#if (defined __ORBIS__ || defined _DURANGO )
|
||||
*width = 96;
|
||||
*height = 96;
|
||||
#else
|
||||
|
||||
@@ -33,11 +33,6 @@ UIScene_AbstractContainerMenu::UIScene_AbstractContainerMenu(int iPad, UILayer *
|
||||
m_bHasMousePosition = false;
|
||||
m_lastMouseX = 0;
|
||||
m_lastMouseY = 0;
|
||||
|
||||
for (int btn = 0; btn < 3; btn++)
|
||||
{
|
||||
KMInput.ConsumeMousePress(btn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -214,8 +209,8 @@ void UIScene_AbstractContainerMenu::tick()
|
||||
scrollDelta = KMInput.ConsumeScrollDelta();
|
||||
|
||||
// Convert mouse position to movie coordinates using the movie/client ratio
|
||||
float mx = (float)mouseX * ((float)m_movieWidth / (float)clientWidth) - (float)m_controlMainPanel.getXPos();
|
||||
float my = (float)mouseY * ((float)m_movieHeight / (float)clientHeight) - (float)m_controlMainPanel.getYPos();
|
||||
float mx = (float)mouseX * ((float)m_movieWidth / (float)clientWidth);
|
||||
float my = (float)mouseY * ((float)m_movieHeight / (float)clientHeight);
|
||||
|
||||
rawMouseMovieX = mx;
|
||||
rawMouseMovieY = my;
|
||||
@@ -306,13 +301,8 @@ void UIScene_AbstractContainerMenu::tick()
|
||||
// Scale mouse client coords to the Iggy display space (which was set to getRenderDimensions())
|
||||
RECT clientRect;
|
||||
GetClientRect(KMInput.GetHWnd(), &clientRect);
|
||||
float mouseMovieX = (float)KMInput.GetMouseX() * ((float)m_movieWidth / (float)clientRect.right);
|
||||
float mouseMovieY = (float)KMInput.GetMouseY() * ((float)m_movieHeight / (float)clientRect.bottom);
|
||||
float mouseLocalX = mouseMovieX - (float)m_controlMainPanel.getXPos();
|
||||
float mouseLocalY = mouseMovieY - (float)m_controlMainPanel.getYPos();
|
||||
|
||||
x = (S32)(mouseLocalX * ((float)width / m_movieWidth));
|
||||
y = (S32)(mouseLocalY * ((float)height / m_movieHeight));
|
||||
x = (S32)((float)KMInput.GetMouseX() * ((float)width / (float)clientRect.right));
|
||||
y = (S32)((float)KMInput.GetMouseY() * ((float)height / (float)clientRect.bottom));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -77,7 +77,12 @@ void EnderDragonRenderer::renderModel(shared_ptr<LivingEntity> _mob, float wp, f
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
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);
|
||||
#else
|
||||
model->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, false);
|
||||
#endif
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
@@ -199,10 +199,11 @@ DWORD IQNetPlayer::GetSendQueueSize(IQNetPlayer * player, DWORD dwFlags) { retur
|
||||
DWORD IQNetPlayer::GetCurrentRtt() { return 0; }
|
||||
bool IQNetPlayer::IsHost() { return m_isHostPlayer; }
|
||||
bool IQNetPlayer::IsGuest() { return false; }
|
||||
bool IQNetPlayer::IsLocal() { return !m_isRemote; }
|
||||
bool IQNetPlayer::IsLocal() { return true; }
|
||||
PlayerUID IQNetPlayer::GetXuid() { return (PlayerUID)(0xe000d45248242f2e + m_smallId); } // todo: restore to INVALID_XUID once saves support this
|
||||
LPCWSTR IQNetPlayer::GetGamertag() { return m_gamertag; }
|
||||
int IQNetPlayer::GetSessionIndex() { return m_smallId; }
|
||||
extern wstring g_playerName;
|
||||
LPCWSTR IQNetPlayer::GetGamertag() { return g_playerName.empty() ? L"Windows" : g_playerName.c_str(); }
|
||||
int IQNetPlayer::GetSessionIndex() { return 0; }
|
||||
bool IQNetPlayer::IsTalking() { return false; }
|
||||
bool IQNetPlayer::IsMutedByLocalUser(DWORD dwUserIndex) { return false; }
|
||||
bool IQNetPlayer::HasVoice() { return false; }
|
||||
@@ -231,17 +232,13 @@ void Win64_SetupRemoteQNetPlayer(IQNetPlayer * player, BYTE smallId, bool isHost
|
||||
IQNet::s_playerCount = smallId + 1;
|
||||
}
|
||||
|
||||
static bool Win64_IsActivePlayer(IQNetPlayer* p, DWORD index);
|
||||
|
||||
HRESULT IQNet::AddLocalPlayerByUserIndex(DWORD dwUserIndex) { return S_OK; }
|
||||
IQNetPlayer* IQNet::GetHostPlayer() { return &m_player[0]; }
|
||||
IQNetPlayer* IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex)
|
||||
{
|
||||
if (s_isHosting)
|
||||
{
|
||||
if (dwUserIndex < MINECRAFT_NET_MAX_PLAYERS &&
|
||||
!m_player[dwUserIndex].m_isRemote &&
|
||||
Win64_IsActivePlayer(&m_player[dwUserIndex], dwUserIndex))
|
||||
if (dwUserIndex < MINECRAFT_NET_MAX_PLAYERS && !m_player[dwUserIndex].m_isRemote)
|
||||
return &m_player[dwUserIndex];
|
||||
return NULL;
|
||||
}
|
||||
@@ -249,7 +246,7 @@ IQNetPlayer* IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex)
|
||||
return NULL;
|
||||
for (DWORD i = 0; i < s_playerCount; i++)
|
||||
{
|
||||
if (!m_player[i].m_isRemote && Win64_IsActivePlayer(&m_player[i], i))
|
||||
if (!m_player[i].m_isRemote)
|
||||
return &m_player[i];
|
||||
}
|
||||
return NULL;
|
||||
@@ -302,28 +299,15 @@ QNET_STATE IQNet::GetState() { return _iQNetStubState; }
|
||||
bool IQNet::IsHost() { return s_isHosting; }
|
||||
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::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::ClientJoinGame() { _iQNetStubState = QNET_STATE_SESSION_STARTING; s_isHosting = false; }
|
||||
void IQNet::EndGame()
|
||||
{
|
||||
_iQNetStubState = QNET_STATE_IDLE;
|
||||
s_isHosting = false;
|
||||
s_playerCount = 1;
|
||||
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++)
|
||||
for (int i = 1; i < MINECRAFT_NET_MAX_PLAYERS; i++)
|
||||
{
|
||||
m_player[i].m_smallId = (BYTE)i;
|
||||
m_player[i].m_smallId = 0;
|
||||
m_player[i].m_isRemote = false;
|
||||
m_player[i].m_isHostPlayer = false;
|
||||
m_player[i].m_gamertag[0] = 0;
|
||||
@@ -603,6 +587,7 @@ void C_4JProfile::SetPrimaryPad(int iPad) {}
|
||||
#ifdef _DURANGO
|
||||
char fakeGamerTag[32] = "PlayerName";
|
||||
void SetFakeGamertag(char* name) { strcpy_s(fakeGamerTag, name); }
|
||||
char* C_4JProfile::GetGamertag(int iPad) { return fakeGamerTag; }
|
||||
#else
|
||||
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; }
|
||||
|
||||
@@ -1964,8 +1964,8 @@ bool LevelRenderer::updateDirtyChunks()
|
||||
{
|
||||
if( (!onlyRebuild) ||
|
||||
globalChunkFlags[ pClipChunk->globalIdx ] & CHUNK_FLAG_COMPILED ||
|
||||
( 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
|
||||
( 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
|
||||
{
|
||||
considered++;
|
||||
// Is this chunk nearer than our nearest?
|
||||
#ifdef _LARGE_WORLDS
|
||||
@@ -2557,19 +2557,13 @@ void LevelRenderer::cull(Culler *culler, float a)
|
||||
{
|
||||
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 ) )
|
||||
{
|
||||
bool clipres = clip(pClipChunk->aabb, fdraw);
|
||||
pClipChunk->visible = clipres;
|
||||
if( pClipChunk->visible ) vis++;
|
||||
total++;
|
||||
}
|
||||
else if (clipres)
|
||||
{
|
||||
pClipChunk->visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pClipChunk->visible = false;
|
||||
@@ -2578,7 +2572,6 @@ void LevelRenderer::cull(Culler *culler, float a)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LevelRenderer::playStreamingMusic(const wstring& name, int x, int y, int z)
|
||||
{
|
||||
if (name != L"")
|
||||
|
||||
@@ -52,16 +52,14 @@ public:
|
||||
static const int CHUNK_SIZE = 16;
|
||||
#endif
|
||||
static const int CHUNK_Y_COUNT = Level::maxBuildHeight / CHUNK_SIZE;
|
||||
#if defined _WINDOWS64
|
||||
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
|
||||
#if (defined _XBOX_ONE || defined _WINDOWS64)
|
||||
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 2047 * 1024 * 1024; // Changed to 2047. 4J had set to 512.
|
||||
#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)
|
||||
#elif defined __PS3__
|
||||
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 110 * 1024 * 1024; // 4J - added
|
||||
#else
|
||||
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 55 * 1024 * 1024; // 4J - added
|
||||
static const int MAX_COMMANDBUFFER_ALLOCATIONS = 55 * 1024 * 1024; // 4J - added
|
||||
#endif
|
||||
public:
|
||||
LevelRenderer(Minecraft *mc, Textures *textures);
|
||||
@@ -272,10 +270,10 @@ public:
|
||||
|
||||
bool dirtyChunkPresent;
|
||||
__int64 lastDirtyChunkFound;
|
||||
static const int FORCE_DIRTY_CHUNK_CHECK_PERIOD_MS = 125; // decreased from 250 to 125 - updated by detectiveren
|
||||
static const int FORCE_DIRTY_CHUNK_CHECK_PERIOD_MS = 250;
|
||||
|
||||
#ifdef _LARGE_WORLDS
|
||||
static const int MAX_CONCURRENT_CHUNK_REBUILDS = 8; // increased from 4 to 8 - updated by detectiveren
|
||||
static const int MAX_CONCURRENT_CHUNK_REBUILDS = 4;
|
||||
static const int MAX_CHUNK_REBUILD_THREADS = MAX_CONCURRENT_CHUNK_REBUILDS - 1;
|
||||
static Chunk permaChunk[MAX_CONCURRENT_CHUNK_REBUILDS];
|
||||
static C4JThread *rebuildThreads[MAX_CHUNK_REBUILD_THREADS];
|
||||
|
||||
@@ -45937,7 +45937,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ORBIS'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|ORBIS'">true</ExcludedFromBuild>
|
||||
</Library>
|
||||
<Library Include="Windows64\4JLibs\libs\4J_Render_PC.lib">
|
||||
<Library Include="Windows64\4JLibs\libs\4J_Render.lib">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Durango'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Durango'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Durango'">true</ExcludedFromBuild>
|
||||
@@ -45996,7 +45996,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ORBIS'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|ORBIS'">true</ExcludedFromBuild>
|
||||
</Library>
|
||||
<Library Include="Windows64\4JLibs\libs\4J_Render_PC_d.lib">
|
||||
<Library Include="Windows64\4JLibs\libs\4J_Render_d.lib">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Durango'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Durango'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Durango'">true</ExcludedFromBuild>
|
||||
@@ -48677,4 +48677,4 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -5972,10 +5972,10 @@
|
||||
<Library Include="Durango\4JLibs\libs\4J_Input_d.lib">
|
||||
<Filter>Durango\4JLibs\libs</Filter>
|
||||
</Library>
|
||||
<Library Include="Windows64\4JLibs\libs\4J_Render_PC.lib">
|
||||
<Library Include="Windows64\4JLibs\libs\4J_Render.lib">
|
||||
<Filter>Windows64\4JLibs\libs</Filter>
|
||||
</Library>
|
||||
<Library Include="Windows64\4JLibs\libs\4J_Render_PC_d.lib">
|
||||
<Library Include="Windows64\4JLibs\libs\4J_Render_d.lib">
|
||||
<Filter>Windows64\4JLibs\libs</Filter>
|
||||
</Library>
|
||||
<Library Include="Windows64\4JLibs\libs\4J_Input.lib">
|
||||
@@ -6295,4 +6295,4 @@
|
||||
<ItemGroup>
|
||||
<AppxManifest Include="Durango\Autogenerated.appxmanifest" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1456,7 +1456,7 @@ void Minecraft::run_middle()
|
||||
if (KMInput.ConsumeKeyPress('C')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_CRAFTING;
|
||||
if (KMInput.ConsumeKeyPress(VK_F5)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON;
|
||||
// In flying mode, Shift held = sneak/descend
|
||||
if (localplayers[i]->abilities.flying && KMInput.IsKeyDown(VK_SHIFT) && !ui.GetMenuDisplayed(i))
|
||||
if (localplayers[i]->abilities.flying && KMInput.IsKeyDown(VK_SHIFT))
|
||||
localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE;
|
||||
}
|
||||
#endif
|
||||
@@ -3618,6 +3618,8 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_RENDER_DEBUG)) )
|
||||
{
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
|
||||
options->renderDebug = !options->renderDebug;
|
||||
#ifdef _XBOX
|
||||
app.EnableDebugOverlay(options->renderDebug,iPad);
|
||||
#else
|
||||
@@ -3627,11 +3629,13 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||
#endif
|
||||
}
|
||||
|
||||
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_SPAWN_CREEPER)))
|
||||
{
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
options->renderDebug = !options->renderDebug;
|
||||
#endif
|
||||
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_SPAWN_CREEPER)) && app.GetMobsDontAttackEnabled())
|
||||
{
|
||||
//shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(Creeper::_class->newInstance( level ));
|
||||
//shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(Wolf::_class->newInstance( level ));
|
||||
shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(shared_ptr<Spider>(new Spider( level )));
|
||||
mob->moveTo(player->x+1, player->y, player->z+1, level->random->nextFloat() * 360, 0);
|
||||
level->addEntity(mob);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -424,11 +424,112 @@ void Textures::bindTextureLayers(ResourceLocation *resource)
|
||||
{
|
||||
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();
|
||||
|
||||
for( int i = 0; i < layers; i++ )
|
||||
{
|
||||
RenderManager.TextureBind(loadTexture(resource->getTexture(i)));
|
||||
cacheKey += _toString<int>((int)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(0, id);
|
||||
for( int i = 1; i < 4; i++ )
|
||||
{
|
||||
RenderManager.TextureBind(i, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1520,3 +1621,6 @@ bool Textures::IsOriginalImage(TEXTURE_NAME texId, const wstring& name)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
11
Minecraft.Client/Windows64/4JLibs/README.md
Normal file
11
Minecraft.Client/Windows64/4JLibs/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Windows64 4JLibs
|
||||
|
||||
This directory contains the Windows x64 `4JLibs` headers and libraries used by this project.
|
||||
|
||||
Important: these files are based on the community reimplementation of `4JLibs`, not the original proprietary 4J Studios version.
|
||||
|
||||
Source:
|
||||
|
||||
- Community reimplementation: https://github.com/smartcmd/4JLibs
|
||||
|
||||
In other words, the `inc/` and `libs/` contents here should be understood as the open community-maintained replacement that makes the Windows build possible, rather than a dump of the original upstream SDK/library package.
|
||||
@@ -145,6 +145,7 @@ public:
|
||||
int TextureCreate();
|
||||
void TextureFree(int idx);
|
||||
void TextureBind(int idx);
|
||||
void TextureBind(int layer, int idx);
|
||||
void TextureBindVertex(int idx);
|
||||
void TextureSetTextureLevels(int levels);
|
||||
int TextureGetTextureLevels();
|
||||
@@ -300,3 +301,4 @@ const int GL_TRIANGLE_STRIP = C4JRender::PRIMITIVE_TYPE_TRIANGLE_STRIP;
|
||||
extern C4JRender RenderManager;
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -103,7 +103,6 @@ void KeyboardMouseInput::OnRawMouseInput(LPARAM lParam)
|
||||
|
||||
void KeyboardMouseInput::OnMouseButton(int button, bool down)
|
||||
{
|
||||
if (ui.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad())) { return; }
|
||||
if (button >= 0 && button < 3)
|
||||
{
|
||||
if (down && !m_mouseButtons[button]) m_mousePressedAccum[button] = true;
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// Code implemented by LCEMP, credit if used on other repos
|
||||
// https://github.com/LCEMP/LCEMP
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
@@ -154,7 +151,7 @@ bool WinsockNetLayer::HostGame(int port)
|
||||
LeaveCriticalSection(&s_freeSmallIdLock);
|
||||
|
||||
struct addrinfo hints = {};
|
||||
struct addrinfo* result = NULL;
|
||||
struct addrinfo *result = NULL;
|
||||
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
@@ -180,7 +177,7 @@ bool WinsockNetLayer::HostGame(int port)
|
||||
}
|
||||
|
||||
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);
|
||||
freeaddrinfo(result);
|
||||
@@ -210,23 +207,15 @@ bool WinsockNetLayer::HostGame(int port)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinsockNetLayer::JoinGame(const char* ip, int port)
|
||||
bool WinsockNetLayer::JoinGame(const char *ip, int port)
|
||||
{
|
||||
if (!s_initialized && !Initialize()) return false;
|
||||
|
||||
s_isHost = false;
|
||||
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* result = NULL;
|
||||
struct addrinfo *result = NULL;
|
||||
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
@@ -242,55 +231,37 @@ bool WinsockNetLayer::JoinGame(const char* ip, int port)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool connected = false;
|
||||
BYTE assignedSmallId = 0;
|
||||
const int maxAttempts = 12;
|
||||
|
||||
for (int attempt = 0; attempt < maxAttempts; ++attempt)
|
||||
{
|
||||
s_hostConnectionSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||
if (s_hostConnectionSocket == INVALID_SOCKET)
|
||||
{
|
||||
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;
|
||||
}
|
||||
freeaddrinfo(result);
|
||||
|
||||
if (!connected)
|
||||
s_hostConnectionSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||
if (s_hostConnectionSocket == INVALID_SOCKET)
|
||||
{
|
||||
app.DebugPrintf("socket() failed: %d\n", WSAGetLastError());
|
||||
freeaddrinfo(result);
|
||||
return false;
|
||||
}
|
||||
s_localSmallId = assignedSmallId;
|
||||
|
||||
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);
|
||||
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];
|
||||
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;
|
||||
}
|
||||
s_localSmallId = assignBuf[0];
|
||||
|
||||
app.DebugPrintf("Win64 LAN: Connected to %s:%d, assigned smallId=%d\n", ip, port, s_localSmallId);
|
||||
|
||||
@@ -302,7 +273,7 @@ bool WinsockNetLayer::JoinGame(const char* ip, int port)
|
||||
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;
|
||||
|
||||
@@ -318,7 +289,7 @@ bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void* data, int dataSize)
|
||||
int toSend = 4;
|
||||
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)
|
||||
{
|
||||
LeaveCriticalSection(&s_sendLock);
|
||||
@@ -330,7 +301,7 @@ bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void* data, int dataSize)
|
||||
totalSent = 0;
|
||||
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)
|
||||
{
|
||||
LeaveCriticalSection(&s_sendLock);
|
||||
@@ -343,7 +314,7 @@ bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void* data, int dataSize)
|
||||
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;
|
||||
|
||||
@@ -375,34 +346,34 @@ SOCKET WinsockNetLayer::GetSocketForSmallId(BYTE smallId)
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
static bool RecvExact(SOCKET sock, BYTE* buf, int len)
|
||||
static bool RecvExact(SOCKET sock, BYTE *buf, int len)
|
||||
{
|
||||
int totalRecv = 0;
|
||||
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;
|
||||
totalRecv += r;
|
||||
}
|
||||
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* pPlayerTo = g_NetworkManager.GetPlayerBySmallId(toSmallId);
|
||||
INetworkPlayer *pPlayerFrom = g_NetworkManager.GetPlayerBySmallId(fromSmallId);
|
||||
INetworkPlayer *pPlayerTo = g_NetworkManager.GetPlayerBySmallId(toSmallId);
|
||||
|
||||
if (pPlayerFrom == NULL || pPlayerTo == NULL) return;
|
||||
|
||||
if (s_isHost)
|
||||
{
|
||||
::Socket* pSocket = pPlayerFrom->GetSocket();
|
||||
::Socket *pSocket = pPlayerFrom->GetSocket();
|
||||
if (pSocket != NULL)
|
||||
pSocket->pushDataToQueue(data, dataSize, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
::Socket* pSocket = pPlayerTo->GetSocket();
|
||||
::Socket *pSocket = pPlayerTo->GetSocket();
|
||||
if (pSocket != NULL)
|
||||
pSocket->pushDataToQueue(data, dataSize, true);
|
||||
}
|
||||
@@ -421,7 +392,7 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
|
||||
}
|
||||
|
||||
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;
|
||||
if (_iQNetStubState != QNET_STATE_GAME_PLAY)
|
||||
@@ -452,7 +423,7 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
|
||||
LeaveCriticalSection(&s_freeSmallIdLock);
|
||||
|
||||
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)
|
||||
{
|
||||
app.DebugPrintf("Failed to send small ID to client\n");
|
||||
@@ -473,15 +444,15 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
|
||||
|
||||
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);
|
||||
|
||||
extern CPlatformNetworkManagerStub* g_pPlatformNetworkManager;
|
||||
extern CPlatformNetworkManagerStub *g_pPlatformNetworkManager;
|
||||
g_pPlatformNetworkManager->NotifyPlayerJoined(qnetPlayer);
|
||||
|
||||
DWORD* threadParam = new DWORD;
|
||||
DWORD *threadParam = new DWORD;
|
||||
*threadParam = connIdx;
|
||||
HANDLE hThread = CreateThread(NULL, 0, RecvThreadProc, threadParam, 0, NULL);
|
||||
|
||||
@@ -495,8 +466,8 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
|
||||
|
||||
DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param)
|
||||
{
|
||||
DWORD connIdx = *(DWORD*)param;
|
||||
delete (DWORD*)param;
|
||||
DWORD connIdx = *(DWORD *)param;
|
||||
delete (DWORD *)param;
|
||||
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
if (connIdx >= (DWORD)s_connections.size())
|
||||
@@ -508,8 +479,7 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param)
|
||||
BYTE clientSmallId = s_connections[connIdx].smallId;
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
|
||||
std::vector<BYTE> recvBuf;
|
||||
recvBuf.resize(WIN64_NET_RECV_BUFFER_SIZE);
|
||||
BYTE *recvBuf = new BYTE[WIN64_NET_RECV_BUFFER_SIZE];
|
||||
|
||||
while (s_active)
|
||||
{
|
||||
@@ -520,47 +490,33 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param)
|
||||
break;
|
||||
}
|
||||
|
||||
int packetSize =
|
||||
((uint32_t)header[0] << 24) |
|
||||
((uint32_t)header[1] << 16) |
|
||||
((uint32_t)header[2] << 8) |
|
||||
((uint32_t)header[3]);
|
||||
int packetSize = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3];
|
||||
|
||||
if (packetSize <= 0 || packetSize > WIN64_NET_MAX_PACKET_SIZE)
|
||||
if (packetSize <= 0 || packetSize > WIN64_NET_RECV_BUFFER_SIZE)
|
||||
{
|
||||
app.DebugPrintf("Win64 LAN: Invalid packet size %d from client smallId=%d (max=%d)\n",
|
||||
packetSize,
|
||||
clientSmallId,
|
||||
(int)WIN64_NET_MAX_PACKET_SIZE);
|
||||
app.DebugPrintf("Win64 LAN: Invalid packet size %d from client smallId=%d\n", packetSize, clientSmallId);
|
||||
break;
|
||||
}
|
||||
|
||||
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))
|
||||
if (!RecvExact(sock, recvBuf, packetSize))
|
||||
{
|
||||
app.DebugPrintf("Win64 LAN: Client smallId=%d disconnected (body)\n", clientSmallId);
|
||||
break;
|
||||
}
|
||||
|
||||
HandleDataReceived(clientSmallId, s_hostSmallId, &recvBuf[0], packetSize);
|
||||
HandleDataReceived(clientSmallId, s_hostSmallId, recvBuf, packetSize);
|
||||
}
|
||||
|
||||
delete[] recvBuf;
|
||||
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
for (size_t i = 0; i < s_connections.size(); i++)
|
||||
{
|
||||
if (s_connections[i].smallId == clientSmallId)
|
||||
{
|
||||
s_connections[i].active = false;
|
||||
if (s_connections[i].tcpSocket != INVALID_SOCKET)
|
||||
{
|
||||
closesocket(s_connections[i].tcpSocket);
|
||||
s_connections[i].tcpSocket = INVALID_SOCKET;
|
||||
}
|
||||
closesocket(s_connections[i].tcpSocket);
|
||||
s_connections[i].tcpSocket = INVALID_SOCKET;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -573,7 +529,7 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool WinsockNetLayer::PopDisconnectedSmallId(BYTE* outSmallId)
|
||||
bool WinsockNetLayer::PopDisconnectedSmallId(BYTE *outSmallId)
|
||||
{
|
||||
bool found = false;
|
||||
EnterCriticalSection(&s_disconnectLock);
|
||||
@@ -594,26 +550,9 @@ void WinsockNetLayer::PushFreeSmallId(BYTE smallId)
|
||||
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)
|
||||
{
|
||||
std::vector<BYTE> recvBuf;
|
||||
recvBuf.resize(WIN64_NET_RECV_BUFFER_SIZE);
|
||||
BYTE *recvBuf = new BYTE[WIN64_NET_RECV_BUFFER_SIZE];
|
||||
|
||||
while (s_active && s_hostConnectionSocket != INVALID_SOCKET)
|
||||
{
|
||||
@@ -626,34 +565,28 @@ DWORD WINAPI WinsockNetLayer::ClientRecvThreadProc(LPVOID param)
|
||||
|
||||
int packetSize = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3];
|
||||
|
||||
if (packetSize <= 0 || packetSize > WIN64_NET_MAX_PACKET_SIZE)
|
||||
if (packetSize <= 0 || packetSize > WIN64_NET_RECV_BUFFER_SIZE)
|
||||
{
|
||||
app.DebugPrintf("Win64 LAN: Invalid packet size %d from host (max=%d)\n",
|
||||
packetSize,
|
||||
(int)WIN64_NET_MAX_PACKET_SIZE);
|
||||
app.DebugPrintf("Win64 LAN: Invalid packet size %d from host\n", packetSize);
|
||||
break;
|
||||
}
|
||||
|
||||
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))
|
||||
if (!RecvExact(s_hostConnectionSocket, recvBuf, packetSize))
|
||||
{
|
||||
app.DebugPrintf("Win64 LAN: Disconnected from host (body)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
HandleDataReceived(s_hostSmallId, s_localSmallId, &recvBuf[0], packetSize);
|
||||
HandleDataReceived(s_hostSmallId, s_localSmallId, recvBuf, packetSize);
|
||||
}
|
||||
|
||||
delete[] recvBuf;
|
||||
|
||||
s_connected = false;
|
||||
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_initialized) return false;
|
||||
@@ -681,7 +614,7 @@ bool WinsockNetLayer::StartAdvertising(int gamePort, const wchar_t* hostName, un
|
||||
}
|
||||
|
||||
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_advertiseThread = CreateThread(NULL, 0, AdvertiseThreadProc, NULL, 0, NULL);
|
||||
@@ -736,8 +669,8 @@ DWORD WINAPI WinsockNetLayer::AdvertiseThreadProc(LPVOID param)
|
||||
Win64LANBroadcast data = s_advertiseData;
|
||||
LeaveCriticalSection(&s_advertiseLock);
|
||||
|
||||
int sent = sendto(s_advertiseSock, (const char*)&data, sizeof(data), 0,
|
||||
(struct sockaddr*)&broadcastAddr, sizeof(broadcastAddr));
|
||||
int sent = sendto(s_advertiseSock, (const char *)&data, sizeof(data), 0,
|
||||
(struct sockaddr *)&broadcastAddr, sizeof(broadcastAddr));
|
||||
|
||||
if (sent == SOCKET_ERROR && s_advertising)
|
||||
{
|
||||
@@ -763,7 +696,7 @@ bool WinsockNetLayer::StartDiscovery()
|
||||
}
|
||||
|
||||
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;
|
||||
memset(&bindAddr, 0, sizeof(bindAddr));
|
||||
@@ -771,7 +704,7 @@ bool WinsockNetLayer::StartDiscovery()
|
||||
bindAddr.sin_port = htons(WIN64_LAN_DISCOVERY_PORT);
|
||||
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());
|
||||
closesocket(s_discoverySock);
|
||||
@@ -780,7 +713,7 @@ bool WinsockNetLayer::StartDiscovery()
|
||||
}
|
||||
|
||||
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_discoveryThread = CreateThread(NULL, 0, DiscoveryThreadProc, NULL, 0, NULL);
|
||||
@@ -830,7 +763,7 @@ DWORD WINAPI WinsockNetLayer::DiscoveryThreadProc(LPVOID param)
|
||||
int senderLen = sizeof(senderAddr);
|
||||
|
||||
int recvLen = recvfrom(s_discoverySock, recvBuf, sizeof(recvBuf), 0,
|
||||
(struct sockaddr*)&senderAddr, &senderLen);
|
||||
(struct sockaddr *)&senderAddr, &senderLen);
|
||||
|
||||
if (recvLen == SOCKET_ERROR)
|
||||
{
|
||||
@@ -840,7 +773,7 @@ DWORD WINAPI WinsockNetLayer::DiscoveryThreadProc(LPVOID param)
|
||||
if (recvLen < (int)sizeof(Win64LANBroadcast))
|
||||
continue;
|
||||
|
||||
Win64LANBroadcast* broadcast = (Win64LANBroadcast*)recvBuf;
|
||||
Win64LANBroadcast *broadcast = (Win64LANBroadcast *)recvBuf;
|
||||
if (broadcast->magic != WIN64_LAN_BROADCAST_MAGIC)
|
||||
continue;
|
||||
|
||||
@@ -908,4 +841,4 @@ DWORD WINAPI WinsockNetLayer::DiscoveryThreadProc(LPVOID param)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// Code implemented by LCEMP, credit if used on other repos
|
||||
// https://github.com/LCEMP/LCEMP
|
||||
#pragma once
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
@@ -14,7 +12,6 @@
|
||||
#define WIN64_NET_DEFAULT_PORT 25565
|
||||
#define WIN64_NET_MAX_CLIENTS 7
|
||||
#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_BROADCAST_MAGIC 0x4D434C4E
|
||||
|
||||
@@ -66,10 +63,10 @@ public:
|
||||
static void Shutdown();
|
||||
|
||||
static bool HostGame(int port);
|
||||
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 SendOnSocket(SOCKET sock, 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 IsHosting() { return s_isHost; }
|
||||
static bool IsConnected() { return s_connected; }
|
||||
@@ -80,13 +77,12 @@ public:
|
||||
|
||||
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 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 UpdateAdvertisePlayerCount(BYTE count);
|
||||
static void UpdateAdvertiseJoinable(bool joinable);
|
||||
|
||||
@@ -10,11 +10,46 @@
|
||||
#include "..\..\Minecraft.World\BiomeSource.h"
|
||||
#include "..\..\Minecraft.World\LevelType.h"
|
||||
|
||||
wstring g_playerName;
|
||||
|
||||
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()
|
||||
{
|
||||
m_bShutdown = false;
|
||||
LoadPlayerName();
|
||||
}
|
||||
|
||||
void CConsoleMinecraftApp::SetRichPresenceContext(int iPad, int contextId)
|
||||
@@ -75,8 +110,8 @@ void CConsoleMinecraftApp::TemporaryCreateGameStart()
|
||||
Minecraft *pMinecraft=Minecraft::GetInstance();
|
||||
app.ReleaseSaveThumbnail();
|
||||
ProfileManager.SetLockedProfile(0);
|
||||
extern wchar_t g_Win64UsernameW[17];
|
||||
pMinecraft->user->name = g_Win64UsernameW;
|
||||
LoadPlayerName();
|
||||
pMinecraft->user->name = g_playerName;
|
||||
app.ApplyGameSettingsChanged(0);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////// From CScene_MultiGameJoinLoad::OnInit
|
||||
|
||||
@@ -85,11 +85,10 @@ BOOL g_bWidescreen = TRUE;
|
||||
int g_iScreenWidth = 1920;
|
||||
int g_iScreenHeight = 1080;
|
||||
|
||||
UINT g_ScreenWidth = 1920;
|
||||
UINT g_ScreenHeight = 1080;
|
||||
|
||||
char g_Win64Username[17] = { 0 };
|
||||
wchar_t g_Win64UsernameW[17] = { 0 };
|
||||
UINT g_ScreenWidth = 1920;
|
||||
UINT g_ScreenHeight = 1080;
|
||||
|
||||
// Fullscreen toggle state
|
||||
static bool g_isFullscreen = false;
|
||||
@@ -766,41 +765,36 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
||||
//g_iScreenHeight = 544;
|
||||
}
|
||||
|
||||
// Default username will be "Windows"
|
||||
strncpy_s(g_Win64Username, sizeof(g_Win64Username), "Windows", _TRUNCATE);
|
||||
char cmdLineA[1024];
|
||||
strncpy_s(cmdLineA, sizeof(cmdLineA), lpCmdLine, _TRUNCATE);
|
||||
|
||||
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 = nullptr;
|
||||
if (fopen_s(&f, filePath, "r") == 0 && f)
|
||||
char* nameArg = strstr(cmdLineA, "-name ");
|
||||
if (nameArg)
|
||||
{
|
||||
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)
|
||||
{
|
||||
strncpy_s(g_Win64Username, sizeof(g_Win64Username), buf, _TRUNCATE);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
nameArg += 6;
|
||||
while (*nameArg == ' ') nameArg++;
|
||||
char nameBuf[17];
|
||||
int n = 0;
|
||||
while (nameArg[n] && nameArg[n] != ' ' && n < 16) { nameBuf[n] = nameArg[n]; n++; }
|
||||
nameBuf[n] = 0;
|
||||
strncpy_s(g_Win64Username, 17, nameBuf, _TRUNCATE);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_Win64Username[0] == 0)
|
||||
{
|
||||
DWORD sz = 17;
|
||||
if (!GetUserNameA(g_Win64Username, &sz))
|
||||
strncpy_s(g_Win64Username, 17, "Player", _TRUNCATE);
|
||||
static bool seeded = false;
|
||||
if (!seeded)
|
||||
{
|
||||
seeded = true;
|
||||
srand((unsigned int)time(NULL));
|
||||
}
|
||||
|
||||
int r = rand() % 10000; // 0<>9999
|
||||
|
||||
snprintf(g_Win64Username, 17, "Player%04d", r);
|
||||
|
||||
g_Win64Username[16] = 0;
|
||||
}
|
||||
|
||||
@@ -1278,7 +1272,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
||||
}
|
||||
}
|
||||
|
||||
// F1 toggles the HUD
|
||||
// F1 toggles the HUD, F3 toggles the debug console overlay, F11 toggles fullscreen
|
||||
if (KMInput.IsKeyPressed(VK_F1))
|
||||
{
|
||||
int primaryPad = ProfileManager.GetPrimaryPad();
|
||||
@@ -1286,43 +1280,21 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
||||
app.SetGameSettings(primaryPad, eGameSetting_DisplayHUD, displayHud ? 0 : 1);
|
||||
app.SetGameSettings(primaryPad, eGameSetting_DisplayHand, displayHud ? 0 : 1);
|
||||
}
|
||||
|
||||
// F3 toggles onscreen debug info
|
||||
|
||||
if (KMInput.IsKeyPressed(VK_F3))
|
||||
{
|
||||
if (Minecraft* pMinecraft = Minecraft::GetInstance())
|
||||
{
|
||||
if (pMinecraft->options)
|
||||
{
|
||||
pMinecraft->options->renderDebug = !pMinecraft->options->renderDebug;
|
||||
}
|
||||
}
|
||||
static bool s_debugConsole = false;
|
||||
s_debugConsole = !s_debugConsole;
|
||||
ui.ShowUIDebugConsole(s_debugConsole);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_MENUS_ENABLED
|
||||
// F4 Open debug overlay
|
||||
if (KMInput.IsKeyPressed(VK_F4))
|
||||
{
|
||||
if (Minecraft *pMinecraft = Minecraft::GetInstance())
|
||||
{
|
||||
if (pMinecraft->options &&
|
||||
app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL)
|
||||
{
|
||||
ui.NavigateToScene(0, eUIScene_DebugOverlay, NULL, eUILayer_Debug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// F6 Open debug console
|
||||
if (KMInput.IsKeyPressed(VK_F6))
|
||||
{
|
||||
static bool s_debugConsole = false;
|
||||
s_debugConsole = !s_debugConsole;
|
||||
ui.ShowUIDebugConsole(s_debugConsole);
|
||||
}
|
||||
if (KMInput.IsKeyPressed(VK_F4))
|
||||
{
|
||||
ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_DebugOverlay, NULL, eUILayer_Debug);
|
||||
}
|
||||
#endif
|
||||
|
||||
// F11 Toggle fullscreen
|
||||
if (KMInput.IsKeyPressed(VK_F11))
|
||||
{
|
||||
ToggleFullscreen();
|
||||
@@ -1340,6 +1312,33 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_MENUS_ENABLED
|
||||
// F3 toggles onscreen debug info
|
||||
if (KMInput.IsKeyPressed(VK_F3))
|
||||
{
|
||||
if (Minecraft* pMinecraft = Minecraft::GetInstance())
|
||||
{
|
||||
if (pMinecraft->options && app.DebugSettingsOn())
|
||||
{
|
||||
pMinecraft->options->renderDebug = !pMinecraft->options->renderDebug;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// F4 opens debug overlay
|
||||
if (KMInput.IsKeyPressed(VK_F4))
|
||||
{
|
||||
if (Minecraft* pMinecraft = Minecraft::GetInstance())
|
||||
{
|
||||
if (pMinecraft->options && app.DebugSettingsOn() &&
|
||||
app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL)
|
||||
{
|
||||
ui.NavigateToScene(0, eUIScene_DebugOverlay, NULL, eUILayer_Debug);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// has the game defined profile data been changed (by a profile load)
|
||||
if(app.uiGameDefinedDataChangedBitmask!=0)
|
||||
|
||||
@@ -3,6 +3,17 @@
|
||||
#include "..\Minecraft.World\IntBuffer.h"
|
||||
#include "..\Minecraft.World\ByteBuffer.h"
|
||||
|
||||
static int g_activeTextureLayer = 0;
|
||||
|
||||
static int getTextureLayer(int textureUnit)
|
||||
{
|
||||
if (textureUnit == GL_TEXTURE1)
|
||||
return 1;
|
||||
if (textureUnit >= GL_TEXTURE0)
|
||||
return textureUnit - GL_TEXTURE0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void glViewport(int x, int y, int w, int h)
|
||||
{
|
||||
// We don't really need anything here because minecraft doesn't current do anything other than the default viewport
|
||||
@@ -139,7 +150,7 @@ void Display::swapBuffers()
|
||||
|
||||
void glBindTexture(int target,int texture)
|
||||
{
|
||||
RenderManager.TextureBind(texture);
|
||||
RenderManager.TextureBind(g_activeTextureLayer, texture);
|
||||
}
|
||||
|
||||
void glTexImage2D(int target,int level,int internalformat,int width,int height,int border,int format,int type, ByteBuffer *data)
|
||||
@@ -190,7 +201,7 @@ void glDisable(int state)
|
||||
switch(state)
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
RenderManager.TextureBind(-1);
|
||||
RenderManager.TextureBind(g_activeTextureLayer, -1);
|
||||
break;
|
||||
case GL_BLEND:
|
||||
RenderManager.StateSetBlendEnable(false);
|
||||
@@ -390,4 +401,23 @@ void glTexGen(int coord, int mode, FloatBuffer *vec)
|
||||
void glCullFace(int dir)
|
||||
{
|
||||
RenderManager.StateSetFaceCullCW( dir == GL_BACK);
|
||||
}
|
||||
}
|
||||
void glClientActiveTexture(int texture)
|
||||
{
|
||||
glActiveTexture(texture);
|
||||
}
|
||||
|
||||
void glActiveTexture(int texture)
|
||||
{
|
||||
int layer = getTextureLayer(texture);
|
||||
if (layer < 0)
|
||||
{
|
||||
layer = 0;
|
||||
}
|
||||
else if (layer > 3)
|
||||
{
|
||||
layer = 3;
|
||||
}
|
||||
g_activeTextureLayer = layer;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,13 +122,6 @@ void glColorMaterial(int,int)
|
||||
}
|
||||
|
||||
//1.8.2
|
||||
void glClientActiveTexture(int)
|
||||
{
|
||||
}
|
||||
|
||||
void glActiveTexture(int)
|
||||
{
|
||||
}
|
||||
|
||||
void glFlush()
|
||||
{
|
||||
@@ -157,4 +150,4 @@ DWORD XCamSetView(
|
||||
) { return 0; }
|
||||
|
||||
XCAMDEVICESTATE XCamGetStatus() { return XCAMDEVICESTATE_DISCONNECTED; }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -627,7 +627,6 @@ void Player::ride(shared_ptr<Entity> e)
|
||||
|
||||
return;
|
||||
}
|
||||
this->abilities.flying = false;
|
||||
LivingEntity::ride(e);
|
||||
}
|
||||
|
||||
|
||||
11
README.md
11
README.md
@@ -33,7 +33,13 @@ 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
|
||||
- Game connections use TCP port `25565` by default
|
||||
- LAN discovery uses UDP port `25566`
|
||||
- You can override your in-game username at launch with `username.txt`
|
||||
- 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/)
|
||||
|
||||
@@ -45,7 +51,7 @@ This feature is based on [LCEMP](https://github.com/LCEMP/LCEMP/)
|
||||
- **Sprint**: `Ctrl` (Hold) or Double-tap `W`
|
||||
- **Inventory**: `E`
|
||||
- **Drop Item**: `Q`
|
||||
- **Crafting**: `C` Use `Q` and `E` to move through tabs (cycles Left/Right)
|
||||
- **Crafting**: `C`
|
||||
- **Toggle View (FPS/TPS)**: `F5`
|
||||
- **Fullscreen**: `F11`
|
||||
- **Pause Menu**: `Esc`
|
||||
@@ -58,7 +64,6 @@ This feature is based on [LCEMP](https://github.com/LCEMP/LCEMP/)
|
||||
- **Toggle HUD**: `F1`
|
||||
- **Toggle Debug Info**: `F3`
|
||||
- **Open Debug Overlay**: `F4`
|
||||
- **Toggle Debug Console**: `F6`
|
||||
|
||||
## Build & Run
|
||||
|
||||
|
||||
Reference in New Issue
Block a user