diff --git a/.gitignore b/.gitignore
index cd9fbc6..b254632 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ MinecraftConsoles.opensdf
MinecraftConsoles.sdf
server.properties
+Agents.MD
fix_include_case.ps1
@@ -299,4 +300,4 @@ Minecraft.Client/redist64/*
# Required by Windows64 post-build copy step in Minecraft.Client.vcxproj
!Minecraft.Client/Durango/Sound/
Minecraft.Client/Durango/Sound/*
-!Minecraft.Client/Durango/Sound/Minecraft.msscmp
\ No newline at end of file
+!Minecraft.Client/Durango/Sound/Minecraft.msscmp
diff --git a/Minecraft.Client/Common/Consoles_App.cpp b/Minecraft.Client/Common/Consoles_App.cpp
index 0220201..50c2c20 100644
--- a/Minecraft.Client/Common/Consoles_App.cpp
+++ b/Minecraft.Client/Common/Consoles_App.cpp
@@ -78,6 +78,107 @@ unsigned int CMinecraftApp::m_uiLastSignInData = 0;
const float CMinecraftApp::fSafeZoneX = 64.0f; // 5% of 1280
const float CMinecraftApp::fSafeZoneY = 36.0f; // 5% of 720
+#if defined(_WINDOWS64) && !defined(_FINAL_BUILD)
+namespace
+{
+ FILE *g_clientLogFile = NULL;
+ CRITICAL_SECTION g_clientLogLock;
+ LONG g_clientLogInitState = 0;
+
+ bool ClientLogHasContent(const char *buf)
+ {
+ for (const char *p = buf; *p; p++)
+ {
+ if (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\r' && *p != '=')
+ return true;
+ }
+ return false;
+ }
+
+ void BuildClientLogFallbackPath(char *path, size_t pathSize)
+ {
+ path[0] = '\0';
+
+ char exePath[MAX_PATH];
+ if (!GetModuleFileNameA(NULL, exePath, MAX_PATH))
+ return;
+
+ exePath[MAX_PATH - 1] = '\0';
+ char *slash = strrchr(exePath, '\\');
+ if (slash == NULL)
+ slash = strrchr(exePath, '/');
+ if (slash == NULL)
+ return;
+
+ slash[1] = '\0';
+ _snprintf_s(path, pathSize, _TRUNCATE, "%sclient.log", exePath);
+ }
+
+ void InitClientLog()
+ {
+ LONG state = InterlockedCompareExchange(&g_clientLogInitState, 1, 0);
+ if (state == 0)
+ {
+ InitializeCriticalSection(&g_clientLogLock);
+
+ char logPath[MAX_PATH];
+ _snprintf_s(logPath, MAX_PATH, _TRUNCATE, "client.log");
+ fopen_s(&g_clientLogFile, logPath, "a");
+
+ if (g_clientLogFile == NULL)
+ {
+ BuildClientLogFallbackPath(logPath, MAX_PATH);
+ if (logPath[0] != '\0')
+ fopen_s(&g_clientLogFile, logPath, "a");
+ }
+
+ if (g_clientLogFile != NULL)
+ {
+ char msg[MAX_PATH + 64];
+ _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Client log: writing to %s\n", logPath);
+ OutputDebugStringA(msg);
+ }
+ else
+ {
+ OutputDebugStringA("Client log: failed to open client.log\n");
+ }
+
+ InterlockedExchange(&g_clientLogInitState, 2);
+ return;
+ }
+
+ while (g_clientLogInitState == 1)
+ Sleep(0);
+ }
+
+ void WriteClientLogLine(const char *buf)
+ {
+ if (buf == NULL || !ClientLogHasContent(buf))
+ return;
+
+ InitClientLog();
+ if (g_clientLogFile == NULL)
+ return;
+
+ char line[1024];
+ strncpy_s(line, sizeof(line), buf, _TRUNCATE);
+ size_t len = strlen(line);
+ while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
+ line[--len] = '\0';
+
+ time_t now = time(NULL);
+ struct tm t;
+ localtime_s(&t, &now);
+
+ EnterCriticalSection(&g_clientLogLock);
+ fprintf(g_clientLogFile, "%04d-%02d-%02d %02d:%02d:%02d [INFO] %s\n",
+ t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, line);
+ fflush(g_clientLogFile);
+ LeaveCriticalSection(&g_clientLogLock);
+ }
+}
+#endif
+
int CMinecraftApp::s_iHTMLFontSizesA[eHTMLSize_COUNT] =
{
#ifdef _XBOX
@@ -244,6 +345,9 @@ void CMinecraftApp::DebugPrintf(const char *szFormat, ...)
vsnprintf(buf, sizeof(buf), szFormat, ap);
va_end(ap);
OutputDebugStringA(buf);
+#ifdef _WINDOWS64
+ WriteClientLogLine(buf);
+#endif
#ifdef WITH_SERVER_CODE
bool hasContent = false;
for (const char *p = buf; *p; p++) {
@@ -313,6 +417,9 @@ void CMinecraftApp::DebugPrintf(int user, const char *szFormat, ...)
}
#else
OutputDebugStringA(buf);
+#ifdef _WINDOWS64
+ WriteClientLogLine(buf);
+#endif
#endif
#ifndef _XBOX
if(user == USER_UI)
@@ -10360,4 +10467,4 @@ bool CMinecraftApp::HasReachedMainMenu()
{
return m_hasReachedMainMenu;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/Minecraft.Client/Common/Network/GameNetworkManager.cpp b/Minecraft.Client/Common/Network/GameNetworkManager.cpp
index 717e6a5..6847ce6 100644
--- a/Minecraft.Client/Common/Network/GameNetworkManager.cpp
+++ b/Minecraft.Client/Common/Network/GameNetworkManager.cpp
@@ -1436,6 +1436,9 @@ void CGameNetworkManager::CreateSocket( INetworkPlayer *pNetworkPlayer, bool loc
{
socket = new Socket( pNetworkPlayer, g_NetworkManager.IsHost(), g_NetworkManager.IsHost() && localPlayer );
pNetworkPlayer->SetSocket( socket );
+ app.DebugPrintf("CGameNetworkManager: Created socket for smallId=%d local=%d host=%d gameplay=%d\n",
+ pNetworkPlayer->GetSmallId(), localPlayer ? 1 : 0, g_NetworkManager.IsHost() ? 1 : 0,
+ g_NetworkManager.IsInGameplay() ? 1 : 0);
// 4J Stu - May be other states we want to accept aswell
// Add this user to the game server if the game is started already
diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
index 9785cb9..1e8fc8a 100644
--- a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
+++ b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
@@ -296,11 +296,18 @@ void CPlatformNetworkManagerStub::DoWork()
BYTE disconnectedSmallId;
while (WinsockNetLayer::PopDisconnectedSmallId(&disconnectedSmallId))
{
+ app.DebugPrintf("PlatformNetworkManagerStub: Processing disconnect smallId=%d\n", disconnectedSmallId);
if (disconnectedSmallId == 0) continue;
- if (WinsockNetLayer::IsSmallIdConnected(disconnectedSmallId)) continue;
+ if (WinsockNetLayer::IsSmallIdConnected(disconnectedSmallId))
+ {
+ app.DebugPrintf("PlatformNetworkManagerStub: smallId=%d is still connected, deferring cleanup\n", disconnectedSmallId);
+ continue;
+ }
IQNetPlayer *qnetPlayer = m_pIQNet->GetPlayerBySmallId(disconnectedSmallId);
if (qnetPlayer != NULL && qnetPlayer->m_smallId == disconnectedSmallId)
{
+ app.DebugPrintf("PlatformNetworkManagerStub: Notifying leave for smallId=%d \"%ls\"\n",
+ disconnectedSmallId, qnetPlayer->GetGamertag());
NotifyPlayerLeaving(qnetPlayer);
qnetPlayer->m_smallId = 0;
qnetPlayer->m_isRemote = false;
@@ -310,15 +317,25 @@ void CPlatformNetworkManagerStub::DoWork()
WinsockNetLayer::PushFreeSmallId(disconnectedSmallId);
if (IQNet::s_playerCount > 1)
IQNet::s_playerCount--;
+ app.DebugPrintf("PlatformNetworkManagerStub: Cleaned up smallId=%d, playerCount=%d\n",
+ disconnectedSmallId, IQNet::s_playerCount);
}
}
BYTE joinedSmallId;
while (WinsockNetLayer::PopPendingJoinSmallId(&joinedSmallId))
{
+ app.DebugPrintf("PlatformNetworkManagerStub: Processing pending join smallId=%d\n", joinedSmallId);
+ if (!WinsockNetLayer::IsSmallIdConnected(joinedSmallId))
+ {
+ app.DebugPrintf("PlatformNetworkManagerStub: Skipping stale pending join smallId=%d\n", joinedSmallId);
+ continue;
+ }
IQNetPlayer *qnetPlayer = m_pIQNet->GetPlayerBySmallId(joinedSmallId);
if (qnetPlayer != NULL && qnetPlayer->m_smallId == joinedSmallId)
{
+ app.DebugPrintf("PlatformNetworkManagerStub: Notifying join for smallId=%d \"%ls\"\n",
+ joinedSmallId, qnetPlayer->GetGamertag());
NotifyPlayerJoined(qnetPlayer);
}
}
@@ -333,6 +350,7 @@ void CPlatformNetworkManagerStub::DoWork()
Socket *sock = np->GetSocket();
if (sock != NULL && sock->isClosing())
{
+ app.DebugPrintf("PlatformNetworkManagerStub: Socket closing for smallId=%d\n", (int)i);
WinsockNetLayer::CloseConnectionBySmallId((BYTE)i);
}
}
diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp
index c59c227..d985ea3 100644
--- a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp
+++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp
@@ -1315,6 +1315,25 @@ bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool b
}
}
+#ifdef _WINDOWS64
+ if(iPad == 0 && iAction == ACTION_MENU_X && !bRepeat && g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_INVENTORY))
+ {
+ ui.SetTooltips(iPad, -1);
+
+ if(m_bNavigateBack)
+ {
+ ui.NavigateBack(iPad);
+ }
+ else
+ {
+ ui.CloseUIScenes(iPad);
+ }
+
+ bHandled = true;
+ return S_OK;
+ }
+#endif
+
#ifdef _XBOX
ui.AnimateKeyPress(iPad, iAction);
#else
@@ -1350,6 +1369,12 @@ bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool b
// Standard left click
buttonNum = 0;
quickKeyHeld = FALSE;
+#ifdef _WINDOWS64
+ if(g_KBMInput.IsKeyDown(VK_SHIFT) || g_KBMInput.IsKeyDown(VK_LSHIFT) || g_KBMInput.IsKeyDown(VK_RSHIFT))
+ {
+ quickKeyHeld = TRUE;
+ }
+#endif
ui.PlayUISFX(eSFX_Press);
}
break;
diff --git a/Minecraft.Client/Common/UI/UIControl_Slider.cpp b/Minecraft.Client/Common/UI/UIControl_Slider.cpp
index bd3b1ad..be906a3 100644
--- a/Minecraft.Client/Common/UI/UIControl_Slider.cpp
+++ b/Minecraft.Client/Common/UI/UIControl_Slider.cpp
@@ -80,6 +80,20 @@ void UIControl_Slider::handleSliderMove(int newValue)
}
}
+void UIControl_Slider::SetSliderValue(int newValue)
+{
+ if(newValue < m_min) newValue = m_min;
+ if(newValue > m_max) newValue = m_max;
+
+ float fTouchPos = 0.0f;
+ if(m_max > m_min)
+ {
+ fTouchPos = (float)(newValue - m_min) / (float)(m_max - m_min);
+ }
+
+ SetSliderTouchPos(fTouchPos);
+}
+
void UIControl_Slider::SetSliderTouchPos(float fTouchPos)
{
IggyDataValue result;
diff --git a/Minecraft.Client/Common/UI/UIControl_Slider.h b/Minecraft.Client/Common/UI/UIControl_Slider.h
index 0b57c2f..a0d1f42 100644
--- a/Minecraft.Client/Common/UI/UIControl_Slider.h
+++ b/Minecraft.Client/Common/UI/UIControl_Slider.h
@@ -24,6 +24,7 @@ public:
void init(const wstring &label, int id, int min, int max, int current);
void handleSliderMove(int newValue);
+ void SetSliderValue(int newValue);
void SetSliderTouchPos(float fTouchPos);
virtual void setAllPossibleLabels(int labelCount, wchar_t labels[][256]);
diff --git a/Minecraft.Client/Common/UI/UIController.cpp b/Minecraft.Client/Common/UI/UIController.cpp
index 9f7a41e..05afd4e 100644
--- a/Minecraft.Client/Common/UI/UIController.cpp
+++ b/Minecraft.Client/Common/UI/UIController.cpp
@@ -1048,7 +1048,7 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
case ACTION_MENU_DOWN: vk = VK_DOWN; break;
case ACTION_MENU_LEFT: vk = VK_LEFT; break;
case ACTION_MENU_RIGHT: vk = VK_RIGHT; break;
- case ACTION_MENU_X: vk = 'E'; break;
+ case ACTION_MENU_X: vk = KeyboardMouseInput::KEY_INVENTORY; break;
case ACTION_MENU_Y: vk = VK_TAB; break;
case ACTION_MENU_LEFT_SCROLL: vk = 'Q'; break;
case ACTION_MENU_RIGHT_SCROLL: vk = 'R'; break;
@@ -1069,6 +1069,12 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT)) { released = true; down = false; }
if (!pressed && !released && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT)) { down = true; }
}
+ else if (!keyboardTextEntryActive && key == ACTION_MENU_X && !g_KBMInput.IsMouseGrabbed())
+ {
+ if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT)) { pressed = true; down = true; }
+ if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_RIGHT)) { released = true; down = false; }
+ if (!pressed && !released && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_RIGHT)) { down = true; }
+ }
// scroll
if (!g_KBMInput.IsMouseGrabbed())
diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp
index f50de39..5779fbc 100644
--- a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp
@@ -288,6 +288,14 @@ void UIScene_AbstractContainerMenu::handleInput(int iPad, int key, bool repeat,
//app.DebugPrintf("UIScene_InventoryMenu handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE");
ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
+#ifdef _WINDOWS64
+ if(iPad == 0 && key == ACTION_MENU_A && !repeat && !g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_RIGHT))
+ {
+ handled = handleKeyDown(m_iPad, ACTION_MENU_X, false);
+ return;
+ }
+#endif
+
if(pressed)
{
handled = handleKeyDown(m_iPad, key, repeat);
diff --git a/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp
index dfe9451..5a2dd7b 100644
--- a/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.cpp
@@ -5,6 +5,16 @@
#include "../../../Minecraft.World/net.minecraft.world.inventory.h"
#include "UIScene_CraftingMenu.h"
+#ifdef _WINDOWS64
+#include "../../KeyboardMouseInput.h"
+extern HWND g_hWnd;
+
+static S32 RoundWindowsCraftingMetric(F32 value)
+{
+ return (S32)(value + 0.5f);
+}
+#endif
+
#ifdef __PSVITA__
#define GAME_CRAFTING_TOUCHUPDATE_TIMER_ID 0
#define GAME_CRAFTING_TOUCHUPDATE_TIMER_TIME 100
@@ -544,6 +554,302 @@ bool UIScene_CraftingMenu::allowRepeat(int key)
return true;
}
+#ifdef _WINDOWS64
+bool UIScene_CraftingMenu::getWindowsMouseScenePos(S32 &x, S32 &y)
+{
+ if(!g_hWnd)
+ {
+ return false;
+ }
+
+ RECT rc;
+ GetClientRect(g_hWnd, &rc);
+ int winW = rc.right - rc.left;
+ int winH = rc.bottom - rc.top;
+ if(winW <= 0 || winH <= 0)
+ {
+ return false;
+ }
+
+ x = (S32)((F32)g_KBMInput.GetMouseX() * (ui.getScreenWidth() / (F32)winW));
+ y = (S32)((F32)g_KBMInput.GetMouseY() * (ui.getScreenHeight() / (F32)winH));
+ return true;
+}
+
+bool UIScene_CraftingMenu::isPointInControl(S32 x, S32 y, UIControl &control, S32 offsetX, S32 offsetY)
+{
+ S32 cx = offsetX + control.getXPos();
+ S32 cy = offsetY + control.getYPos();
+ return x >= cx && x <= cx + control.getWidth() && y >= cy && y <= cy + control.getHeight();
+}
+
+bool UIScene_CraftingMenu::isPointInWindowsGroupTab(S32 mouseX, S32 mouseY, int group)
+{
+ const S32 smallTabOffsets[7] = { 0, 70, 139, 209, 279, 348, 418 };
+ F32 scale = 1.0f;
+ S32 tabX = m_controlMainPanel.getXPos();
+ S32 tabY = m_controlMainPanel.getYPos();
+ S32 tabWidth = 72;
+ S32 tabHeight = 56;
+
+ if(m_loadedResolution == eSceneResolution_720 || m_loadedResolution == eSceneResolution_1080)
+ {
+ scale = ui.getScreenHeight() / 720.0f;
+ if(scale <= 0.0f)
+ {
+ scale = 1.0f;
+ }
+
+ tabWidth = RoundWindowsCraftingMetric(107.0f * scale);
+ tabHeight = RoundWindowsCraftingMetric(85.0f * scale);
+ tabX = m_controlMainPanel.getXPos() - RoundWindowsCraftingMetric(3.0f * scale) + RoundWindowsCraftingMetric((98.0f * scale) * group);
+ tabY = m_controlMainPanel.getYPos() - RoundWindowsCraftingMetric(5.0f * scale);
+ }
+ else
+ {
+ scale = ui.getScreenHeight() == 480.0f ? 1.0f : ui.getScreenHeight() / 360.0f;
+ if(scale <= 0.0f)
+ {
+ scale = 1.0f;
+ }
+
+ tabWidth = RoundWindowsCraftingMetric(72.0f * scale);
+ tabHeight = RoundWindowsCraftingMetric(56.0f * scale);
+ tabX = m_controlMainPanel.getXPos() + RoundWindowsCraftingMetric(smallTabOffsets[group] * scale);
+ tabY = m_controlMainPanel.getYPos() - RoundWindowsCraftingMetric(2.0f * scale);
+ }
+
+ return mouseX >= tabX && mouseX <= tabX + tabWidth && mouseY >= tabY && mouseY <= tabY + tabHeight;
+}
+
+bool UIScene_CraftingMenu::setGroupFromWindowsMouse(S32 mouseX, S32 mouseY, bool &handled)
+{
+ int maxGroup = m_iContainerType == RECIPE_TYPE_3x3 ? m_iMaxGroup3x3 : m_iMaxGroup2x2;
+ S32 panelX = m_controlMainPanel.getXPos();
+ S32 panelY = m_controlMainPanel.getYPos();
+
+ for(int group = 0; group < maxGroup; ++group)
+ {
+ if(isPointInWindowsGroupTab(mouseX, mouseY, group))
+ {
+ if(group != m_iGroupIndex)
+ {
+ showTabHighlight(m_iGroupIndex, false);
+ m_iGroupIndex = group;
+ showTabHighlight(m_iGroupIndex, true);
+ }
+
+ m_iCurrentSlotHIndex = 0;
+ m_iCurrentSlotVIndex = 1;
+ CheckRecipesAvailable();
+ iVSlotIndexA[0] = CanBeMadeA[m_iCurrentSlotHIndex].iCount - 1;
+ iVSlotIndexA[1] = 0;
+ iVSlotIndexA[2] = 1;
+ UpdateVerticalSlots();
+ UpdateHighlight();
+ setGroupText(GetGroupNameText(m_pGroupA[m_iGroupIndex]));
+ ui.PlayUISFX(eSFX_Focus);
+ handled = true;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool UIScene_CraftingMenu::handleWindowsMouseRecipeSelect(bool &handled)
+{
+ if(!g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT))
+ {
+ return false;
+ }
+
+ S32 mouseX = 0;
+ S32 mouseY = 0;
+ if(!getWindowsMouseScenePos(mouseX, mouseY))
+ {
+ return false;
+ }
+
+ S32 panelX = m_controlMainPanel.getXPos();
+ S32 panelY = m_controlMainPanel.getYPos();
+
+ if(setGroupFromWindowsMouse(mouseX, mouseY, handled))
+ {
+ return true;
+ }
+
+ if(isPointInControl(mouseX, mouseY, m_slotListCraftingHSlots, panelX, panelY))
+ {
+ S32 slotSize = m_slotListCraftingHSlots.getHeight();
+ S32 slotX = m_slotListCraftingHSlots.getXPos();
+
+ if(slotSize <= 0)
+ {
+ slotSize = m_slotListCraftingHSlots.getWidth() / m_iCraftablesMaxHSlotC;
+ }
+
+ if(slotSize > 0)
+ {
+ int newSlot = (mouseX - panelX - slotX) / slotSize;
+ if(newSlot >= 0 && newSlot < m_iCraftablesMaxHSlotC && CanBeMadeA[newSlot].iCount > 0)
+ {
+ int oldSlot = m_iCurrentSlotHIndex;
+ m_iCurrentSlotHIndex = newSlot;
+ m_iCurrentSlotVIndex = 1;
+ iVSlotIndexA[0] = CanBeMadeA[m_iCurrentSlotHIndex].iCount - 1;
+ iVSlotIndexA[1] = 0;
+ iVSlotIndexA[2] = 1;
+
+ UpdateVerticalSlots();
+ UpdateHighlight();
+ if(CanBeMadeA[oldSlot].iCount > 0)
+ {
+ setShowCraftHSlot(oldSlot, true);
+ }
+ ui.PlayUISFX(eSFX_Focus);
+ handled = true;
+ return true;
+ }
+ }
+ }
+
+ UIControl *activeSelector = NULL;
+ int activeSlotCount = 0;
+ int activeSlotIndices[3] = { 0, 1, 2 };
+
+ if(m_bSplitscreen ||(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()))
+ {
+ activeSelector = &m_control1Selector;
+ activeSlotCount = 1;
+ activeSlotIndices[0] = 1;
+ }
+ else if(CanBeMadeA[m_iCurrentSlotHIndex].iCount <= 2)
+ {
+ activeSelector = &m_control2Selector;
+ activeSlotCount = 2;
+ activeSlotIndices[0] = 1;
+ activeSlotIndices[1] = 0;
+ }
+ else
+ {
+ activeSelector = &m_control3Selector;
+ activeSlotCount = 3;
+ }
+
+ if(CanBeMadeA[m_iCurrentSlotHIndex].iCount > 1)
+ {
+ S32 slotSize = m_slotListCraftingHSlots.getHeight();
+ if(slotSize <= 0 && m_iCraftablesMaxHSlotC > 0)
+ {
+ slotSize = m_slotListCraftingHSlots.getWidth() / m_iCraftablesMaxHSlotC;
+ }
+
+ if(slotSize > 0 && activeSlotCount > 0)
+ {
+ S32 hSlotX = panelX + m_slotListCraftingHSlots.getXPos() + (m_iCurrentSlotHIndex * slotSize);
+ S32 hSlotY = panelY + m_slotListCraftingHSlots.getYPos();
+ S32 hitLeft = hSlotX - (slotSize / 3);
+ S32 hitRight = hSlotX + slotSize + (slotSize / 3);
+ S32 hitTop = hSlotY;
+
+ if(activeSlotCount > 1)
+ {
+ hitTop -= slotSize;
+ }
+
+ if(mouseX >= hitLeft && mouseX <= hitRight && mouseY >= hitTop && mouseY <= hitTop + (slotSize * activeSlotCount))
+ {
+ int row = (mouseY - hitTop) / slotSize;
+ if(row < 0)
+ {
+ row = 0;
+ }
+ else if(row >= activeSlotCount)
+ {
+ row = activeSlotCount - 1;
+ }
+
+ m_iCurrentSlotVIndex = activeSlotIndices[row];
+ UpdateHighlight();
+ ui.PlayUISFX(eSFX_Focus);
+ handled = true;
+ return true;
+ }
+ }
+ }
+
+ UIControl *selectors[3] = { &m_control3Selector, &m_control2Selector, &m_control1Selector };
+ UIControl_SlotList *slots[3] = { &m_slotListCrafting3VSlots[0], &m_slotListCrafting3VSlots[1], &m_slotListCrafting3VSlots[2] };
+ int slotIndices[3] = { 0, 1, 2 };
+
+ if(m_bSplitscreen ||(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()))
+ {
+ selectors[0] = &m_control1Selector;
+ slots[0] = &m_slotListCrafting1VSlots;
+ slotIndices[0] = 1;
+ selectors[1] = NULL;
+ selectors[2] = NULL;
+ }
+ else if(CanBeMadeA[m_iCurrentSlotHIndex].iCount <= 2)
+ {
+ selectors[0] = &m_control2Selector;
+ slots[0] = &m_slotListCrafting2VSlots[0];
+ slotIndices[0] = 1;
+ selectors[1] = &m_control2Selector;
+ slots[1] = &m_slotListCrafting2VSlots[1];
+ slotIndices[1] = 0;
+ selectors[2] = NULL;
+ }
+
+ for(int i = 0; i < 3; ++i)
+ {
+ if(selectors[i] == NULL || slots[i] == NULL)
+ {
+ continue;
+ }
+
+ S32 selectorX = panelX + selectors[i]->getXPos();
+ S32 selectorY = panelY + selectors[i]->getYPos();
+ if(isPointInControl(mouseX, mouseY, *slots[i], selectorX, selectorY))
+ {
+ m_iCurrentSlotVIndex = slotIndices[i];
+ UpdateHighlight();
+ ui.PlayUISFX(eSFX_Focus);
+ handled = true;
+ return true;
+ }
+ }
+
+ if(activeSelector != NULL && activeSlotCount > 0 && isPointInControl(mouseX, mouseY, *activeSelector, panelX, panelY))
+ {
+ S32 selectorTop = panelY + activeSelector->getYPos();
+ S32 selectorHeight = activeSelector->getHeight();
+ int row = 0;
+ if(selectorHeight > 0)
+ {
+ row = ((mouseY - selectorTop) * activeSlotCount) / selectorHeight;
+ }
+ if(row < 0)
+ {
+ row = 0;
+ }
+ else if(row >= activeSlotCount)
+ {
+ row = activeSlotCount - 1;
+ }
+
+ m_iCurrentSlotVIndex = activeSlotIndices[row];
+ UpdateHighlight();
+ ui.PlayUISFX(eSFX_Focus);
+ handled = true;
+ return true;
+ }
+
+ return false;
+}
+#endif
+
void UIScene_CraftingMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
//app.DebugPrintf("UIScene_InventoryMenu handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE");
@@ -553,11 +859,30 @@ void UIScene_CraftingMenu::handleInput(int iPad, int key, bool repeat, bool pres
{
case ACTION_MENU_OTHER_STICK_UP:
case ACTION_MENU_OTHER_STICK_DOWN:
+#ifdef _WINDOWS64
+ if(iPad == 0 && g_KBMInput.IsKBMActive() && !g_KBMInput.IsMouseGrabbed() && pressed)
+ {
+ handled = handleKeyDown(m_iPad, key == ACTION_MENU_OTHER_STICK_UP ? ACTION_MENU_UP : ACTION_MENU_DOWN, repeat);
+ break;
+ }
+#endif
sendInputToMovie(key,repeat,pressed,released);
break;
default:
if(pressed)
{
+#ifdef _WINDOWS64
+ if(iPad == 0 && key == ACTION_MENU_RIGHT_SCROLL && !repeat && g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_CRAFTING_ALT))
+ {
+ handled = handleKeyDown(m_iPad, ACTION_MENU_B, false);
+ break;
+ }
+
+ if(iPad == 0 && key == ACTION_MENU_A && handleWindowsMouseRecipeSelect(handled))
+ {
+ break;
+ }
+#endif
handled = handleKeyDown(m_iPad, key, repeat);
}
break;
diff --git a/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h
index 44a39d6..a52b41f 100644
--- a/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h
+++ b/Minecraft.Client/Common/UI/UIScene_CraftingMenu.h
@@ -86,7 +86,6 @@ protected:
IggyName m_funcMoveSelector, m_funcSelectVerticalItem, m_funcSetActiveTab;
IggyName m_funcShowPanelDisplay, m_funcShowIngredientSlot;
-#ifdef __PSVITA__
enum ETouchInput
{
ETouchInput_TouchPanel_0,
@@ -100,6 +99,8 @@ protected:
ETouchInput_Count,
};
+
+#ifdef __PSVITA__
UIControl_Touch m_TouchInput[ETouchInput_Count];
S32 m_iCraftingSlotTouchStartY;
#endif
@@ -177,6 +178,14 @@ protected:
virtual bool allowRepeat(int key);
void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
+#ifdef _WINDOWS64
+ bool getWindowsMouseScenePos(S32 &x, S32 &y);
+ bool isPointInControl(S32 x, S32 y, UIControl &control, S32 offsetX = 0, S32 offsetY = 0);
+ bool handleWindowsMouseRecipeSelect(bool &handled);
+ bool setGroupFromWindowsMouse(S32 mouseX, S32 mouseY, bool &handled);
+ bool isPointInWindowsGroupTab(S32 mouseX, S32 mouseY, int group);
+#endif
+
protected:
virtual int getPad();
virtual void hideAllHSlots();
diff --git a/Minecraft.Client/Common/UI/UIScene_HUD.cpp b/Minecraft.Client/Common/UI/UIScene_HUD.cpp
index 09cdf8a..4a4fa7d 100644
--- a/Minecraft.Client/Common/UI/UIScene_HUD.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_HUD.cpp
@@ -18,7 +18,7 @@ UIScene_HUD::UIScene_HUD(int iPad, void *initData, UILayer *parentLayer) : UISce
initialiseMovie();
m_lastActiveSlot = 0;
- m_lastScale = 1;
+ m_lastScale = -1;
m_bToolTipsVisible = true;
m_lastExpProgress = 0.0f;
m_lastExpLevel = 0;
@@ -230,7 +230,7 @@ void UIScene_HUD::customDraw(IggyCustomDrawCallbackRegion *region)
void UIScene_HUD::handleReload()
{
m_lastActiveSlot = 0;
- m_lastScale = 1;
+ m_lastScale = -1;
m_bToolTipsVisible = true;
m_lastExpProgress = 0.0f;
m_lastExpLevel = 0;
diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp
index 6d892d7..70f0a72 100644
--- a/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_SettingsAudioMenu.cpp
@@ -72,6 +72,7 @@ void UIScene_SettingsAudioMenu::handleInput(int iPad, int key, bool repeat, bool
case ACTION_MENU_CANCEL:
if(pressed)
{
+ app.CheckGameSettingsChanged(true,m_iPad);
navigateBack();
}
break;
diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsControlMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsControlMenu.cpp
index d5447f7..b6a0c35 100644
--- a/Minecraft.Client/Common/UI/UIScene_SettingsControlMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_SettingsControlMenu.cpp
@@ -71,6 +71,7 @@ void UIScene_SettingsControlMenu::handleInput(int iPad, int key, bool repeat, bo
case ACTION_MENU_CANCEL:
if(pressed)
{
+ app.CheckGameSettingsChanged(true,m_iPad);
navigateBack();
handled = true;
}
diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp
index 0ee21be..00a9426 100644
--- a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp
@@ -130,6 +130,7 @@ void UIScene_SettingsGraphicsMenu::handleInput(int iPad, int key, bool repeat, b
}
}
+ app.CheckGameSettingsChanged(true,m_iPad);
navigateBack();
handled = true;
}
diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp
index 72576de..1728079 100644
--- a/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_SettingsOptionsMenu.cpp
@@ -200,6 +200,7 @@ void UIScene_SettingsOptionsMenu::handleInput(int iPad, int key, bool repeat, bo
// 4J-PB - don't action changes here or we might write to the profile on backing out here and then get a change in the settings all, and write again on backing out there
//app.CheckGameSettingsChanged(true,pInputData->UserIndex);
+ app.CheckGameSettingsChanged(true,m_iPad);
navigateBack();
}
diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp
index 917012d..15e7c65 100644
--- a/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_SettingsUIMenu.cpp
@@ -110,6 +110,7 @@ void UIScene_SettingsUIMenu::handleInput(int iPad, int key, bool repeat, bool pr
{
// changed
app.SetGameSettings(m_iPad,eGameSetting_SplitScreenVertical,m_checkboxSplitscreen.IsChecked()?1:0);
+ app.CheckGameSettingsChanged(true,m_iPad);
// close the xui scenes, so we don't have the navigate backed to menu at the wrong place
if(app.GetLocalPlayerCount()==2)
@@ -123,6 +124,7 @@ void UIScene_SettingsUIMenu::handleInput(int iPad, int key, bool repeat, bool pr
}
else
{
+ app.CheckGameSettingsChanged(true,m_iPad);
navigateBack();
}
handled = true;
@@ -136,8 +138,34 @@ void UIScene_SettingsUIMenu::handleInput(int iPad, int key, bool repeat, bool pr
break;
case ACTION_MENU_UP:
case ACTION_MENU_DOWN:
+ sendInputToMovie(key, repeat, pressed, released);
+ break;
case ACTION_MENU_LEFT:
case ACTION_MENU_RIGHT:
+ if(pressed && !repeat)
+ {
+ int direction = key == ACTION_MENU_RIGHT ? 1 : -1;
+ if(m_sliderUISize.hasFocus())
+ {
+ int value = app.GetGameSettings(m_iPad,eGameSetting_UISize) + 1 + direction;
+ if(value < 1) value = 1;
+ if(value > 3) value = 3;
+ m_sliderUISize.SetSliderValue(value);
+ handleSliderMove(eControl_UISize, value);
+ handled = true;
+ break;
+ }
+ if(m_sliderUISizeSplitscreen.hasFocus())
+ {
+ int value = app.GetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen) + 1 + direction;
+ if(value < 1) value = 1;
+ if(value > 3) value = 3;
+ m_sliderUISizeSplitscreen.SetSliderValue(value);
+ handleSliderMove(eControl_UISizeSplitscreen, value);
+ handled = true;
+ break;
+ }
+ }
sendInputToMovie(key, repeat, pressed, released);
break;
}
@@ -159,6 +187,7 @@ void UIScene_SettingsUIMenu::handleSliderMove(F64 sliderId, F64 currentValue)
if(value != app.GetGameSettings(m_iPad,eGameSetting_UISize)+1)
{
app.SetGameSettings(m_iPad,eGameSetting_UISize,value-1);
+ app.CheckGameSettingsChanged(true,m_iPad);
// Apply the changes to the selected text position
ui.UpdateSelectedItemPos(m_iPad);
}
@@ -174,6 +203,7 @@ void UIScene_SettingsUIMenu::handleSliderMove(F64 sliderId, F64 currentValue)
{
// slider is 1 to 3
app.SetGameSettings(m_iPad,eGameSetting_UISizeSplitscreen,value-1);
+ app.CheckGameSettingsChanged(true,m_iPad);
// Apply the changes to the selected text position
ui.UpdateSelectedItemPos(m_iPad);
}
diff --git a/Minecraft.Client/Minecraft.Client.vcxproj b/Minecraft.Client/Minecraft.Client.vcxproj
index 54e3e23..28d92a4 100644
--- a/Minecraft.Client/Minecraft.Client.vcxproj
+++ b/Minecraft.Client/Minecraft.Client.vcxproj
@@ -233,34 +233,34 @@
Application
MultiByte
- v110
+ v145
Application
Unicode
- v110
+ v145
false
Application
MultiByte
- v110
+ v145
Application
MultiByte
- v110
+ v145
Application
Unicode
- v110
+ v145
true
Application
Unicode
- v110
+ v145
true
@@ -336,49 +336,49 @@
Application
MultiByte
true
- v110
+ v145
Application
MultiByte
true
- v110
+ v145
Application
MultiByte
true
- v110
+ v145
Application
MultiByte
true
- v110
+ v145
Application
Unicode
true
- v110
+ v145
Application
MultiByte
true
- v110
+ v145
Application
MultiByte
true
- v110
+ v145
Application
MultiByte
true
- v110
+ v145
Application
@@ -38423,4 +38423,4 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU
-
+
\ No newline at end of file
diff --git a/Minecraft.Client/Minecraft.Client.vcxproj.filters b/Minecraft.Client/Minecraft.Client.vcxproj.filters
index 9f24100..a2d451c 100644
--- a/Minecraft.Client/Minecraft.Client.vcxproj.filters
+++ b/Minecraft.Client/Minecraft.Client.vcxproj.filters
@@ -3634,6 +3634,9 @@
Common\Source Files\UI\Scenes
+
+ Header Files
+
@@ -5736,6 +5739,45 @@
Common\Source Files\UI\Scenes
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
@@ -6107,10 +6149,7 @@
PS3\SPUObjFiles\ContentPackage
-
-
-
-
+
\ No newline at end of file
diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp
index 69b4dcf..ed4908f 100644
--- a/Minecraft.Client/Minecraft.cpp
+++ b/Minecraft.Client/Minecraft.cpp
@@ -1621,8 +1621,24 @@ void Minecraft::run_middle()
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DEBUG_INFO))
{
+#ifdef _DEBUG_MENUS_ENABLED
+ if(i == ProfileManager.GetPrimaryPad())
+ {
+ options->renderDebug = !options->renderDebug;
+ }
+#else
localplayers[i]->ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<renderDebug = !options->renderDebug;
#ifdef _XBOX
+ options->renderDebug = !options->renderDebug;
app.EnableDebugOverlay(options->renderDebug,iPad);
#else
// 4J Stu - The xbox uses a completely different way of navigating to this scene
diff --git a/Minecraft.Client/PendingConnection.cpp b/Minecraft.Client/PendingConnection.cpp
index ceea182..526d505 100644
--- a/Minecraft.Client/PendingConnection.cpp
+++ b/Minecraft.Client/PendingConnection.cpp
@@ -94,7 +94,8 @@ void PendingConnection::handlePreLogin(shared_ptr packet)
return;
}
// printf("Server: handlePreLogin\n");
- app.DebugPrintf("PreLogin received from \"%ls\"\n", packet->loginKey.c_str());
+ app.DebugPrintf("PreLogin received from \"%ls\" smallId=%d\n",
+ packet->loginKey.c_str(), connection && connection->getSocket() ? connection->getSocket()->getSmallId() : 0);
name = packet->loginKey; // 4J Stu - Change from the login packet as we know better on client end during the pre-login packet
sendPreLoginResponse();
}
@@ -149,7 +150,8 @@ void PendingConnection::sendPreLoginResponse()
void PendingConnection::handleLogin(shared_ptr packet)
{
- app.DebugPrintf("Login received from \"%ls\" (protocol %d)\n", name.c_str(), packet->clientVersion);
+ app.DebugPrintf("Login received from \"%ls\" (protocol %d) smallId=%d\n",
+ name.c_str(), packet->clientVersion, connection && connection->getSocket() ? connection->getSocket()->getSmallId() : 0);
// printf("Server: handleLogin\n");
//name = packet->userName;
if (packet->clientVersion != SharedConstants::NETWORK_PROTOCOL_VERSION)
@@ -296,9 +298,15 @@ void PendingConnection::handleAcceptedLogin(shared_ptr packet)
shared_ptr playerEntity = server->getPlayers()->getPlayerForLogin(this, name, playerXuid,packet->m_onlineXuid);
if (playerEntity != NULL)
{
+ app.DebugPrintf("PendingConnection: Placing \"%ls\" smallId=%d\n",
+ name.c_str(), connection && connection->getSocket() ? connection->getSocket()->getSmallId() : 0);
server->getPlayers()->placeNewPlayer(connection, playerEntity, packet);
connection = NULL; // We've moved responsibility for this over to the new PlayerConnection, NULL so we don't delete our reference to it here in our dtor
}
+ else
+ {
+ app.DebugPrintf("PendingConnection: getPlayerForLogin returned NULL for \"%ls\"\n", name.c_str());
+ }
done = true;
}
@@ -348,4 +356,4 @@ wstring PendingConnection::getName()
bool PendingConnection::isServerPacketListener()
{
return true;
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Platform_Libs/Dev/Render/RendererCore.cpp b/Minecraft.Client/Platform_Libs/Dev/Render/RendererCore.cpp
index 5069422..c3e5289 100644
--- a/Minecraft.Client/Platform_Libs/Dev/Render/RendererCore.cpp
+++ b/Minecraft.Client/Platform_Libs/Dev/Render/RendererCore.cpp
@@ -621,16 +621,14 @@ void Renderer::Present()
if (m_bShouldScreenGrabNextFrame)
{
PROFILER_SCOPE("Renderer::Present", "ScreenGrab", MP_MAGENTA)
-
- unsigned char *linearData = new unsigned char[kScreenGrabWidth * kScreenGrabHeight * 4];
ID3D11Texture2D *backBuffer = NULL;
ID3D11Texture2D *stagingTexture = NULL;
+ D3D11_TEXTURE2D_DESC desc = {};
m_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer));
if (backBuffer)
{
- D3D11_TEXTURE2D_DESC desc = {};
backBuffer->GetDesc(&desc);
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
@@ -639,6 +637,11 @@ void Renderer::Present()
m_pDevice->CreateTexture2D(&desc, NULL, &stagingTexture);
}
+ const UINT screenGrabWidth = desc.Width ? desc.Width : kScreenGrabWidth;
+ const UINT screenGrabHeight = desc.Height ? desc.Height : kScreenGrabHeight;
+ unsigned char *linearData = new unsigned char[screenGrabWidth * screenGrabHeight * 4];
+ memset(linearData, 0, screenGrabWidth * screenGrabHeight * 4);
+
if (stagingTexture && backBuffer)
{
PROFILER_SCOPE("Renderer::Present", "CopyResource", MP_MAGENTA)
@@ -649,14 +652,29 @@ void Renderer::Present()
{
const unsigned char *src = reinterpret_cast(mapped.pData);
- for (UINT y = 0; y < kScreenGrabHeight; ++y)
+ for (UINT y = 0; y < screenGrabHeight; ++y)
{
- unsigned char *dstRow = linearData + y * kScreenGrabWidth * 4;
+ unsigned char *dstRow = linearData + y * screenGrabWidth * 4;
const unsigned char *srcRow = src + y * mapped.RowPitch;
- memcpy(dstRow, srcRow, kScreenGrabWidth * 4);
+ if (desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM || desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB)
+ {
+ for (UINT x = 0; x < screenGrabWidth; ++x)
+ {
+ const unsigned char *srcPixel = srcRow + x * 4;
+ unsigned char *dstPixel = dstRow + x * 4;
+ dstPixel[0] = srcPixel[2];
+ dstPixel[1] = srcPixel[1];
+ dstPixel[2] = srcPixel[0];
+ dstPixel[3] = 0xFF;
+ }
+ }
+ else
+ {
+ memcpy(dstRow, srcRow, screenGrabWidth * 4);
- for (UINT x = 0; x < kScreenGrabWidth; ++x)
- dstRow[x * 4 + 3] = 0xFF;
+ for (UINT x = 0; x < screenGrabWidth; ++x)
+ dstRow[x * 4 + 3] = 0xFF;
+ }
}
m_pDeviceContext->Unmap(stagingTexture, 0);
@@ -664,12 +682,27 @@ void Renderer::Present()
}
static int count = 0;
- char fileName[304];
- sprintf_s(fileName, "d:\\screen%d.png", count++);
+ CreateDirectoryA("screenshots", NULL);
+
+ SYSTEMTIME now;
+ GetLocalTime(&now);
+
+ char fileName[MAX_PATH];
+ sprintf_s(
+ fileName,
+ "screenshots\\screenshot_%04d%02d%02d_%02d%02d%02d_%03d_%03d.png",
+ now.wYear,
+ now.wMonth,
+ now.wDay,
+ now.wHour,
+ now.wMinute,
+ now.wSecond,
+ now.wMilliseconds,
+ count++);
D3DXIMAGE_INFO info;
- info.Width = kScreenGrabWidth;
- info.Height = kScreenGrabHeight;
+ info.Width = screenGrabWidth;
+ info.Height = screenGrabHeight;
SaveTextureData(fileName, &info, reinterpret_cast(linearData));
delete[] linearData;
diff --git a/Minecraft.Client/ServerConnection.cpp b/Minecraft.Client/ServerConnection.cpp
index 4a23e23..c095294 100644
--- a/Minecraft.Client/ServerConnection.cpp
+++ b/Minecraft.Client/ServerConnection.cpp
@@ -29,12 +29,15 @@ ServerConnection::~ServerConnection()
// 4J - added to handle incoming connections, to replace thread that original used to have
void ServerConnection::NewIncomingSocket(Socket *socket)
{
+ app.DebugPrintf("ServerConnection: New incoming socket smallId=%d\n", socket ? socket->getSmallId() : 0);
shared_ptr unconnectedClient = shared_ptr(new PendingConnection(server, socket, L"Connection #" + _toString(connectionCounter++)));
handleConnection(unconnectedClient);
}
void ServerConnection::addPlayerConnection(shared_ptr uc)
{
+ if (uc != NULL && uc->connection != NULL && uc->connection->getSocket() != NULL)
+ app.DebugPrintf("ServerConnection: Added player connection smallId=%d\n", uc->connection->getSocket()->getSmallId());
players.push_back(uc);
}
@@ -200,4 +203,4 @@ void ServerConnection::handleServerSettingsChanged(shared_ptrsetShowOnMaps(pMinecraft->options->GetGamertagSetting());
// }
// }
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp b/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp
index 55a4dea..4900d7c 100644
--- a/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp
+++ b/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp
@@ -639,6 +639,8 @@ void WinsockNetLayer::HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsig
EnterCriticalSection(&s_earlyDataLock);
s_earlyDataBuffers[fromSmallId].insert(
s_earlyDataBuffers[fromSmallId].end(), data, data + dataSize);
+ app.DebugPrintf("Win64 LAN: Buffered %u early bytes for smallId=%d (total=%d)\n",
+ dataSize, fromSmallId, (int)s_earlyDataBuffers[fromSmallId].size());
LeaveCriticalSection(&s_earlyDataLock);
}
return;
@@ -654,6 +656,8 @@ void WinsockNetLayer::HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsig
EnterCriticalSection(&s_earlyDataLock);
s_earlyDataBuffers[fromSmallId].insert(
s_earlyDataBuffers[fromSmallId].end(), data, data + dataSize);
+ app.DebugPrintf("Win64 LAN: Buffered %u bytes waiting for socket smallId=%d (total=%d)\n",
+ dataSize, fromSmallId, (int)s_earlyDataBuffers[fromSmallId].size());
LeaveCriticalSection(&s_earlyDataLock);
}
}
@@ -678,6 +682,8 @@ void WinsockNetLayer::FlushPendingData()
::Socket *pSocket = pPlayer->GetSocket();
if (pSocket == NULL) continue;
+ app.DebugPrintf("Win64 LAN: Flushing %d early bytes for smallId=%d\n",
+ (int)s_earlyDataBuffers[i].size(), (int)i);
pSocket->pushDataToQueue(s_earlyDataBuffers[i].data(),
(DWORD)s_earlyDataBuffers[i].size(), false);
s_earlyDataBuffers[i].clear();
@@ -740,15 +746,6 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
continue;
}
- BYTE assignBuf[1] = { assignedSmallId };
- int sent = send(clientSocket, (const char *)assignBuf, 1, 0);
- if (sent != 1)
- {
- app.DebugPrintf("Failed to send small ID to client\n");
- closesocket(clientSocket);
- continue;
- }
-
u_long nonBlocking = 1;
ioctlsocket(clientSocket, FIONBIO, &nonBlocking);
@@ -785,7 +782,17 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
EnterCriticalSection(&s_pendingJoinLock);
s_pendingJoinSmallIds.push_back(assignedSmallId);
+ app.DebugPrintf("Win64 LAN: Queued pending join for smallId=%d\n", assignedSmallId);
LeaveCriticalSection(&s_pendingJoinLock);
+
+ BYTE assignBuf[1] = { assignedSmallId };
+ int sent = send(clientSocket, (const char *)assignBuf, 1, 0);
+ if (sent != 1)
+ {
+ app.DebugPrintf("Win64 LAN: Failed to send small ID to client smallId=%d\n", assignedSmallId);
+ MarkConnectionDisconnected(assignedSmallId);
+ continue;
+ }
}
return 0;
}
@@ -805,7 +812,7 @@ bool WinsockNetLayer::ProcessRecvData(Win64RemoteConnection &conn)
if (packetSize <= 0 || (unsigned int)packetSize > WIN64_NET_MAX_PACKET_SIZE)
{
app.DebugPrintf("Win64 LAN: Invalid packet size %d from smallId=%d\n", packetSize, conn.smallId);
- conn.active = false;
+ MarkConnectionDisconnected(conn.smallId);
return false;
}
@@ -821,7 +828,8 @@ bool WinsockNetLayer::ProcessRecvData(Win64RemoteConnection &conn)
BYTE *newBuf = (BYTE *)realloc(conn.recvBuffer, newSize);
if (newBuf == NULL)
{
- conn.active = false;
+ app.DebugPrintf("Win64 LAN: Failed to grow receive buffer for smallId=%d\n", conn.smallId);
+ MarkConnectionDisconnected(conn.smallId);
return false;
}
conn.recvBuffer = newBuf;
@@ -842,6 +850,47 @@ bool WinsockNetLayer::ProcessRecvData(Win64RemoteConnection &conn)
return (remaining >= 4);
}
+void WinsockNetLayer::MarkConnectionDisconnected(BYTE smallId)
+{
+ bool shouldNotify = false;
+
+ EnterCriticalSection(&s_connectionsLock);
+ if ((size_t)smallId < s_connections.size())
+ {
+ Win64RemoteConnection &conn = s_connections[smallId];
+ shouldNotify = conn.active;
+ conn.active = false;
+
+ if (conn.tcpSocket != INVALID_SOCKET)
+ {
+ closesocket(conn.tcpSocket);
+ conn.tcpSocket = INVALID_SOCKET;
+ }
+
+ EnterCriticalSection(&conn.sendBufLock);
+ conn.sendBufferUsed = 0;
+ LeaveCriticalSection(&conn.sendBufLock);
+
+ conn.recvBufferUsed = 0;
+ conn.currentPacketSize = 0;
+ conn.readingHeader = true;
+ }
+ LeaveCriticalSection(&s_connectionsLock);
+
+ EnterCriticalSection(&s_earlyDataLock);
+ if ((size_t)smallId < s_earlyDataBuffers.size())
+ s_earlyDataBuffers[smallId].clear();
+ LeaveCriticalSection(&s_earlyDataLock);
+
+ if (shouldNotify)
+ {
+ EnterCriticalSection(&s_disconnectLock);
+ s_disconnectedSmallIds.push_back(smallId);
+ LeaveCriticalSection(&s_disconnectLock);
+ app.DebugPrintf("Win64 LAN: Queued disconnect for smallId=%d\n", smallId);
+ }
+}
+
DWORD WINAPI WinsockNetLayer::IOThreadProc(LPVOID param)
{
std::vector pollFds;
@@ -886,13 +935,7 @@ DWORD WINAPI WinsockNetLayer::IOThreadProc(LPVOID param)
if (pollFds[i].revents & (POLLERR | POLLHUP | POLLNVAL))
{
- conn.active = false;
- closesocket(conn.tcpSocket);
- conn.tcpSocket = INVALID_SOCKET;
-
- EnterCriticalSection(&s_disconnectLock);
- s_disconnectedSmallIds.push_back(smallId);
- LeaveCriticalSection(&s_disconnectLock);
+ MarkConnectionDisconnected(smallId);
continue;
}
@@ -907,12 +950,7 @@ DWORD WINAPI WinsockNetLayer::IOThreadProc(LPVOID param)
BYTE *newBuf = (BYTE *)realloc(conn.recvBuffer, newSize);
if (newBuf == NULL)
{
- conn.active = false;
- closesocket(conn.tcpSocket);
- conn.tcpSocket = INVALID_SOCKET;
- EnterCriticalSection(&s_disconnectLock);
- s_disconnectedSmallIds.push_back(smallId);
- LeaveCriticalSection(&s_disconnectLock);
+ MarkConnectionDisconnected(smallId);
break;
}
conn.recvBuffer = newBuf;
@@ -929,12 +967,7 @@ DWORD WINAPI WinsockNetLayer::IOThreadProc(LPVOID param)
}
else if (bytesRead == 0)
{
- conn.active = false;
- closesocket(conn.tcpSocket);
- conn.tcpSocket = INVALID_SOCKET;
- EnterCriticalSection(&s_disconnectLock);
- s_disconnectedSmallIds.push_back(smallId);
- LeaveCriticalSection(&s_disconnectLock);
+ MarkConnectionDisconnected(smallId);
break;
}
else
@@ -942,12 +975,7 @@ DWORD WINAPI WinsockNetLayer::IOThreadProc(LPVOID param)
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK)
break;
- conn.active = false;
- closesocket(conn.tcpSocket);
- conn.tcpSocket = INVALID_SOCKET;
- EnterCriticalSection(&s_disconnectLock);
- s_disconnectedSmallIds.push_back(smallId);
- LeaveCriticalSection(&s_disconnectLock);
+ MarkConnectionDisconnected(smallId);
break;
}
}
@@ -968,6 +996,8 @@ bool WinsockNetLayer::PopDisconnectedSmallId(BYTE *outSmallId)
found = true;
}
LeaveCriticalSection(&s_disconnectLock);
+ if (found)
+ app.DebugPrintf("Win64 LAN: Popped disconnect for smallId=%d\n", *outSmallId);
return found;
}
@@ -976,6 +1006,7 @@ void WinsockNetLayer::PushFreeSmallId(BYTE smallId)
EnterCriticalSection(&s_freeSmallIdLock);
s_freeSmallIds.push_back(smallId);
LeaveCriticalSection(&s_freeSmallIdLock);
+ app.DebugPrintf("Win64 LAN: Returned smallId=%d to free list\n", smallId);
}
bool WinsockNetLayer::PopPendingJoinSmallId(BYTE *outSmallId)
@@ -989,6 +1020,8 @@ bool WinsockNetLayer::PopPendingJoinSmallId(BYTE *outSmallId)
found = true;
}
LeaveCriticalSection(&s_pendingJoinLock);
+ if (found)
+ app.DebugPrintf("Win64 LAN: Popped pending join for smallId=%d\n", *outSmallId);
return found;
}
@@ -1000,27 +1033,8 @@ bool WinsockNetLayer::IsSmallIdConnected(BYTE smallId)
void WinsockNetLayer::CloseConnectionBySmallId(BYTE smallId)
{
- EnterCriticalSection(&s_connectionsLock);
- if ((size_t)smallId < s_connections.size() && s_connections[smallId].active && s_connections[smallId].tcpSocket != INVALID_SOCKET)
- {
- s_connections[smallId].active = false;
- closesocket(s_connections[smallId].tcpSocket);
- s_connections[smallId].tcpSocket = INVALID_SOCKET;
- app.DebugPrintf("Win64 LAN: Force-closed TCP connection for smallId=%d\n", smallId);
- }
- LeaveCriticalSection(&s_connectionsLock);
-
- if ((size_t)smallId < s_connections.size())
- {
- EnterCriticalSection(&s_connections[smallId].sendBufLock);
- s_connections[smallId].sendBufferUsed = 0;
- LeaveCriticalSection(&s_connections[smallId].sendBufLock);
- }
-
- EnterCriticalSection(&s_earlyDataLock);
- if ((size_t)smallId < s_earlyDataBuffers.size())
- s_earlyDataBuffers[smallId].clear();
- LeaveCriticalSection(&s_earlyDataLock);
+ MarkConnectionDisconnected(smallId);
+ app.DebugPrintf("Win64 LAN: Force-closed TCP connection for smallId=%d\n", smallId);
}
void WinsockNetLayer::FlushSendBuffers()
@@ -1031,6 +1045,7 @@ void WinsockNetLayer::FlushSendBuffers()
{
if (!s_connections[i].active) continue;
+ bool disconnectAfterSendError = false;
EnterCriticalSection(&s_connections[i].sendBufLock);
if (s_connections[i].sendBufferUsed > 0 && s_connections[i].tcpSocket != INVALID_SOCKET)
{
@@ -1045,10 +1060,8 @@ void WinsockNetLayer::FlushSendBuffers()
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK)
break;
- s_connections[i].active = false;
- EnterCriticalSection(&s_disconnectLock);
- s_disconnectedSmallIds.push_back((BYTE)i);
- LeaveCriticalSection(&s_disconnectLock);
+ app.DebugPrintf("Win64 LAN: Send failed for smallId=%d err=%d\n", (int)i, err);
+ disconnectAfterSendError = true;
break;
}
if (sent == 0) break;
@@ -1061,6 +1074,9 @@ void WinsockNetLayer::FlushSendBuffers()
s_connections[i].sendBufferUsed = remaining;
}
LeaveCriticalSection(&s_connections[i].sendBufLock);
+
+ if (disconnectAfterSendError)
+ MarkConnectionDisconnected((BYTE)i);
}
}
diff --git a/Minecraft.Client/Windows64/Network/WinsockNetLayer.h b/Minecraft.Client/Windows64/Network/WinsockNetLayer.h
index 70a4c31..9d6e4ba 100644
--- a/Minecraft.Client/Windows64/Network/WinsockNetLayer.h
+++ b/Minecraft.Client/Windows64/Network/WinsockNetLayer.h
@@ -139,6 +139,7 @@ private:
static DWORD WINAPI DiscoveryThreadProc(LPVOID param);
static DWORD WINAPI AsyncJoinThreadProc(LPVOID param);
static bool ProcessRecvData(Win64RemoteConnection &conn);
+ static void MarkConnectionDisconnected(BYTE smallId);
static SOCKET s_listenSocket;
static SOCKET s_hostConnectionSocket;
diff --git a/Minecraft.Server b/Minecraft.Server
index aad5c68..b0bbb51 160000
--- a/Minecraft.Server
+++ b/Minecraft.Server
@@ -1 +1 @@
-Subproject commit aad5c68b7eac04586d13241ea18e9bf6f7170185
+Subproject commit b0bbb51e8078b20b5add5f006dab2819ec31671c
diff --git a/Minecraft.World/Minecraft.World.vcxproj b/Minecraft.World/Minecraft.World.vcxproj
index ffa0622..b3aa438 100644
--- a/Minecraft.World/Minecraft.World.vcxproj
+++ b/Minecraft.World/Minecraft.World.vcxproj
@@ -231,32 +231,32 @@
StaticLibrary
MultiByte
- v110
+ v145
StaticLibrary
Unicode
- v110
+ v145
StaticLibrary
MultiByte
- v110
+ v145
StaticLibrary
MultiByte
- v110
+ v145
StaticLibrary
Unicode
- v110
+ v145
StaticLibrary
Unicode
- v110
+ v145
StaticLibrary
@@ -319,42 +319,42 @@
StaticLibrary
MultiByte
- v110
+ v145
StaticLibrary
MultiByte
- v110
+ v145
StaticLibrary
MultiByte
- v110
+ v145
StaticLibrary
MultiByte
- v110
+ v145
StaticLibrary
Unicode
- v110
+ v145
StaticLibrary
MultiByte
- v110
+ v145
StaticLibrary
MultiByte
- v110
+ v145
StaticLibrary
MultiByte
- v110
+ v145
StaticLibrary
@@ -3964,4 +3964,4 @@
-
+
\ No newline at end of file