Merge branch 'main' into linux-clang-support

This commit is contained in:
Loki 2026-04-12 23:02:08 -05:00 committed by GitHub
commit a015f34e6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 457 additions and 166 deletions

View file

@ -1,48 +0,0 @@
name: Check formatting
on:
pull_request:
paths:
- '**'
- '!.gitignore'
- '!*.md'
- '!.github/**'
- '.github/workflows/clang-format.yml'
permissions:
contents: read
pull-requests: write
jobs:
format-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Fetch base commit
run: git fetch origin ${{ github.event.pull_request.base.sha }}
- name: Install clang-format-20
run: |
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
sudo add-apt-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-20 main"
sudo apt-get install -y -qq clang-format-20
- uses: reviewdog/action-setup@v1
- name: Check formatting on changed lines
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git clang-format-20 --binary clang-format-20 \
--diff ${{ github.event.pull_request.base.sha }} -- \
'*.c' '*.cpp' '*.cc' '*.h' '*.hpp' \
| reviewdog \
-name="clang-format" \
-f=diff \
-reporter=github-pr-check \
-fail-level=error \
-filter-mode=added

15
BACKPORTING.md Normal file
View file

@ -0,0 +1,15 @@
# Approach to Backported Features
All backported features incorperated into MinecraftConsoles should be, when merged, functionally identical to their state in the version of the game we're currently targeting. This should be in reference to a known 4J build of LCE. Verification can either be done by doing a decompilation based match of the implementation or, alternatively, all functionality and limitations of the given feature should be compared against the version of LCE we're targeting.
# Approach to Bugfixes
Anything that does not behave in an "expected" manner, especially if its behavior is not widely accepted as a gameplay mechanic, is valid for fixing in our repository. This includes bugfixes that were made in versions past the version we target, but excludes any visual changes that may not have been included at the build we're targeting.
If you provide a visual bugfix that fixes a distinctive quirk of the LCE renderer, it should be provided in an "off by default" state that can be toggled on in-game by the user. There is no guarantee that we will merge it.
If your visual bugfix is a fix added in a future version of LCE than the one we're targeting, it should also be put behind a toggle or equivalent system for keeping it off by default.
# Targeted Version
We are currently accepting backports for up to and including TU24. Feature backports from TU25 and above will not be accepted.
# Original Codebase
MinecraftConsoles is based on a WIP build of TU19, built on top of the December 2014 codebase.

View file

@ -1,6 +1,9 @@
# Scope of Project
At the moment, this project's scope is generally limited outside of adding new content to the game (blocks, mobs, items). We are currently prioritizing stability, quality of life, and platform support over these things.
## Backporting
If you're backporting a feature, please read [BACKPORTING.md](./BACKPORTING.md)
## Parity
We are attempting to keep our version of LCE as close to visual and experience parity with the original console experience of LCE as possible. This means that we will not be accepting changes that...
- Backport things from Java Edition that did not ever exist in LCE

View file

@ -11,6 +11,7 @@ const wstring ChatScreen::allowedChars = SharedConstants::acceptableLetters;
vector<wstring> ChatScreen::s_chatHistory;
int ChatScreen::s_historyIndex = -1;
wstring ChatScreen::s_historyDraft;
int ChatScreen::s_chatIndex = 0;
bool ChatScreen::isAllowedChatChar(wchar_t c)
{
@ -22,6 +23,8 @@ ChatScreen::ChatScreen()
frame = 0;
cursorIndex = 0;
s_historyIndex = -1;
ChatScreen::s_chatIndex = 0;
}
void ChatScreen::init()
@ -83,6 +86,20 @@ void ChatScreen::handleHistoryDown()
applyHistoryMessage();
}
int ChatScreen::getChatIndex()
{
return ChatScreen::s_chatIndex;
}
void ChatScreen::correctChatIndex(int newChatIndex) {
ChatScreen::s_chatIndex = newChatIndex;
}
void ChatScreen::setWheelValue(int wheel) {
ChatScreen::s_chatIndex += wheel;
if (ChatScreen::s_chatIndex < 0) ChatScreen::s_chatIndex = 0;
}
void ChatScreen::keyPressed(wchar_t ch, int eventKey)
{
if (eventKey == Keyboard::KEY_ESCAPE)
@ -131,6 +148,7 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
cursorIndex--;
return;
}
if (isAllowedChatChar(ch) && static_cast<int>(message.length()) < SharedConstants::maxChatLength)
{
message.insert(cursorIndex, 1, ch);

View file

@ -16,6 +16,7 @@ private:
static std::vector<wstring> s_chatHistory;
static int s_historyIndex;
static wstring s_historyDraft;
static int s_chatIndex;
static const wstring allowedChars;
static bool isAllowedChatChar(wchar_t c);
@ -28,6 +29,9 @@ public:
virtual void handleHistoryUp();
virtual void handleHistoryDown();
static int getChatIndex();
static void correctChatIndex(int newChatIndex);
static void setWheelValue(int wheel);
protected:
void keyPressed(wchar_t ch, int eventKey);
public:

View file

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "UIController.h"
#include <ChatScreen.h>
#include "UI.h"
#include "UIScene.h"
#include "UIControl_Slider.h"
@ -1428,6 +1429,9 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
}
#endif
if (key == 4) ChatScreen::setWheelValue(1);
if (key == 5) ChatScreen::setWheelValue(-1);
if(pressed) app.DebugPrintf("Pressed %d\n",key);
if(released) app.DebugPrintf("Released %d\n",key);
// Repeat handling

View file

@ -491,17 +491,19 @@ SCreditTextItemDef UIScene_Credits::gs_aCreditDefs[MAX_CREDIT_STRINGS] =
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"MinecraftConsoles", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eExtraLargeText},
{L"Project Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
{L"smartcmd", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"codeHusky", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Patoke", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"rtm516", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"mattsumi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"dxf", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"la", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Thank you to our 100+ contributors on GitHub!", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
{L"github.com/smartcmd/MinecraftConsoles", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Project Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
{L"codeHusky", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"mattsumi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Former Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
{L"smartcmd", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Patoke", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"rtm516", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Thank you to our 120+ contributors on GitHub!", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
{L"github.com/MCLCE/MinecraftConsoles", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"(formerly smartcmd/MinecraftConsoles)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Additional Thanks", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},

View file

@ -50,14 +50,7 @@ UIScene_EndPoem::UIScene_EndPoem(int iPad, void *initData, UILayer *parentLayer)
Minecraft *pMinecraft = Minecraft::GetInstance();
wstring playerName = L"";
if(pMinecraft->localplayers[ui.GetWinUserIndex()] != nullptr)
{
playerName = escapeXML( pMinecraft->localplayers[ui.GetWinUserIndex()]->getDisplayName() );
}
else
{
playerName = escapeXML( pMinecraft->localplayers[ProfileManager.GetPrimaryPad()]->getDisplayName() );
}
playerName = escapeXML( pMinecraft->localplayers[ProfileManager.GetPrimaryPad()]->getDisplayName() );
noNoiseString = replaceAll(noNoiseString,L"{*PLAYER*}",playerName);
Random random(8124371);

View file

@ -9,6 +9,7 @@
#include "../../EnderDragonRenderer.h"
#include "../../../Minecraft.World/net.minecraft.world.inventory.h"
#include "../../../Minecraft.World/StringHelpers.h"
#include <ChatScreen.h>
UIScene_HUD::UIScene_HUD(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
@ -761,16 +762,31 @@ void UIScene_HUD::render(S32 width, S32 height, C4JRender::eViewportType viewpor
void UIScene_HUD::handleTimerComplete(int id)
{
Minecraft *pMinecraft = Minecraft::GetInstance();
bool isChatOpen = (dynamic_cast<ChatScreen*>(pMinecraft->getScreen()) != nullptr);
bool anyVisible = false;
if(pMinecraft->localplayers[m_iPad]!= nullptr)
{
Gui *pGui = pMinecraft->gui;
//DWORD messagesToDisplay = min( CHAT_LINES_COUNT, pGui->getMessagesCount(m_iPad) );
for( unsigned int i = 0; i < CHAT_LINES_COUNT; ++i )
DWORD totalMessages = pGui->getMessagesCount(m_iPad);
DWORD messagesToDisplay = min( CHAT_LINES_COUNT, totalMessages);
DWORD maxScroll = max(0, totalMessages - messagesToDisplay);
bool canScroll = messagesToDisplay < totalMessages;
int startIndex = (canScroll && isChatOpen ? ChatScreen::getChatIndex() : 0);
if (startIndex > maxScroll) {
ChatScreen::correctChatIndex(maxScroll);
startIndex = maxScroll;
}
app.DebugPrintf("handleTimerComplete: %d | %d | %d\n", maxScroll, startIndex, totalMessages);
for( unsigned int i = 0; i < messagesToDisplay; ++i )
{
float opacity = pGui->getOpacity(m_iPad, i);
if( opacity > 0 )
unsigned int msgIndex = startIndex + i;
float opacity = pGui->getOpacity(m_iPad, msgIndex);
if( opacity > 0 || isChatOpen)
{
#if 0 // def _WINDOWS64 // Use Iggy chat until Gui::render has visual parity
// Chat drawn by Gui::render with color codes. Hides Iggy chat to avoid double chats.
@ -778,9 +794,10 @@ void UIScene_HUD::handleTimerComplete(int id)
m_labelChatText[i].setOpacity(0);
m_labelChatText[i].setLabel(L"");
#else
m_controlLabelBackground[i].setOpacity(opacity);
m_labelChatText[i].setOpacity(opacity);
m_labelChatText[i].setLabel( pGui->getMessagesCount(m_iPad) ? pGui->getMessage(m_iPad,i) : L"" );
m_controlLabelBackground[i].setOpacity((isChatOpen ? 1 : opacity));
m_labelChatText[i].setOpacity((isChatOpen ? 1 : opacity));
m_labelChatText[i].setLabel(pGui->getMessage(m_iPad, msgIndex));
#endif
anyVisible = true;
}

View file

@ -89,6 +89,11 @@ void EnderDragonRenderer::render(shared_ptr<Entity> _mob, double x, double y, do
// 4J - dynamic cast required because we aren't using templates/generics in our version
shared_ptr<EnderDragon> mob = dynamic_pointer_cast<EnderDragon>(_mob);
BossMobGuiInfo::setBossHealth(mob, false);
if (!mob->getCustomName().empty())
{
BossMobGuiInfo::name = mob->getCustomName();
}
MobRenderer::render(mob, x, y, z, rot, a);
if (mob->nearestCrystal != nullptr)
{

View file

@ -81,7 +81,7 @@ void EntityTracker::addEntity(shared_ptr<Entity> e, int range, int updateInterva
{
assert(false); // Entity already tracked
}
if( e->entityId >= 2048 )
if( e->entityId >= 16384 )
{
__debugbreak();
}

View file

@ -310,6 +310,8 @@ void Font::draw(const wstring &str, bool dropShadow, int initialColor)
t->begin();
t->color(currentColor & 0x00ffffff, (currentColor >> 24) & 255);
bool prev = t->setMipmapEnable(false); // Disable mipmapping for fonts, and save previous enabled value to be restored later - Botch
for (int i = 0; i < static_cast<int>(cleanStr.length()); ++i)
{
// Map character
@ -371,6 +373,8 @@ void Font::draw(const wstring &str, bool dropShadow, int initialColor)
addCharacterQuad(c);
}
t->setMipmapEnable(prev); //Reinstates previously used enabled value - Botch
t->end();
}

View file

@ -1208,7 +1208,20 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
// Disable the depth test so the text shows on top of the paperdoll
glDisable(GL_DEPTH_TEST);
#ifdef _WINDOWS64
float scaleWidth = (g_rScreenWidth / 1920.0f);
float scaleHeight = (g_rScreenHeight / 1080.0f);
float scale = min(scaleWidth, scaleHeight); //stop stretching
if (scale < 0.5f) scale = 0.5f; // force minimum scale
if (scale > 1.2f) // resolutions over 1296 pixels tall
{
scale = scale - 0.33f; // tame overscaling on 1440p
}
glScalef(scale, scale, 1);
#endif
// Loop through the lines and draw them all on screen
int yPos = debugTop;
for (const auto &line : lines)
@ -1217,6 +1230,9 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
yPos += 10;
}
#ifdef _WINDOWS64
glScalef(1, 1, 1);
#endif
// Restore the depth test
glEnable(GL_DEPTH_TEST);

View file

@ -17,6 +17,7 @@ private:
static const int m_iMaxMessageWidth = 280;
static ItemRenderer *itemRenderer;
vector<GuiMessage> guiMessages[XUSER_MAX_COUNT];
int chatIndex = 0;
Random *random;
Minecraft *minecraft;

View file

@ -241,7 +241,7 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float
if (riding)
{
if(uiBitmaskOverrideAnim&(1<<eAnim_SmallModel) == 0)
if ((uiBitmaskOverrideAnim&(1<<eAnim_SmallModel)) == 0)
{
arm0->xRot += -HALF_PI * 0.4f;
arm1->xRot += -HALF_PI * 0.4f;

View file

@ -286,6 +286,20 @@ void ItemInHandRenderer::renderItem(shared_ptr<LivingEntity> mob, shared_ptr<Ite
float xo = 0.0f;
float yo = 0.3f;
// Re position height of held item if skin is small
if (mob->getAnimOverrideBitmask() & (1 << HumanoidModel::eAnim_SmallModel))
{
if (mob->isRiding())
{
std::shared_ptr<Entity> ridingEntity = mob->riding;
if (ridingEntity != nullptr) // Safety check;
{
yo += 0.3f; // reverts the change in Boat.cpp for smaller models.
}
}
}
glEnable(GL_RESCALE_NORMAL);
glTranslatef(-xo, -yo, 0);

View file

@ -1537,8 +1537,12 @@ void Minecraft::run_middle()
// Utility keys always work regardless of KBM active state
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_PAUSE) && !ui.GetMenuDisplayed(i))
{
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_PAUSEMENU;
app.DebugPrintf("PAUSE PRESSED (keyboard) - ipad = %d\n",i);
if (dynamic_cast<ChatScreen*>(getScreen()) != nullptr) {
setScreen(nullptr);
} else {
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_PAUSEMENU;
app.DebugPrintf("PAUSE PRESSED (keyboard) - ipad = %d\n",i);
}
}
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_THIRD_PERSON))

View file

@ -1795,7 +1795,6 @@ void MinecraftServer::run(int64_t seed, void *lpParameter)
chunkPacketManagement_PostTick();
}
lastTime = getCurrentTimeMillis();
// int64_t afterall = System::currentTimeMillis();
// PIXReportCounter(L"Server time all",(float)(afterall-beforeall));
// PIXReportCounter(L"Server ticks",(float)tickcount);

View file

@ -199,11 +199,26 @@ void PlayerRenderer::render(shared_ptr<Entity> _mob, double x, double y, double
armorParts1->sneaking = armorParts2->sneaking = humanoidModel->sneaking = mob->isSneaking();
double yp = y - mob->heightOffset;
if (mob->isSneaking() && !mob->instanceof(eTYPE_LOCALPLAYER))
if (mob->isSneaking())
{
yp -= 2 / 16.0f;
}
if (mob->getAnimOverrideBitmask() & (1 << HumanoidModel::eAnim_SmallModel))
{
if (mob->isRiding())
{
std::shared_ptr<Entity> ridingEntity = mob->riding;
if (ridingEntity != nullptr) // Safety check;
{
if (ridingEntity->instanceof(eTYPE_BOAT))
{
yp += 0.25f; // reverts the change in Boat.cpp for smaller models.
}
}
}
}
// Check if an idle animation is needed
if(mob->getAnimOverrideBitmask()&(1<<HumanoidModel::eAnim_HasIdle))
{

View file

@ -161,7 +161,7 @@ void Screen::updateEvents()
static bool s_arrowFirstRepeat[2] = { false, false };
const DWORD ARROW_REPEAT_DELAY_MS = 250;
const DWORD ARROW_REPEAT_INTERVAL_MS = 50;
DWORD now = GetTickCount();
DWORD now = GetTickCount64();
// Poll keyboard events (special keys that may not come through WM_CHAR, e.g. Escape, arrows)
for (int vk = 0; vk < 256; vk++)

View file

@ -147,12 +147,12 @@ void ServerPlayer::flagEntitiesToBeRemoved(unsigned int *flags, bool *removedFou
{
*removedFound = true;
// before this left 192 bytes uninitialized!!!!!
memset(flags, 0, (2048 / 32) * sizeof(unsigned int));
memset(flags, 0, (16384 / 32) * sizeof(unsigned int));
}
for(int index : entitiesToRemove)
{
if( index < 2048 )
if( index < 16384 )
{
unsigned int i = index / 32;
unsigned int j = index % 32;

View file

@ -32,20 +32,30 @@ int SheepRenderer::prepareArmor(shared_ptr<LivingEntity> _sheep, int layer, floa
int c2 = (value + 1) % Sheep::COLOR_LENGTH;
float subStep = ((sheep->tickCount % colorDuration) + a) / static_cast<float>(colorDuration);
glColor3f(Sheep::COLOR[c1][0] * (1.0f - subStep) + Sheep::COLOR[c2][0] * subStep, Sheep::COLOR[c1][1] * (1.0f - subStep) + Sheep::COLOR[c2][1] * subStep, Sheep::COLOR[c1][2]
* (1.0f - subStep) + Sheep::COLOR[c2][2] * subStep);
glColor3f(
Sheep::COLOR[c1][0] * (1.0f - subStep) + Sheep::COLOR[c2][0] * subStep,
Sheep::COLOR[c1][1] * (1.0f - subStep) + Sheep::COLOR[c2][1] * subStep,
Sheep::COLOR[c1][2] * (1.0f - subStep) + Sheep::COLOR[c2][2] * subStep);
}
else
{
int color = sheep->getColor();
glColor3f(Sheep::COLOR[color][0], Sheep::COLOR[color][1], Sheep::COLOR[color][2]);
float brightness = SharedConstants::TEXTURE_LIGHTING ? 1.0f : sheep->getBrightness(a);
int color = sheep->getColor();
glColor3f(brightness * Sheep::COLOR[color][0], brightness * Sheep::COLOR[color][1], brightness * Sheep::COLOR[color][2]);
}
// 4J - change brought forward from 1.8.2
float brightness = SharedConstants::TEXTURE_LIGHTING ? 1.0f : sheep->getBrightness(a);
int color = sheep->getColor();
glColor3f(brightness * Sheep::COLOR[color][0], brightness * Sheep::COLOR[color][1], brightness * Sheep::COLOR[color][2]);
/* Fix; this code originally completely overrided the _jeb and normal textures so i just commented it out and updated the part that should have worked.
float brightness = SharedConstants::TEXTURE_LIGHTING ? 1.0f : sheep->getBrightness(a);
int color = sheep->getColor();
glColor3f(brightness * Sheep::COLOR[color][0], brightness * Sheep::COLOR[color][1], brightness * Sheep::COLOR[color][2]); */
return 1;
}
return -1;

View file

@ -57,6 +57,13 @@ extern Renderer InternalRenderManager;
#include "Xbox/Resource.h"
// request use of dedicated GPU from AMD and Nvidia drivers
extern "C"
{
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
}
#ifdef _MSC_VER
#pragma comment(lib, "legacy_stdio_definitions.lib")
#endif
@ -472,6 +479,8 @@ IDXGISwapChain* g_pSwapChain = nullptr;
ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
ID3D11DepthStencilView* g_pDepthStencilView = nullptr;
ID3D11Texture2D* g_pDepthStencilBuffer = nullptr;
static const float kClearColorWhite[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
static const float kClearColorBlack[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
@ -663,7 +672,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}
@ -675,23 +684,23 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.cbSize = sizeof(WNDCLASSEXW);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, "Minecraft");
wcex.hIcon = LoadIconW(hInstance, L"Minecraft");
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = "Minecraft";
wcex.lpszClassName = "MinecraftClass";
wcex.lpszMenuName = L"Minecraft";
wcex.lpszClassName = L"MinecraftClass";
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_MINECRAFTWINDOWS));
return RegisterClassEx(&wcex);
return RegisterClassExW(&wcex);
}
//
@ -711,8 +720,8 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
RECT wr = {0, 0, g_rScreenWidth, g_rScreenHeight}; // set the size, but not the position
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size
g_hWnd = CreateWindow( "MinecraftClass",
"Minecraft",
g_hWnd = CreateWindowW( L"MinecraftClass",
L"Minecraft",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
0,
@ -1564,7 +1573,14 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
continue;
}
const float* clearColor = app.GetGameStarted() ? kClearColorBlack : kClearColorWhite;
RenderManager.SetClearColour(clearColor);
RenderManager.StartFrame();
if (!app.GetGameStarted())
{
RenderManager.SetClearColour(kClearColorWhite); // set intro scene background to white
RenderManager.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
#if 0
if(pMinecraft->soundEngine->isStreamingWavebankReady() &&
!pMinecraft->soundEngine->isPlayingStreamingGameMusic() &&

View file

@ -20,6 +20,10 @@ void WitherBossRenderer::render(shared_ptr<Entity> entity, double x, double y, d
shared_ptr<WitherBoss> mob = dynamic_pointer_cast<WitherBoss>(entity);
BossMobGuiInfo::setBossHealth(mob, true);
if (!mob->getCustomName().empty())
{
BossMobGuiInfo::name = mob->getCustomName();
}
int modelVersion = dynamic_cast<WitherBossModel*>(model)->modelVersion();
if (modelVersion != this->modelVersion)

View file

@ -28,6 +28,7 @@
#include "../../Minecraft.World/TilePos.h"
#include "../../Minecraft.World/compression.h"
#include "../../Minecraft.World/OldChunkStorage.h"
#include "../../Minecraft.World/ConsoleSaveFileOriginal.h"
#include "../../Minecraft.World/net.minecraft.world.level.tile.h"
#include "../../Minecraft.World/Random.h"
@ -325,6 +326,7 @@ static void TickCoreSystems()
g_NetworkManager.DoWork();
ProfileManager.Tick();
StorageManager.Tick();
ConsoleSaveFileOriginal::flushPendingBackgroundSave();
}
/**
@ -655,7 +657,7 @@ int main(int argc, char **argv)
break;
}
if (autosaveRequested && app.GetXuiServerAction(kServerActionPad) == eXuiServerAction_Idle)
if (autosaveRequested && app.GetXuiServerAction(kServerActionPad) == eXuiServerAction_Idle && !ConsoleSaveFileOriginal::hasPendingBackgroundSave())
{
LogWorldIO("autosave completed");
autosaveRequested = false;
@ -669,7 +671,7 @@ int main(int argc, char **argv)
DWORD now = GetTickCount();
if ((LONG)(now - nextAutosaveTick) >= 0)
{
if (app.GetXuiServerAction(kServerActionPad) == eXuiServerAction_Idle)
if (app.GetXuiServerAction(kServerActionPad) == eXuiServerAction_Idle && !ConsoleSaveFileOriginal::hasPendingBackgroundSave())
{
LogWorldIO("requesting autosave");
app.SetXuiServerAction(kServerActionPad, eXuiServerAction_AutoSaveGame);
@ -685,25 +687,38 @@ int main(int argc, char **argv)
LogInfof("shutdown", "Dedicated server stopped");
MinecraftServer *server = MinecraftServer::getInstance();
if (server != NULL)
{
server->setSaveOnExit(true);
}
if (server != NULL)
if (server != NULL && !ConsoleSaveFileOriginal::hasPendingBackgroundSave())
{
server->setSaveOnExit(true);
LogWorldIO("requesting save before shutdown");
LogWorldIO("using saveOnExit for shutdown");
}
if (ConsoleSaveFileOriginal::hasPendingBackgroundSave())
{
LogWorldIO("Waiting for autosave to complete...");
}
MinecraftServer::HaltServer();
if (g_NetworkManager.ServerStoppedValid())
{
C4JThread waitThread(&WaitForServerStoppedThreadProc, NULL, "WaitServerStopped");
waitThread.Run();
while (waitThread.isRunning())
{
TickCoreSystems();
Sleep(10);
}
waitThread.WaitForCompletion(INFINITE);
}
while (ConsoleSaveFileOriginal::hasPendingBackgroundSave())
{
TickCoreSystems();
Sleep(10);
}
LogInfof("shutdown", "Cleaning up and exiting.");
WinsockNetLayer::Shutdown();
LogDebugf("shutdown", "Network layer shutdown complete.");

View file

@ -494,6 +494,9 @@ set(_MINECRAFT_SERVER_COMMON_ROOT
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/iob_shim.asm"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/stdafx.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/stubs.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/Entity.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/ConsoleSaveFileOriginal.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/ConsoleSaveFileOriginal.h"
"${CMAKE_CURRENT_SOURCE_DIR}/../include/lce_filesystem/lce_filesystem.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Console/ServerCliInput.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Console/ServerCliInput.h"

View file

@ -87,7 +87,7 @@ Boat::Boat(Level *level, double x, double y, double z) : Entity( level )
double Boat::getRideHeight()
{
return heightOffset;
return heightOffset - 0.4f;
}
bool Boat::hurt(DamageSource *source, float hurtDamage)

View file

@ -12,6 +12,26 @@
#include "../Minecraft.Client/Common/GameRules/LevelGenerationOptions.h"
#include "../Minecraft.World/net.minecraft.world.level.chunk.storage.h"
#ifdef MINECRAFT_SERVER_BUILD
#include <thread>
#include <atomic>
#include <mutex>
static std::atomic<bool> s_bgSaveActive{false};
static std::mutex s_bgSaveMutex;
struct BackgroundSaveResult
{
ConsoleSaveFile *owner = nullptr;
PBYTE thumbData = nullptr;
DWORD thumbSize = 0;
BYTE textMeta[88] = {};
int textMetaBytes = 0;
bool pending = false;
};
static BackgroundSaveResult s_bgResult;
#endif
#ifdef _XBOX
#define RESERVE_ALLOCATION MEM_RESERVE | MEM_LARGE_PAGES
@ -673,6 +693,83 @@ void ConsoleSaveFileOriginal::Flush(bool autosave, bool updateThumbnail )
unsigned int fileSize = header.GetFileSize();
#ifdef MINECRAFT_SERVER_BUILD
// on the server we dont want to block the tick thread doing compression!!!
// sna[pshot pvSaveMem while we still hold the lock then hand it off to a background thread
byte *snap = new (std::nothrow) byte[fileSize];
if (snap)
{
// copy the save buffer while we still own the lock so nothing can write to it mid-copy
QueryPerformanceCounter(&qwTime);
memcpy(snap, pvSaveMem, fileSize);
QueryPerformanceCounter(&qwNewTime);
app.DebugPrintf("snapshot %u bytes in %.3f sec\n", fileSize,
(qwNewTime.QuadPart - qwTime.QuadPart) * fSecsPerTick);
PBYTE thumb = nullptr;
DWORD thumbSz = 0;
app.GetSaveThumbnail(&thumb, &thumbSz);
BYTE meta[88];
ZeroMemory(meta, 88);
int64_t seed = 0;
bool hasSeed = false;
if (MinecraftServer *sv = MinecraftServer::getInstance(); sv && sv->levels[0])
{
seed = sv->levels[0]->getLevelData()->getSeed();
hasSeed = true;
}
int metaLen = app.CreateImageTextData(meta, seed, hasSeed,
app.GetGameHostOption(eGameHostOption_All), Minecraft::GetInstance()->getCurrentTexturePackId());
// telemetry
INT uid = 0;
StorageManager.GetSaveUniqueNumber(&uid);
TelemetryManager->RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), uid, fileSize);
ReleaseSaveAccess();
s_bgSaveActive.store(true, std::memory_order_release);
std::thread([snap, fileSize, thumb, thumbSz, meta, metaLen, this]() {
unsigned int compLen = fileSize + 8;
byte *buf = static_cast<byte *>(StorageManager.AllocateSaveData(compLen));
if (!buf)
{
// FAIL!! attempt precalc
compLen = 0;
Compression::getCompression()->Compress(nullptr, &compLen, snap, fileSize);
compLen += 8;
buf = static_cast<byte *>(StorageManager.AllocateSaveData(compLen));
}
if (buf)
{
// COM,PRESS
Compression::getCompression()->Compress(buf + 8, &compLen, snap, fileSize);
ZeroMemory(buf, 8);
memcpy(buf + 4, &fileSize, sizeof(fileSize));
// store the result so flushPendingBackgroundSave() can pick it up on the main thread next tick
// StorageManager isnt thread safe so we cant call SetSaveImages or SaveSaveData from here. Bwoomp
std::lock_guard<std::mutex> lk(s_bgSaveMutex);
s_bgResult.owner = this;
s_bgResult.thumbData = thumb;
s_bgResult.thumbSize = thumbSz;
memcpy(s_bgResult.textMeta, meta, sizeof(meta));
s_bgResult.textMetaBytes = metaLen;
s_bgResult.pending = true;
}
else
{
app.DebugPrintf("save buf alloc failed\n");
s_bgSaveActive.store(false, std::memory_order_release);
}
delete[] snap;
}).detach();
return;
}
app.DebugPrintf("snapshot alloc failed (%u bytes)\n", fileSize);
#endif
// Assume that the compression will make it smaller so initially attempt to allocate the current file size
// We add 4 bytes to the start so that we can signal compressed data
// And another 4 bytes to store the decompressed data size
@ -838,6 +935,10 @@ int ConsoleSaveFileOriginal::SaveSaveDataCallback(LPVOID lpParam,bool bRes)
{
ConsoleSaveFile *pClass=static_cast<ConsoleSaveFile *>(lpParam);
#ifdef MINECRAFT_SERVER_BUILD
s_bgSaveActive.store(false, std::memory_order_release);
#endif
return 0;
}
@ -1085,3 +1186,25 @@ void *ConsoleSaveFileOriginal::getWritePointer(FileEntry *file)
{
return static_cast<char *>(pvSaveMem) + file->currentFilePointer;;
}
#ifdef MINECRAFT_SERVER_BUILD
void ConsoleSaveFileOriginal::flushPendingBackgroundSave()
{
std::lock_guard<std::mutex> lk(s_bgSaveMutex);
if (!s_bgResult.pending)
return;
StorageManager.SetSaveImages(
s_bgResult.thumbData, s_bgResult.thumbSize,
nullptr, 0, s_bgResult.textMeta, s_bgResult.textMetaBytes);
StorageManager.SaveSaveData(&ConsoleSaveFileOriginal::SaveSaveDataCallback, s_bgResult.owner);
s_bgResult.pending = false;
// the actual write isnt done until SaveSaveDataCallback fires
}
bool ConsoleSaveFileOriginal::hasPendingBackgroundSave()
{
return s_bgSaveActive.load(std::memory_order_acquire);
}
#endif

View file

@ -77,6 +77,11 @@ public:
virtual void LockSaveAccess();
virtual void ReleaseSaveAccess();
#ifdef MINECRAFT_SERVER_BUILD
static void flushPendingBackgroundSave();
static bool hasPendingBackgroundSave();
#endif
virtual ESavePlatform getSavePlatform();
virtual bool isSaveEndianDifferent();
virtual void setLocalPlatform();

View file

@ -183,7 +183,7 @@ public:
double getHeadPartYRotDiff(int partIndex, doubleArray bodyPos, doubleArray partPos);
Vec3 *getHeadLookVector(float a);
virtual wstring getAName() { return app.GetString(IDS_ENDERDRAGON); };
virtual wstring getAName() { if (hasCustomName()) return getCustomName(); return app.GetString(IDS_ENDERDRAGON); };
virtual float getHealth() { return LivingEntity::getHealth(); };
virtual float getMaxHealth() { return LivingEntity::getMaxHealth(); };
};

View file

@ -27,13 +27,17 @@
const wstring Entity::RIDING_TAG = L"Riding";
int Entity::entityCounter = 2048; // 4J - changed initialiser to 2048, as we are using range 0 - 2047 as special unique smaller ids for things that need network tracked
//int Entity::entityCounter = 2048; // 4J - changed initialiser to 2048, as we are using range 0 - 2047 as special unique smaller ids for things that need network tracked
int Entity::entityCounter = 16384; //now using full range of 0 - 16383, limit is 32k but we shouldnt need that yet
DWORD Entity::tlsIdx = TlsAlloc();
// 4J - added getSmallId & freeSmallId methods
unsigned int Entity::entityIdUsedFlags[2048/32] = {0};
unsigned int Entity::entityIdWanderFlags[2048/32] = {0};
unsigned int Entity::entityIdRemovingFlags[2048/32] = {0};
//unsigned int Entity::entityIdUsedFlags[2048/32] = {0};
//unsigned int Entity::entityIdWanderFlags[2048/32] = {0};
//unsigned int Entity::entityIdRemovingFlags[2048/32] = {0};
unsigned int Entity::entityIdUsedFlags[16384/32] = {0};
unsigned int Entity::entityIdWanderFlags[16384/32] = {0};
unsigned int Entity::entityIdRemovingFlags[16384/32] = {0};
int Entity::extraWanderIds[EXTRA_WANDER_MAX] = {0};
int Entity::extraWanderTicks = 0;
int Entity::extraWanderCount = 0;
@ -65,7 +69,7 @@ int Entity::getSmallId()
}
}
for( int i = 0; i < (2048 / 32 ); i++ )
for( int i = 0; i < (16384 / 32 ); i++ )
{
unsigned int uiFlags = *puiUsedFlags;
if( uiFlags != 0xffffffff )
@ -102,7 +106,7 @@ int Entity::getSmallId()
if (entityCounter == 0x7ffffff)
{
entityCounter = 2048;
entityCounter = 16384;
}
return fallbackId;
#else
@ -116,7 +120,7 @@ void Entity::countFlagsForPIX()
{
int freecount = 0;
unsigned int *puiUsedFlags = entityIdUsedFlags;
for( int i = 0; i < (2048 / 32 ); i++ )
for( int i = 0; i < (16384 / 32 ); i++ )
{
unsigned int uiFlags = *puiUsedFlags;
if( uiFlags != 0xffffffff )
@ -134,7 +138,7 @@ void Entity::countFlagsForPIX()
puiUsedFlags++;
}
PIXAddNamedCounter(freecount,"Small Ids free");
PIXAddNamedCounter(2048 - freecount,"Small Ids used");
PIXAddNamedCounter(16384 - freecount,"Small Ids used");
}
void Entity::resetSmallId()
@ -149,7 +153,7 @@ void Entity::resetSmallId()
void Entity::freeSmallId(int index)
{
if( ( (size_t)TlsGetValue(tlsIdx) ) == 0 ) return; // Don't do anything with small ids if this isn't the server thread
if( index >= 2048 ) return; // Don't do anything if this isn't a short id
if( index >= 16384 ) return; // Don't do anything if this isn't a short id
unsigned int i = index / 32;
unsigned int j = index % 32;
@ -172,7 +176,7 @@ void Entity::useSmallIds()
void Entity::considerForExtraWandering(bool enable)
{
if( ( (size_t)TlsGetValue(tlsIdx) ) == 0 ) return; // Don't do anything with small ids if this isn't the server thread
if( entityId >= 2048 ) return; // Don't do anything if this isn't a short id
if( entityId >= 16384 ) return; // Don't do anything if this isn't a short id
unsigned int i = entityId / 32;
unsigned int j = entityId % 32;
@ -192,7 +196,7 @@ void Entity::considerForExtraWandering(bool enable)
bool Entity::isExtraWanderingEnabled()
{
if( ( (size_t)TlsGetValue(tlsIdx) ) == 0 ) return false; // Don't do anything with small ids if this isn't the server thread
if( entityId >= 2048 ) return false; // Don't do anything if this isn't a short id
if( entityId >= 16384 ) return false; // Don't do anything if this isn't a short id
for( int i = 0; i < extraWanderCount; i++ )
{
@ -224,12 +228,12 @@ void Entity::tickExtraWandering()
int entityId = 0;
if( extraWanderCount )
{
entityId = ( extraWanderIds[ extraWanderCount - 1 ] + 1 ) % 2048;
entityId = ( extraWanderIds[ extraWanderCount - 1 ] + 1 ) % 16384;
}
extraWanderCount = 0;
for( int k = 0; ( k < 2048 ) && ( extraWanderCount < EXTRA_WANDER_MAX); k++ )
for( int k = 0; ( k < 16384 ) && ( extraWanderCount < EXTRA_WANDER_MAX); k++ )
{
unsigned int i = entityId / 32;
unsigned int j = entityId % 32;
@ -241,7 +245,7 @@ void Entity::tickExtraWandering()
// printf("%d, ", entityId);
}
entityId = ( entityId + 1 ) % 2048;
entityId = ( entityId + 1 ) % 16384;
}
// printf("\n");
}
@ -261,7 +265,7 @@ void Entity::_init(bool useSmallId, Level *level)
else
{
entityId = Entity::entityCounter++;
if(entityCounter == 0x7ffffff ) entityCounter = 2048;
if(entityCounter == 0x7ffffff ) entityCounter = 16384;
}
viewScale = 1.0;

View file

@ -382,9 +382,12 @@ private:
int getSmallId();
void freeSmallId(int index);
static unsigned int entityIdUsedFlags[2048/32];
static unsigned int entityIdWanderFlags[2048/32];
static unsigned int entityIdRemovingFlags[2048/32];
//static unsigned int entityIdUsedFlags[2048/32];
//static unsigned int entityIdWanderFlags[2048/32];
//static unsigned int entityIdRemovingFlags[2048/32];
static unsigned int entityIdUsedFlags[16384/32];
static unsigned int entityIdWanderFlags[16384/32];
static unsigned int entityIdRemovingFlags[16384/32];
static int extraWanderIds[EXTRA_WANDER_MAX];
static int extraWanderCount;
static int extraWanderTicks;

View file

@ -35,7 +35,7 @@ void MoveEntityPacket::read(DataInputStream *dis) //throws IOException
void MoveEntityPacket::write(DataOutputStream *dos) //throws IOException
{
if( (id < 0 ) || (id >= 2048 ) )
if( (id < 0 ) || (id >= 16384 ) )
{
// We shouln't be tracking an entity that doesn't have a short type of id
__debugbreak();

View file

@ -19,7 +19,7 @@ MoveEntityPacketSmall::MoveEntityPacketSmall()
MoveEntityPacketSmall::MoveEntityPacketSmall(int id)
{
if( (id < 0 ) || (id >= 2048 ) )
if( (id < 0 ) || (id >= 16384 ) )
{
// We shouln't be tracking an entity that doesn't have a short type of id
__debugbreak();
@ -42,7 +42,7 @@ void MoveEntityPacketSmall::read(DataInputStream *dis) //throws IOException
void MoveEntityPacketSmall::write(DataOutputStream *dos) //throws IOException
{
if( (id < 0 ) || (id >= 2048 ) )
if( (id < 0 ) || (id >= 16384 ) )
{
// We shouln't be tracking an entity that doesn't have a short type of id
__debugbreak();
@ -99,7 +99,7 @@ void MoveEntityPacketSmall::PosRot::read(DataInputStream *dis) //throws IOExcept
void MoveEntityPacketSmall::PosRot::write(DataOutputStream *dos) //throws IOException
{
if( (id < 0 ) || (id >= 2048 ) )
if( (id < 0 ) || (id >= 16384 ) )
{
// We shouln't be tracking an entity that doesn't have a short type of id
__debugbreak();
@ -138,7 +138,7 @@ void MoveEntityPacketSmall::Pos::read(DataInputStream *dis) //throws IOException
void MoveEntityPacketSmall::Pos::write(DataOutputStream *dos) //throws IOException
{
if( (id < 0 ) || (id >= 2048 ) )
if( (id < 0 ) || (id >= 16384 ) )
{
// We shouln't be tracking an entity that doesn't have a short type of id
__debugbreak();
@ -176,7 +176,7 @@ void MoveEntityPacketSmall::Rot::read(DataInputStream *dis) //throws IOException
void MoveEntityPacketSmall::Rot::write(DataOutputStream *dos) //throws IOException
{
if( (id < 0 ) || (id >= 2048 ) )
if( (id < 0 ) || (id >= 16384 ) )
{
// We shouln't be tracking an entity that doesn't have a short type of id
__debugbreak();

View file

@ -67,21 +67,8 @@ bool PortalTile::isCubeShaped()
return false;
}
bool PortalTile::trySpawnPortal(Level *level, int x, int y, int z, bool actuallySpawn)
bool PortalTile::validPortalFrame(Level* level, int x, int y, int z, int xd, int zd, bool actuallySpawn)
{
int xd = 0;
int zd = 0;
if (level->getTile(x - 1, y, z) == Tile::obsidian_Id || level->getTile(x + 1, y, z) == Tile::obsidian_Id) xd = 1;
if (level->getTile(x, y, z - 1) == Tile::obsidian_Id || level->getTile(x, y, z + 1) == Tile::obsidian_Id) zd = 1;
if (xd == zd) return false;
if (level->getTile(x - xd, y, z - zd) == 0)
{
x -= xd;
z -= zd;
}
for (int xx = -1; xx <= 2; xx++)
{
for (int yy = -1; yy <= 3; yy++)
@ -101,9 +88,7 @@ bool PortalTile::trySpawnPortal(Level *level, int x, int y, int z, bool actually
}
}
}
if( !actuallySpawn )
return true;
if (!actuallySpawn) return true;
for (int xx = 0; xx < 2; xx++)
{
@ -112,9 +97,52 @@ bool PortalTile::trySpawnPortal(Level *level, int x, int y, int z, bool actually
level->setTileAndData(x + xd * xx, y + yy, z + zd * xx, Tile::portalTile_Id, 0, Tile::UPDATE_CLIENTS);
}
}
return true;
}
bool PortalTile::trySpawnPortal(Level *level, int x, int y, int z, bool actuallySpawn)
{
int xd = 0;
int zd = 0;
if (level->getTile(x - 1, y, z) == Tile::obsidian_Id || level->getTile(x + 1, y, z) == Tile::obsidian_Id) xd = 1;
if (level->getTile(x, y, z - 1) == Tile::obsidian_Id || level->getTile(x, y, z + 1) == Tile::obsidian_Id) zd = 1;
bool twoPosible = false; // two neth portals posible (x and z direction)
if (xd == zd)
{
if (xd == 1) twoPosible = true;
else return false;
}
bool changedx = false; // changed x so it can be reverted if two portals are posible
if (level->getTile(x - xd, y, z) == 0)
{
changedx = true;
x--;
}
else if (level->getTile(x, y, z - zd) == 0 && !twoPosible)
{
z--;
}
if (!twoPosible)
{
if (!validPortalFrame(level, x, y, z, xd, zd, actuallySpawn)) return false;
}
else
{
if (!validPortalFrame(level, x, y, z, xd, 0, actuallySpawn))
{
if (changedx) x++; // revert x (this check wants to check z not x and z)
if (level->getTile(x, y, z - zd) == 0) z--;
if (!validPortalFrame(level, x, y, z, 0, zd, actuallySpawn))
return false;
}
}
return true;
}
void PortalTile::neighborChanged(Level *level, int x, int y, int z, int type)

View file

@ -13,6 +13,7 @@ public:
virtual void updateShape(LevelSource *level, int x, int y, int z, int forceData = -1, shared_ptr<TileEntity> forceEntity = shared_ptr<TileEntity>()); // 4J added forceData, forceEntity param
virtual bool isSolidRender(bool isServerLevel = false);
virtual bool isCubeShaped();
virtual bool validPortalFrame(Level* level, int x, int y, int z, int xd, int zd, bool actuallySpawn);
virtual bool trySpawnPortal(Level *level, int x, int y, int z, bool actuallySpawn);
virtual void neighborChanged(Level *level, int x, int y, int z, int type);
virtual bool shouldRenderFace(LevelSource *level, int x, int y, int z, int face);

View file

@ -105,5 +105,5 @@ public:
// 4J Stu - These are required for the BossMob interface
virtual float getMaxHealth() { return Monster::getMaxHealth(); };
virtual float getHealth() { return Monster::getHealth(); };
virtual wstring getAName() { return app.GetString(IDS_WITHER); };
virtual wstring getAName() { if (hasCustomName()) return getCustomName(); return app.GetString(IDS_WITHER); };
};

View file

@ -1,7 +1,15 @@
![Legacy Edition Banner](.github/banner.png)
# MinecraftConsoles (Legacy Console Edition)
[![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/jrum7HhegA)
[![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/dH8AZWGcau)
---
## IMPORTANT UPDATE
**This repo was moved to a new org!**
Please change all links and references from `smartcmd/MinecraftConsoles` to `MCLCE/MinecraftConsoles` instead.
---
This project is based on source code of Minecraft Legacy Console Edition v1.6.0560.0 (TU19) with some fixes and improvements applied.
@ -9,11 +17,11 @@ The current goal of MinecraftConsoles is to be a multi-platform base for further
See our our [Contributor's Guide](./CONTRIBUTING.md) for more information on the goals of this project.
## Download
## Download
### Client
Windows users can download our [Nightly Build](https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly)! Simply download the `.zip` file and extract it to a folder where you'd like to keep the game. You can set your username in `username.txt` (you'll have to make this file)
Windows users can download our [Nightly Build](https://github.com/MCLCE/MinecraftConsoles/releases/tag/nightly)! Simply download the `.zip` file and extract it to a folder where you'd like to keep the game. You can set your username in `username.txt` (you'll have to make this file)
### Server
If you're looking for Dedicated Server software, download its [Nightly Build here](https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly-dedicated-server). Similar instructions to the client more or less, though see further down in this README for more info on that.
If you're looking for Dedicated Server software, download its [Nightly Build here](https://github.com/MCLCE/MinecraftConsoles/releases/tag/nightly-dedicated-server). Similar instructions to the client more or less, though see further down in this README for more info on that.
## Platform Support
@ -220,4 +228,4 @@ For more information, see [COMPILE.md](COMPILE.md).
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=smartcmd/MinecraftConsoles&type=date&legend=top-left)](https://www.star-history.com/?spm=a2c6h.12873639.article-detail.7.7b9d7fabjNxTRk#smartcmd/MinecraftConsoles&type=date&legend=top-left)
[![Star History Chart](https://api.star-history.com/svg?repos=MCLCE/MinecraftConsoles&type=date&legend=top-left)](https://www.star-history.com/?spm=a2c6h.12873639.article-detail.7.7b9d7fabjNxTRk#MCLCE/MinecraftConsoles&type=date&legend=top-left)

View file

@ -1,12 +1,12 @@
services:
minecraft-lce-dedicated-server:
image: ghcr.io/kuwacom/minecraft-lce-dedicated-server:nightly
image: ghcr.io/smartcmd/minecraft-lce-dedicated-server:nightly
container_name: minecraft-lce-dedicated-server
restart: unless-stopped
tty: true
stdin_open: true
environment:
TZ: ${TZ:-Asia/Tokyo}
TZ: ${TZ:-Etc/UTC}
WINEARCH: win64
WINEPREFIX: /var/opt/wineprefix64
WINEDEBUG: -all
@ -15,12 +15,15 @@ services:
# minimum required virtual screen
XVFB_DISPLAY: ${XVFB_DISPLAY:-:99}
XVFB_SCREEN: ${XVFB_SCREEN:-720x1280x16}
# ip & port the server will run on
SERVER_BIND_IP: ${SERVER_BIND_IP:-0.0.0.0}
SERVER_PORT: ${SERVER_PORT:-25565}
volumes:
# - wineprefix64:/var/opt/wineprefix64
- ./server-data:/srv/persist
ports:
- "25565:25565/tcp"
- "25565:25565/udp"
- "$SERVER_PORT:$SERVER_PORT/tcp"
- "$SERVER_PORT:$SERVER_PORT/udp"
stop_grace_period: 30s
# volumes:

View file

@ -10,7 +10,7 @@ services:
tty: true
stdin_open: true
environment:
TZ: ${TZ:-Asia/Tokyo}
TZ: ${TZ:-Etc/UTC}
WINEARCH: win64
WINEPREFIX: /var/opt/wineprefix64
WINEDEBUG: -all
@ -18,13 +18,16 @@ services:
SERVER_CLI_INPUT_MODE: ${SERVER_CLI_INPUT_MODE:-stream}
# minimum required virtual screen
XVFB_DISPLAY: ${XVFB_DISPLAY:-:99}
XVFB_SCREEN: ${XVFB_SCREEN:-64x64x16}
XVFB_SCREEN: ${XVFB_SCREEN:-720x1280x16}
# ip & port the server will run on
SERVER_BIND_IP: ${SERVER_BIND_IP:-0.0.0.0}
SERVER_PORT: ${SERVER_PORT:-25565}
volumes:
# - wineprefix64:/var/opt/wineprefix64
- ./server-data:/srv/persist
ports:
- "25565:25565/tcp"
- "25565:25565/udp"
- "$SERVER_PORT:$SERVER_PORT/tcp"
- "$SERVER_PORT:$SERVER_PORT/udp"
stop_grace_period: 30s
# volumes:

View file

@ -3,9 +3,8 @@ set -euo pipefail
SERVER_DIR="/srv/mc"
SERVER_EXE="Minecraft.Server.exe"
# ip & port are fixed since they run inside the container
SERVER_PORT="25565"
SERVER_BIND_IP="0.0.0.0"
SERVER_PORT="${SERVER_PORT:-25565}"
SERVER_BIND_IP="${SERVER_BIND_IP:-0.0.0.0}"
PERSIST_DIR="/srv/persist"
WINE_CMD=""