TU43 Structures, bug fixes & minor changes

- Elytra flight, damage, kinetic energy, pretty much any bug someone reported, paper doll, etc.
- Fossil & Igloo generation
- Texture interpolation
- Iggy mouse fix for world settings
- Neo branding on main screen
- Release build txt logger
- Debug mode spectator
- Several server fixes
- Flowerpot fixes
- Several more changes made in TU43
This commit is contained in:
Tranqlmao
2026-07-11 19:30:16 -04:00
parent d236146e92
commit a4c746bee4
89 changed files with 1793 additions and 590 deletions
+21
View File
@@ -0,0 +1,21 @@
{
"configurations": [
{
"inheritEnvironments": [
"msvc_x64"
],
"name": "x64-Debug",
"includePath": [
"${env.INCLUDE}",
"${workspaceRoot}\\**"
],
"defines": [
"WIN32",
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"intelliSenseMode": "windows-msvc-x64"
}
]
}
+7
View File
@@ -70,6 +70,11 @@ set_source_files_properties(compat_shims.cpp PROPERTIES SKIP_PRECOMPILE_HEADERS
configure_compiler_target(Minecraft.Client)
if(PLATFORM_NAME STREQUAL "Windows64")
target_compile_options(Minecraft.Client PRIVATE $<$<CONFIG:Release>:/Zi>)
target_link_options(Minecraft.Client PRIVATE $<$<CONFIG:Release>:/DEBUG /OPT:REF /OPT:ICF>)
endif()
set(MINECRAFT_CLIENT_USE_4J_DEBUG_LIBS TRUE)
if(CMAKE_CROSSCOMPILING AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(MINECRAFT_CLIENT_USE_4J_DEBUG_LIBS FALSE)
@@ -88,6 +93,7 @@ if(MINECRAFT_CLIENT_USE_4J_DEBUG_LIBS)
d3dcompiler
XInput9_1_0
wsock32
dbghelp
legacy_stdio_definitions
4JLibs.${PLATFORM_NAME}.Input
4JLibs.${PLATFORM_NAME}.Profile
@@ -102,6 +108,7 @@ else()
d3dcompiler
XInput9_1_0
wsock32
dbghelp
legacy_stdio_definitions
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/4JLibs/libs/4J_Input.lib"
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/4JLibs/libs/4J_Storage.lib"
+6
View File
@@ -3486,6 +3486,10 @@ void ClientConnection::handleTileEntityData(shared_ptr<TileEntityDataPacket> pac
{
dynamic_pointer_cast<BannerTileEntity>(te)->load(packet->tag);
}
else if (packet->type == TileEntityDataPacket::TYPE_FLOWER_POT && dynamic_pointer_cast<FlowerPotTileEntity>(te) != nullptr)
{
dynamic_pointer_cast<FlowerPotTileEntity>(te)->load(packet->tag);
}
}
}
}
@@ -3834,8 +3838,10 @@ void ClientConnection::handlePlayerAbilities(shared_ptr<PlayerAbilitiesPacket> p
player->abilities.instabuild = playerAbilitiesPacket->canInstabuild();
player->abilities.invulnerable = playerAbilitiesPacket->isInvulnerable();
player->abilities.mayfly = playerAbilitiesPacket->canFly();
player->abilities.spectatorMode = playerAbilitiesPacket->isNoPhysics();
player->abilities.setFlyingSpeed(playerAbilitiesPacket->getFlyingSpeed());
player->abilities.setWalkingSpeed(playerAbilitiesPacket->getWalkingSpeed());
player->noPhysics = playerAbilitiesPacket->isNoPhysics();
}
void ClientConnection::handleSoundEvent(shared_ptr<LevelSoundPacket> packet)
@@ -77,11 +77,28 @@ void UIControl_MinecraftPlayer::render(IggyCustomDrawCallbackRegion *region)
glTranslatef(0, pMinecraft->localplayers[containerMenu->getPad()]->heightOffset, 0);
EntityRenderDispatcher::instance->playerRotY = 180;
auto lp = pMinecraft->localplayers[containerMenu->getPad()];
float owp = lp->walkAnimPos;
float ows = lp->walkAnimSpeed;
float owsO = lp->walkAnimSpeedO;
if (lp->isElytraFlying())
{
lp->walkAnimPos = 0.0f;
lp->walkAnimSpeed = 0.0f;
lp->walkAnimSpeedO = 0.0f;
}
// 4J Stu - Turning on hideGui while we do this stops the name rendering in split-screen
bool wasHidingGui = pMinecraft->options->hideGui;
pMinecraft->options->hideGui = true;
EntityRenderDispatcher::instance->render(pMinecraft->localplayers[containerMenu->getPad()], 0, 0, 0, 0, 1, false, false);
EntityRenderDispatcher::instance->isInventoryRender = true;
EntityRenderDispatcher::instance->render(lp, 0, 0, 0, 0, 1, false, false);
EntityRenderDispatcher::instance->isInventoryRender = false;
pMinecraft->options->hideGui = wasHidingGui;
lp->walkAnimPos = owp;
lp->walkAnimSpeed = ows;
lp->walkAnimSpeedO = owsO;
//pMinecraft->localplayers[m_iPad]->glow = 0;
pMinecraft->localplayers[containerMenu->getPad()]->yBodyRot = oybr;
@@ -80,6 +80,8 @@ UIScene_LaunchMoreOptionsMenu::UIScene_LaunchMoreOptionsMenu(int iPad, void *ini
m_bUpdateCheats = false;
// Update cheat checkboxes
UpdateCheats();
m_bPendingTabSwitch = false;
m_iPendingTabIndex = -1;
m_checkboxes[eLaunchCheckbox_Online].init(app.GetString(IDS_ONLINE_GAME),eLaunchCheckbox_Online,bOnlineGame);
m_checkboxes[eLaunchCheckbox_InviteOnly].init(app.GetString(IDS_INVITE_ONLY),eLaunchCheckbox_InviteOnly,bInviteOnly);
@@ -240,6 +242,14 @@ void UIScene_LaunchMoreOptionsMenu::tick()
UpdateOnline();
m_bUpdateOnline = false;
}
if (m_bPendingTabSwitch)
{
m_bPendingTabSwitch = false;
m_tabIndex = m_iPendingTabIndex;
updateTooltips();
IggyDataValue result;
IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcChangeTab, 0, nullptr);
}
}
void UIScene_LaunchMoreOptionsMenu::handleDestroy()
@@ -339,6 +349,42 @@ void UIScene_LaunchMoreOptionsMenu::handleTouchInput(unsigned int iPad, S32 x, S
}
#endif
#ifdef _WINDOWS64
bool UIScene_LaunchMoreOptionsMenu::handleMouseClick(F32 x, F32 y)
{
if (!hasFocus(m_iPad) || getMovie() == nullptr || g_KBMInput.IsMouseGrabbed() || !g_KBMInput.IsKBMActive())
return false;
if (m_bIgnoreInput)
return false;
float sceneMouseX = x;
float sceneMouseY = y;
if (sceneMouseY >= 190.0f && sceneMouseY <= 270.0f)
{
int newTab = -1;
if (sceneMouseX >= 480.0f && sceneMouseX <= 700.0f)
newTab = TAB_WORLD_OPTIONS;
else if (sceneMouseX > 700.0f && sceneMouseX <= 960.0f)
newTab = TAB_GAME_OPTIONS;
if (newTab >= 0)
{
if (m_tabIndex != newTab)
{
m_bPendingTabSwitch = true;
m_iPendingTabIndex = newTab;
ui.PlayUISFX(eSFX_Press);
}
return true;
}
}
return UIScene::handleMouseClick(x, y);
}
#endif
#if defined(__PSVITA__) || defined(_WINDOWS64)
UIControl* UIScene_LaunchMoreOptionsMenu::GetMainPanel()
{
@@ -146,6 +146,9 @@ public:
#endif
// INPUT
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
#ifdef _WINDOWS64
virtual bool handleMouseClick(F32 x, F32 y);
#endif
virtual void handleFocusChange(F64 controlId, F64 childId);
virtual void handleTimerComplete(int id);
static int KeyboardCompleteSeedCallback(LPVOID lpParam,const bool bRes);
@@ -162,6 +165,9 @@ private:
bool m_bUpdateOnline; // If true, update online settings on next tick
void UpdateOnline();
bool m_bPendingTabSwitch;
int m_iPendingTabIndex;
#ifdef __PSVITA__
virtual void handleTouchInput(unsigned int iPad, S32 x, S32 y, int iId, bool bPressed, bool bRepeat, bool bReleased);
#endif //__PSVITA__
@@ -1,4 +1,9 @@
#include "stdafx.h"
#include "../../Lighting.h"
#ifdef _WINDOWS64
#include "../../Windows64/Iggy/gdraw/gdraw_d3d11.h"
#include "../../Windows64/4JLibs/inc/4J_Render.h"
#endif
#include "../../../Minecraft.World/Mth.h"
#include "../../../Minecraft.World/StringHelpers.h"
#include "../../../Minecraft.World/Random.h"
@@ -556,6 +561,60 @@ void UIScene_MainMenu::customDrawSplash(IggyCustomDrawCallbackRegion *region)
ui.endCustomDraw(region);
}
void UIScene_MainMenu::render(S32 width, S32 height, C4JRender::eViewportType viewport)
{
UIScene::render(width, height, viewport);
Minecraft *pMinecraft = Minecraft::GetInstance();
if (!pMinecraft || !pMinecraft->font) return;
Font *font = pMinecraft->font;
const wstring part1 = L"neo";
const wstring part2 = L"Legacy";
const float scale = 0.6f;
const int pad = 4;
ScreenSizeCalculator ssc(pMinecraft->options, pMinecraft->width_phys, pMinecraft->height_phys);
S32 sw = ssc.getWidth();
S32 sh = ssc.getHeight();
#ifdef _WINDOWS64
RenderManager.StartFrame();
gdraw_D3D11_setViewport_4J();
#endif
RenderManager.Set_matrixDirty();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, sw, sh, 0, 1000, 3000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -2000.0f);
Lighting::turnOff();
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
int totalW = static_cast<int>((font->width(part1) + font->width(part2)) * scale);
int tx = sw - totalW - pad;
int ty = sh - static_cast<int>(8 * scale) - pad;
glPushMatrix();
glTranslatef(static_cast<float>(tx), static_cast<float>(ty), 0.0f);
glScalef(scale, scale, scale);
font->drawShadow(part1, 0, 0, 0x66A254FA);
font->drawShadow(part2, font->width(part1), 0, 0x66ffffff);
glPopMatrix();
glDepthMask(true);
glEnable(GL_DEPTH_TEST);
}
int UIScene_MainMenu::MustSignInReturned(void *pParam, int iPad, C4JStorage::EMessageResult result)
{
UIScene_MainMenu* pClass = static_cast<UIScene_MainMenu *>(pParam);
@@ -118,6 +118,7 @@ public:
virtual EUIScene getSceneType() { return eUIScene_MainMenu;}
virtual void customDraw(IggyCustomDrawCallbackRegion *region);
virtual void render(S32 width, S32 height, C4JRender::eViewportType viewport);
protected:
void customDrawSplash(IggyCustomDrawCallbackRegion *region);
Binary file not shown.

After

Width:  |  Height:  |  Size: 776 B

@@ -0,0 +1,4 @@
interp:1
0*8
1*8
2*8
Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

@@ -1,440 +1,23 @@
0*15
1*15
2*15
3*15
4*15
5*15
6*15
7*15
8*15
9*15
10*15
11*15
12*15
13*15
14*15
15*15
16*15
17*15
18*15
19*15
20*15
21*15
22*15
23*15
24*15
25*15
26*15
27*15
28*15
29*15
30*15
31*15
32*15
33*15
34*15
35*15
36*15
37*15
38*15
39*15
40*15
41*15
42*15
43*15
44*15
45*15
46*15
47*15
48*15
49*15
50*15
51*15
52*15
53*15
54*15
55*15
56*15
57*15
58*15
59*15
60*15
61*15
62*15
63*15
64*15
65*15
66*15
67*15
68*15
69*15
70*15
71*15
72*15
73*15
74*15
75*15
76*15
77*15
78*15
79*15
80*15
81*15
82*15
83*15
84*15
85*15
86*15
87*15
88*15
89*15
90*15
91*15
92*15
93*15
94*15
95*15
96*15
97*15
98*15
99*15
100*15
101*15
102*15
103*15
104*15
105*15
106*15
107*15
108*15
109*15
110*15
111*15
112*15
113*15
114*15
115*15
116*15
117*15
118*15
119*15
120*15
121*15
122*15
123*15
124*15
125*15
126*15
127*15
128*15
129*15
130*15
131*15
132*15
133*15
134*15
135*15
136*15
137*15
138*15
139*15
140*15
141*15
142*15
143*15
144*15
145*15
146*15
147*15
148*15
149*15
150*15
151*15
152*15
153*15
154*15
155*15
156*15
157*15
158*15
159*15
160*15
161*15
162*15
163*15
164*15
165*15
166*15
167*15
168*15
169*15
170*15
171*15
172*15
173*15
174*15
175*15
176*15
177*15
178*15
179*15
180*15
181*15
182*15
183*15
184*15
185*15
186*15
187*15
188*15
189*15
190*15
191*15
192*15
193*15
194*15
195*15
196*15
197*15
198*15
199*15
200*15
201*15
202*15
203*15
204*15
205*15
206*15
207*15
208*15
209*15
210*15
211*15
212*15
213*15
214*15
215*15
216*15
217*15
218*15
219*15
220*15
221*15
222*15
223*15
224*15
225*15
226*15
227*15
228*15
229*15
230*15
231*15
232*15
233*15
234*15
235*15
236*15
237*15
238*15
239*15
240*15
241*15
242*15
243*15
244*15
245*15
246*15
247*15
248*15
249*15
250*15
251*15
252*15
253*15
254*15
255*15
256*15
257*15
258*15
259*15
260*15
261*15
262*15
263*15
264*15
265*15
266*15
267*15
268*15
269*15
270*15
271*15
272*15
273*15
274*15
275*15
276*15
277*15
278*15
279*15
280*15
281*15
282*15
283*15
284*15
285*15
286*15
287*15
288*15
289*15
290*15
291*15
292*15
293*15
294*15
295*15
296*15
297*15
298*15
299*15
300*15
301*15
302*15
303*15
304*15
305*15
306*15
307*15
308*15
309*15
310*15
311*15
312*15
313*15
314*15
315*15
316*15
317*15
318*15
319*15
320*15
321*15
322*15
323*15
324*15
325*15
326*15
327*15
328*15
329*15
330*15
331*15
332*15
333*15
334*15
335*15
336*15
337*15
338*15
339*15
340*15
341*15
342*15
343*15
344*15
345*15
346*15
347*15
348*15
349*15
350*15
351*15
352*15
353*15
354*15
355*15
356*15
357*15
358*15
359*15
360*15
361*15
362*15
363*15
364*15
365*15
366*15
367*15
368*15
369*15
370*15
371*15
372*15
373*15
374*15
375*15
376*15
377*15
378*15
379*15
380*15
381*15
382*15
383*15
384*15
385*15
386*15
387*15
388*15
389*15
390*15
391*15
392*15
393*15
394*15
395*15
396*15
397*15
398*15
399*15
400*15
401*15
402*15
403*15
404*15
405*15
406*15
407*15
408*15
409*15
410*15
411*15
412*15
413*15
414*15
415*15
416*15
417*15
418*15
419*15
420*15
421*15
422*15
423*15
424*15
425*15
426*15
427*15
428*15
429*15
430*15
431*15
432*15
433*15
434*15
435*15
436*15
437*15
438*15
439*15
interp:1
0*300
1*300
0*300
2*300
0*300
3*300
0*300
1*300
2*300
1*300
3*300
1*300
0*300
2*300
1*300
2*300
3*300
2*300
0*300
3*300
1*300
3*300
Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

@@ -4726,7 +4726,7 @@ At night monsters come out, make sure to build a shelter before that happens.</v
</data>
<data name="IDS_TOOLTIPS_WHAT_IS_THIS">
<value>What's This?</value>
<value>Info</value>
</data>
<data name="IDS_TOOLTIPS_SHARE">
+13 -5
View File
@@ -214,9 +214,8 @@ void GameRenderer::tick(bool first) // 4J - add bFirst
{
shared_ptr<Player> yBobPlayer = dynamic_pointer_cast<Player>(mc->cameraTargetPlayer);
float target = 0.0f;
if (yBobPlayer != nullptr && yBobPlayer->isElytraFlying())
if (yBobPlayer != nullptr && yBobPlayer->isElytraFlying())
{
target = (float)(atan(-yBobPlayer->yd * 0.2) * 15.0);
}
m_yBob += (target - m_yBob) * 0.8f;
@@ -482,7 +481,8 @@ void GameRenderer::bobView(float a)
glRotatef((float) tilt, 1, 0, 0);
float yBobAngle = m_yBobO + (m_yBob - m_yBobO) * a;
if (fabsf(yBobAngle) > 0.001f)
shared_ptr<LocalPlayer> yBobLocalPlayer = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
if (fabsf(yBobAngle) > 0.001f && yBobLocalPlayer != nullptr && yBobLocalPlayer->isElytraFlying() && !yBobLocalPlayer->ThirdPersonView())
glRotatef(yBobAngle, 1, 0, 0);
}
@@ -742,7 +742,11 @@ void GameRenderer::setupCamera(float a, int eye)
glTranslatef(static_cast<float>(zoom_x), static_cast<float>(-zoom_y), 0);
glScaled(zoom, zoom, 1);
}
gluPerspective(fov, aspect, 0.05f, renderDistance * 2);
{
auto _sp = dynamic_pointer_cast<Player>(mc->cameraTargetPlayer);
float nearClip = (_sp && _sp->abilities.spectatorMode) ? 0.99f : 0.05f;
gluPerspective(fov, aspect, nearClip, renderDistance * 2);
}
if (mc->gameMode->isCutScene())
{
@@ -825,7 +829,11 @@ void GameRenderer::renderItemInHand(float a, int eye)
glTranslatef(static_cast<float>(zoom_x), static_cast<float>(-zoom_y), 0);
glScaled(zoom, zoom, 1);
}
gluPerspective(fov, aspect, 0.05f, renderDistance * 2);
{
auto _sp = dynamic_pointer_cast<Player>(mc->cameraTargetPlayer);
float nearClip = (_sp && _sp->abilities.spectatorMode) ? 0.99f : 0.05f;
gluPerspective(fov, aspect, nearClip, renderDistance * 2);
}
if (mc->gameMode->isCutScene())
{
+14 -5
View File
@@ -685,9 +685,13 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
{
characterDisplayTimer[iPad] = 30;
}
else if( minecraft->player->isElytraFlying() )
{
characterDisplayTimer[iPad] = 30;
}
else if( minecraft->player->abilities.flying)
{
characterDisplayTimer[iPad] = 5; // quickly get rid of the player display if they stop flying
characterDisplayTimer[iPad] = 5;
}
else if( characterDisplayTimer[iPad] > 0 )
{
@@ -696,8 +700,9 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
bool displayCrouch = minecraft->player->isSneaking() || ( characterDisplayTimer[iPad] > 0 );
bool displaySprint = minecraft->player->isSprinting() || ( characterDisplayTimer[iPad] > 0 );
bool displayFlying = minecraft->player->abilities.flying || ( characterDisplayTimer[iPad] > 0 );
bool displayElytra = minecraft->player->isElytraFlying() || ( characterDisplayTimer[iPad] > 0 );
if( bDisplayGui && (displayCrouch || displaySprint || displayFlying) )
if( bDisplayGui && (displayCrouch || displaySprint || displayElytra || displayFlying) )
{
EntityRenderDispatcher::instance->prepare(minecraft->level, minecraft->textures, minecraft->font, minecraft->cameraTargetPlayer, minecraft->crosshairPickMob, minecraft->options, a);
glEnable(GL_RESCALE_NORMAL);
@@ -714,7 +719,10 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
#endif
glPushMatrix();
glTranslatef(static_cast<float>(xo), static_cast<float>(yo), 50);
float pitchOffset = minecraft->player->isElytraFlying()
? -minecraft->player->xRot / 180.0f * 40.0f
: 0.0f;
glTranslatef(static_cast<float>(xo), static_cast<float>(yo) + pitchOffset, 50);
// correct paper doll aspect ratio
float ss = 12.0f;
@@ -756,7 +764,8 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
Lighting::turnOn();
glRotatef(-45 - 90, 0, 1, 0);
const float xRotAngle = -(float) atan(yd / 40.0f) * 20;
bool elytraFlying = minecraft->player->isElytraFlying();
const float xRotAngle = elytraFlying ? 0.0f : -(float) atan(yd / 40.0f) * 20;
glRotatef(xRotAngle, 1, 0, 0);
float bodyRot = (minecraft->player->yBodyRotO + (minecraft->player->yBodyRot - minecraft->player->yBodyRotO));
// Fixed rotation angle of degrees, adjusted by bodyRot to negate the rotation that occurs in the renderer
@@ -768,7 +777,7 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
// Set head rotation to body rotation to make head static
minecraft->player->yRot = bodyRot;
minecraft->player->yRotO = minecraft->player->yRot;
minecraft->player->xRot = xRotAngle;
minecraft->player->xRot = elytraFlying ? oxr : xRotAngle;
minecraft->player->onFire = 0;
minecraft->player->setSharedFlag(Entity::FLAG_ONFIRE, false);
+22
View File
@@ -1387,9 +1387,15 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float
if (elytraCrouching)
{
arm0->xRot = PI; arm0->yRot = 0.0f; arm0->zRot = 0.0f; arm0->y = 2.0f;
if (sleeve0) { sleeve0->xRot = PI; sleeve0->yRot = 0.0f; sleeve0->zRot = 0.0f; sleeve0->y = 2.0f; }
arm1->xRot = 0.0f; arm1->yRot = 0.0f; arm1->zRot = 0.0f; arm1->y = 2.0f;
if (sleeve1) { sleeve1->xRot = 0.0f; sleeve1->yRot = 0.0f; sleeve1->zRot = 0.0f; sleeve1->y = 2.0f; }
leg0->xRot = 0.0f; leg0->yRot = 0.0f; leg0->zRot = 0.0f;
leg1->xRot = 0.0f; leg1->yRot = 0.0f; leg1->zRot = 0.0f;
if (pants0) { pants0->xRot = 0.0f; pants0->yRot = 0.0f; pants0->zRot = 0.0f; }
if (pants1) { pants1->xRot = 0.0f; pants1->yRot = 0.0f; pants1->zRot = 0.0f; }
}
else
{
@@ -1404,14 +1410,30 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float
arm0->xRot = Mth::cos(elytraTime + PI) * armAmp;
arm0->yRot = 0.0f; arm0->zRot = 0.0f; arm0->y = 2.0f;
if (sleeve0) { sleeve0->xRot = arm0->xRot; sleeve0->yRot = 0.0f; sleeve0->zRot = 0.0f; sleeve0->y = 2.0f; }
if (attackTime > -9990.0f)
{
float elytraSwing = 1.0f - attackTime;
elytraSwing *= elytraSwing; elytraSwing *= elytraSwing;
elytraSwing = 1.0f - elytraSwing;
float elytraAA = Mth::sin(elytraSwing * PI);
float elytraBB = Mth::sin(attackTime * PI) * -(head->xRot - 0.7f) * 0.75f;
arm0->xRot -= elytraAA * 1.2f + elytraBB;
arm0->zRot = Mth::sin(attackTime * PI) * -0.4f;
if (sleeve0) { sleeve0->xRot -= elytraAA * 1.2f + elytraBB; sleeve0->zRot = Mth::sin(attackTime * PI) * -0.4f; }
}
arm1->xRot = Mth::cos(elytraTime) * armAmp;
arm1->yRot = 0.0f; arm1->zRot = 0.0f; arm1->y = 2.0f;
if (sleeve1) { sleeve1->xRot = arm1->xRot; sleeve1->yRot = 0.0f; sleeve1->zRot = 0.0f; sleeve1->y = 2.0f; }
leg0->xRot = Mth::cos(elytraTime) * legAmp;
leg0->yRot = 0.0f; leg0->zRot = 0.0f;
leg1->xRot = Mth::cos(elytraTime + PI) * legAmp;
leg1->yRot = 0.0f; leg1->zRot = 0.0f;
if (pants0) { pants0->xRot = leg0->xRot; pants0->yRot = 0.0f; pants0->zRot = 0.0f; }
if (pants1) { pants1->xRot = leg1->xRot; pants1->yRot = 0.0f; pants1->zRot = 0.0f; }
}
body->xRot = 0.0f;
+5
View File
@@ -128,6 +128,8 @@ LocalPlayer::LocalPlayer(Minecraft *minecraft, Level *level, User *user, int dim
LocalPlayer::~LocalPlayer()
{
if (minecraft != nullptr && minecraft->soundEngine != nullptr)
minecraft->soundEngine->stopElytraSound();
if( this->input != nullptr )
delete input;
}
@@ -168,6 +170,9 @@ bool LocalPlayer::isEffectiveAi() const
void LocalPlayer::aiStep()
{
if (abilities.spectatorMode)
noPhysics = true;
if (sprintTime > 0)
{
sprintTime--;
+340
View File
@@ -0,0 +1,340 @@
#include "stdafx.h"
#undef OutputDebugStringA
#undef OutputDebugStringW
#undef OutputDebugString
#include "Logger.h"
#include <dbghelp.h>
#include <time.h>
#include <intrin.h>
static FILE *s_logFile = nullptr;
static CRITICAL_SECTION s_cs;
static bool s_csInit = false;
static const char *s_wittyComments[] =
{
"Who set us up the TNT?",
"Everything's a creeper when you think about it",
"I bet Notch wouldn't have this problem",
"Oops.",
"Why did you do that?",
"Uh... Did I do that?",
"I just don't know what went wrong",
"Quite honestly, I wouldn't worry myself about that.",
"This doesn't make any sense!",
"This is a bug, not a feature!",
"The server is on fire.",
"My bad.",
"I feel sad now :(",
"Don't be sad, have a hug! <3",
"You should try our sister game, Minceraft!",
"Hi. I'm Minecraft, and I'm a crashaholic.",
"Ooh. Shiny.",
"This is not good.",
"Abandon ship!",
"Oh - I know what I did wrong!",
"Shall we play a game?",
"Quite honestly, I wouldn't worry myself about that.",
"Sorry, Dave.",
"We're sorry, we're sorry, we're sorry...",
"Never gonna give you up.",
"A wild Herobrine appeared.",
"Surprise! Haha. Well, this is awkward.",
"Would you like a cupcake?",
"Oh man. I thought that might happen.",
"This is not a good sign.",
};
static void writeRaw(const char *msg)
{
if (!s_logFile) return;
fputs(msg, s_logFile);
fflush(s_logFile);
}
static void writeLineA(const char *msg)
{
if (!s_logFile) return;
EnterCriticalSection(&s_cs);
fputs(msg, s_logFile);
fputc('\n', s_logFile);
fflush(s_logFile);
LeaveCriticalSection(&s_cs);
}
static void getTimestamp(char *buf, size_t size)
{
time_t t = time(nullptr);
struct tm tm_info;
localtime_s(&tm_info, &t);
strftime(buf, size, "%Y-%m-%d %H:%M:%S", &tm_info);
}
static void getCpuName(char *buf, size_t size)
{
int regs[4] = {};
char name[49] = {};
__cpuid(regs, 0x80000002); memcpy(name, regs, 16);
__cpuid(regs, 0x80000003); memcpy(name + 16, regs, 16);
__cpuid(regs, 0x80000004); memcpy(name + 32, regs, 16);
name[48] = '\0';
const char *p = name;
while (*p == ' ') p++;
strncpy_s(buf, size, p, _TRUNCATE);
}
static void getOsName(char *buf, size_t size)
{
DWORD major = 0, minor = 0, build = 0;
HKEY hKey = nullptr;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
DWORD val = 0, sz = sizeof(val);
if (RegQueryValueExW(hKey, L"CurrentMajorVersionNumber", nullptr, nullptr, (LPBYTE)&val, &sz) == ERROR_SUCCESS) major = val;
sz = sizeof(val);
if (RegQueryValueExW(hKey, L"CurrentMinorVersionNumber", nullptr, nullptr, (LPBYTE)&val, &sz) == ERROR_SUCCESS) minor = val;
sz = sizeof(val);
if (RegQueryValueExW(hKey, L"CurrentBuildNumber", nullptr, nullptr, (LPBYTE)&val, &sz) == ERROR_SUCCESS) build = val;
if (build == 0)
{
wchar_t strBuild[16] = {};
DWORD strSz = sizeof(strBuild);
if (RegQueryValueExW(hKey, L"CurrentBuildNumber", nullptr, nullptr, (LPBYTE)strBuild, &strSz) == ERROR_SUCCESS)
build = (DWORD)_wtoi(strBuild);
}
RegCloseKey(hKey);
}
SYSTEM_INFO si = {};
GetNativeSystemInfo(&si);
const char *arch = (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ? "amd64" : "x86";
snprintf(buf, size, "Windows %lu.%lu (Build %lu) (%s)", major, minor, build, arch);
}
static const char *exceptionName(DWORD code)
{
switch (code)
{
case EXCEPTION_ACCESS_VIOLATION: return "ACCESS_VIOLATION";
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "ARRAY_BOUNDS_EXCEEDED";
case EXCEPTION_BREAKPOINT: return "BREAKPOINT";
case EXCEPTION_DATATYPE_MISALIGNMENT: return "DATATYPE_MISALIGNMENT";
case EXCEPTION_FLT_DENORMAL_OPERAND: return "FLT_DENORMAL_OPERAND";
case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "FLT_DIVIDE_BY_ZERO";
case EXCEPTION_FLT_INEXACT_RESULT: return "FLT_INEXACT_RESULT";
case EXCEPTION_FLT_INVALID_OPERATION: return "FLT_INVALID_OPERATION";
case EXCEPTION_FLT_OVERFLOW: return "FLT_OVERFLOW";
case EXCEPTION_FLT_STACK_CHECK: return "FLT_STACK_CHECK";
case EXCEPTION_FLT_UNDERFLOW: return "FLT_UNDERFLOW";
case EXCEPTION_ILLEGAL_INSTRUCTION: return "ILLEGAL_INSTRUCTION";
case EXCEPTION_IN_PAGE_ERROR: return "IN_PAGE_ERROR";
case EXCEPTION_INT_DIVIDE_BY_ZERO: return "INT_DIVIDE_BY_ZERO";
case EXCEPTION_INT_OVERFLOW: return "INT_OVERFLOW";
case EXCEPTION_INVALID_DISPOSITION: return "INVALID_DISPOSITION";
case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "NONCONTINUABLE_EXCEPTION";
case EXCEPTION_PRIV_INSTRUCTION: return "PRIV_INSTRUCTION";
case EXCEPTION_SINGLE_STEP: return "SINGLE_STEP";
case EXCEPTION_STACK_OVERFLOW: return "STACK_OVERFLOW";
default: return "UNKNOWN";
}
}
static LONG WINAPI crashHandler(EXCEPTION_POINTERS *ep)
{
if (!s_logFile) return EXCEPTION_CONTINUE_SEARCH;
DWORD code = ep->ExceptionRecord->ExceptionCode;
const char *name = exceptionName(code);
srand((unsigned)time(nullptr));
const char *comment = s_wittyComments[rand() % (sizeof(s_wittyComments) / sizeof(s_wittyComments[0]))];
char timestamp[64];
getTimestamp(timestamp, sizeof(timestamp));
char description[128];
if (code == EXCEPTION_ACCESS_VIOLATION && ep->ExceptionRecord->NumberParameters >= 2)
{
const char *op = ep->ExceptionRecord->ExceptionInformation[0] == 1 ? "write" : "read";
snprintf(description, sizeof(description),
"%s (0x%08X) - Attempted to %s from address 0x%p",
name, code, op, (void*)ep->ExceptionRecord->ExceptionInformation[1]);
}
else
{
snprintf(description, sizeof(description), "%s (0x%08X)", name, code);
}
EnterCriticalSection(&s_cs);
fprintf(s_logFile,
"\n\n---- neoLegacy Crash Report ----\n"
"// %s\n\n"
"Time: %s\n"
"Description: %s\n\n",
comment, timestamp, description);
HANDLE proc = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
SymInitialize(proc, nullptr, TRUE);
SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
CONTEXT ctx = *ep->ContextRecord;
STACKFRAME64 frame = {};
#ifdef _WIN64
DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
frame.AddrPC.Offset = ctx.Rip;
frame.AddrStack.Offset = ctx.Rsp;
#else
DWORD machineType = IMAGE_FILE_MACHINE_I386;
frame.AddrPC.Offset = ctx.Eip;
frame.AddrStack.Offset = ctx.Esp;
#endif
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrStack.Mode = AddrModeFlat;
char symBuf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
SYMBOL_INFO *sym = (SYMBOL_INFO*)symBuf;
IMAGEHLP_LINE64 line = {};
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
fputs("Stack Trace:\n", s_logFile);
for (int i = 0; i < 64; i++)
{
if (!StackWalk64(machineType, proc, thread, &frame, &ctx,
nullptr, SymFunctionTableAccess64, SymGetModuleBase64, nullptr))
break;
if (frame.AddrPC.Offset == 0) break;
sym->SizeOfStruct = sizeof(SYMBOL_INFO);
sym->MaxNameLen = MAX_SYM_NAME;
DWORD64 disp64 = 0;
DWORD disp32 = 0;
if (SymFromAddr(proc, frame.AddrPC.Offset, &disp64, sym))
{
if (SymGetLineFromAddr64(proc, frame.AddrPC.Offset, &disp32, &line))
fprintf(s_logFile, "\tat %s (%s:%lu)\n", sym->Name, line.FileName, line.LineNumber);
else
fprintf(s_logFile, "\tat %s+0x%llx\n", sym->Name, disp64);
}
else
{
fprintf(s_logFile, "\tat 0x%016llX\n", frame.AddrPC.Offset);
}
}
SymCleanup(proc);
fprintf(s_logFile,
"\nA detailed walkthrough of the error, its code path and all known details is as follows:\n"
"---------------------------------------------------------------------------\n\n");
fprintf(s_logFile, "-- System Details --\nDetails:\n");
fprintf(s_logFile, "\tneoLegacy Version: %s\n", NEOL_VERSION);
char osBuf[128];
getOsName(osBuf, sizeof(osBuf));
fprintf(s_logFile, "\tOperating System: %s\n", osBuf);
char cpuBuf[64];
getCpuName(cpuBuf, sizeof(cpuBuf));
fprintf(s_logFile, "\tCPU: %s\n", cpuBuf);
MEMORYSTATUSEX mem = {};
mem.dwLength = sizeof(mem);
GlobalMemoryStatusEx(&mem);
DWORDLONG freeMB = mem.ullAvailPhys / (1024 * 1024);
DWORDLONG totalMB = mem.ullTotalPhys / (1024 * 1024);
fprintf(s_logFile, "\tMemory: %llu bytes (%llu MB) free / %llu bytes (%llu MB) total\n",
mem.ullAvailPhys, freeMB, mem.ullTotalPhys, totalMB);
fflush(s_logFile);
LeaveCriticalSection(&s_cs);
return EXCEPTION_CONTINUE_SEARCH;
}
void Logger::init()
{
InitializeCriticalSection(&s_cs);
s_csInit = true;
char exePath[MAX_PATH] = {};
GetModuleFileNameA(nullptr, exePath, MAX_PATH);
char *slash = strrchr(exePath, '\\');
if (slash) *(slash + 1) = '\0';
strcat_s(exePath, "neoLegacy_log.txt");
fopen_s(&s_logFile, exePath, "w");
if (!s_logFile) return;
SetUnhandledExceptionFilter(crashHandler);
char timestamp[64];
getTimestamp(timestamp, sizeof(timestamp));
char osBuf[128];
getOsName(osBuf, sizeof(osBuf));
char cpuBuf[64];
getCpuName(cpuBuf, sizeof(cpuBuf));
fprintf(s_logFile,
"neoLegacy log started %s\n"
"Version: %s | OS: %s | CPU: %s\n"
"--------------------------------------------------------------------------\n\n",
timestamp, NEOL_VERSION, osBuf, cpuBuf);
fflush(s_logFile);
}
void Logger::shutdown()
{
if (s_logFile)
{
char timestamp[64];
getTimestamp(timestamp, sizeof(timestamp));
fprintf(s_logFile, "\n--------------------------------------------------------------------------\n");
fprintf(s_logFile, "neoLegacy log ended %s\n", timestamp);
fclose(s_logFile);
s_logFile = nullptr;
}
if (s_csInit)
{
DeleteCriticalSection(&s_cs);
s_csInit = false;
}
}
void Logger::interceptA(const char *msg)
{
#ifndef _FINAL_BUILD
OutputDebugStringA(msg);
#endif
writeLineA(msg);
}
void Logger::interceptW(const wchar_t *msg)
{
#ifndef _FINAL_BUILD
OutputDebugStringW(msg);
#endif
if (!s_logFile) return;
int needed = WideCharToMultiByte(CP_UTF8, 0, msg, -1, nullptr, 0, nullptr, nullptr);
if (needed <= 0) return;
char *buf = new char[needed];
WideCharToMultiByte(CP_UTF8, 0, msg, -1, buf, needed, nullptr, nullptr);
writeLineA(buf);
delete[] buf;
}
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#define NEOL_VERSION "TU43"
class Logger
{
public:
static void init();
static void shutdown();
static void interceptA(const char *msg);
static void interceptW(const wchar_t *msg);
};
+2 -2
View File
@@ -4342,10 +4342,10 @@ void Minecraft::releaseLevel(int message)
// time when exiting from an online game
void Minecraft::forceStatsSave(int idx)
{
//4J Gordon: Force a stats save
if (idx < 0 || idx >= 4 || stats[idx] == nullptr) return;
stats[idx]->save(idx, true);
//4J Gordon: If the player is signed in, save the leaderboards
if( ProfileManager.IsSignedInLive(idx) )
{
int tempLockedProfile = ProfileManager.GetLockedProfile();
+22 -6
View File
@@ -4,6 +4,7 @@
#include "ClientConnection.h"
#include "../Minecraft.World/net.minecraft.world.level.h"
#include "../Minecraft.World/net.minecraft.network.h"
#include "../Minecraft.World/PlayerActionPacket.h"
#include "../Minecraft.World/Mth.h"
#include "../Minecraft.World/AABB.h"
#include "../Minecraft.World/net.minecraft.stats.h"
@@ -76,7 +77,7 @@ void MultiplayerLocalPlayer::tick()
{
if (isRiding())
{
connection->send(std::make_shared<MovePlayerPacket::Rot>(yRot, xRot, onGround, abilities.flying));
connection->send(std::make_shared<MovePlayerPacket::Rot>(yRot, xRot, onGround, abilities.flying || isElytraFlying()));
connection->send(std::make_shared<PlayerInputPacket>(xxa, yya, input->jumping, input->sneaking));
}
else
@@ -131,26 +132,26 @@ void MultiplayerLocalPlayer::sendPosition()
bool rot = rydd != 0 || rxdd != 0;
if (riding != nullptr)
{
connection->send(std::make_shared<MovePlayerPacket::PosRot>(xd, -999, -999, zd, yRot, xRot, onGround, abilities.flying));
connection->send(std::make_shared<MovePlayerPacket::PosRot>(xd, -999, -999, zd, yRot, xRot, onGround, abilities.flying || isElytraFlying()));
move = false;
}
else
{
if (move && rot)
{
connection->send(std::make_shared<MovePlayerPacket::PosRot>(x, bb->y0, y, z, yRot, xRot, onGround, abilities.flying));
connection->send(std::make_shared<MovePlayerPacket::PosRot>(x, bb->y0, y, z, yRot, xRot, onGround, abilities.flying || isElytraFlying()));
}
else if (move)
{
connection->send(std::make_shared<MovePlayerPacket::Pos>(x, bb->y0, y, z, onGround, abilities.flying));
connection->send(std::make_shared<MovePlayerPacket::Pos>(x, bb->y0, y, z, onGround, abilities.flying || isElytraFlying()));
}
else if (rot)
{
connection->send(std::make_shared<MovePlayerPacket::Rot>(yRot, xRot, onGround, abilities.flying));
connection->send(std::make_shared<MovePlayerPacket::Rot>(yRot, xRot, onGround, abilities.flying || isElytraFlying()));
}
else
{
connection->send(std::make_shared<MovePlayerPacket>(onGround, abilities.flying));
connection->send(std::make_shared<MovePlayerPacket>(onGround, abilities.flying || isElytraFlying()));
}
}
@@ -210,6 +211,21 @@ void MultiplayerLocalPlayer::actuallyHurt(DamageSource *source, float dmg)
setHealth(getHealth() - dmg);
}
void MultiplayerLocalPlayer::onElytraKineticDamage(float damage)
{
if (damage <= 0.0f) return;
int dmg = (int)damage;
if ((float)dmg < damage) dmg++;
if (dmg < 1) dmg = 1;
connection->send(std::make_shared<PlayerActionPacket>(PlayerActionPacket::ELYTRA_IMPACT, dmg, 0, 0, 0));
}
void MultiplayerLocalPlayer::onElytraFallDamage(int amount)
{
if (amount <= 0) return;
connection->send(std::make_shared<PlayerActionPacket>(PlayerActionPacket::ELYTRA_FALL_DAMAGE, amount, 0, 0, 0));
}
// 4J Added override to capture event for tutorial messages
void MultiplayerLocalPlayer::completeUsingItem()
{
@@ -44,6 +44,8 @@ public:
virtual void respawn();
protected:
virtual void actuallyHurt(DamageSource *source, float dmg);
virtual void onElytraKineticDamage(float damage);
virtual void onElytraFallDamage(int amount);
// 4J Added override to capture event for tutorial messages
virtual void completeUsingItem();
+94 -4
View File
@@ -12,6 +12,8 @@
#include "../Minecraft.World/net.minecraft.world.level.dimension.h"
#include "../Minecraft.World/net.minecraft.world.item.h"
#include "../Minecraft.World/net.minecraft.world.item.trading.h"
#include "../Minecraft.World/net.minecraft.world.damagesource.h"
#include "../Minecraft.World/net.minecraft.world.effect.h"
#include "../Minecraft.World/net.minecraft.world.inventory.h"
#include "../Minecraft.World/net.minecraft.world.level.tile.entity.h"
#include "../Minecraft.World/net.minecraft.world.level.saveddata.h"
@@ -85,6 +87,8 @@ PlayerConnection::PlayerConnection(MinecraftServer *server, Connection *connecti
done = false;
tickCount = 0;
aboveGroundTickCount = 0;
elytraDurabilityTicks = 0;
elytraBoostCooldown = 0;
xLastOk = yLastOk = zLastOk = 0;
synched = true;
hasDoneFirstTickFourKit = false;
@@ -460,14 +464,20 @@ void PlayerConnection::handleMovePlayer(shared_ptr<MovePlayerPacket> packet)
return;
}
bool newOk = level->getCubes(player, playerBB->copy()->shrink(r, r, r))->empty();
if (oldOk && (fail || !newOk) && !player->isSleeping())
if (oldOk && (fail || !newOk) && !player->isSleeping() && !player->abilities.spectatorMode)
{
teleport(xLastOk, yLastOk, zLastOk, yRotT, xRotT);
return;
}
if (player->abilities.spectatorMode)
{
xLastOk = xt;
yLastOk = yt;
zLastOk = zt;
}
AABB *testBox = playerBB->copy()->grow(r, r, r)->expand(0, -0.55, 0);
// && server.level.getCubes(player, testBox).size() == 0
if (!server->isFlightAllowed() && !player->gameMode->isCreative() && !level->containsAnyBlocks(testBox) && !player->isAllowedToFly() )
if (!server->isFlightAllowed() && !player->gameMode->isCreative() && !level->containsAnyBlocks(testBox) && !player->isAllowedToFly() && !player->abilities.spectatorMode)
{
if (oyDist >= (-0.5f / 16.0f))
{
@@ -490,9 +500,32 @@ void PlayerConnection::handleMovePlayer(shared_ptr<MovePlayerPacket> packet)
player->onGround = packet->onGround;
server->getPlayers()->move(player);
player->doCheckFallDamage(player->y - startY, packet->onGround);
if (packet->isFlying)
player->fallDistance = 0.0f;
else
player->doCheckFallDamage(player->y - startY, packet->onGround);
{
shared_ptr<ItemInstance> chestItem = player->inventory->armor[LivingEntity::SLOT_CHEST - 1];
bool elytraFlying = packet->isFlying && !player->onGround
&& chestItem != nullptr && dynamic_cast<ElytraItem*>(chestItem->getItem()) != nullptr;
if (elytraFlying)
{
if (++elytraDurabilityTicks >= 20)
{
elytraDurabilityTicks = 0;
chestItem->hurtAndBreak(1, dynamic_pointer_cast<LivingEntity>(player));
}
if (elytraBoostCooldown > 0)
elytraBoostCooldown--;
}
else
{
elytraDurabilityTicks = 0;
}
}
}
else if ((tickCount % SharedConstants::TICKS_PER_SECOND) == 0)
else if ((tickCount % SharedConstants::TICKS_PER_SECOND) == 0 && !player->abilities.spectatorMode)
{
teleport(xLastOk, yLastOk, zLastOk, player->yRot, player->xRot);
}
@@ -574,6 +607,20 @@ void PlayerConnection::handlePlayerAction(shared_ptr<PlayerActionPacket> packet)
player->releaseUsingItem();
return;
}
else if (packet->action == PlayerActionPacket::ELYTRA_IMPACT)
{
float damage = (float)packet->x;
if (damage > 0.0f)
player->hurt(DamageSource::flyIntoWall, damage);
return;
}
else if (packet->action == PlayerActionPacket::ELYTRA_FALL_DAMAGE)
{
float damage = (float)packet->x;
if (damage > 0.0f)
player->hurt(DamageSource::fall, damage);
return;
}
bool shouldVerifyLocation = false;
if (packet->action == PlayerActionPacket::START_DESTROY_BLOCK) shouldVerifyLocation = true;
@@ -668,6 +715,22 @@ void PlayerConnection::handleUseItem(shared_ptr<UseItemPacket> packet)
}
#endif
player->gameMode->useItem(player, level, item);
if (item->getItem() != nullptr && item->getItem()->getBaseItemType() == Item::eBaseItemType_fireworks && !player->abilities.instabuild)
{
shared_ptr<ItemInstance> chestItem = player->inventory->armor[LivingEntity::SLOT_CHEST - 1];
bool elytraFlying = !player->onGround
&& chestItem != nullptr
&& dynamic_cast<ElytraItem*>(chestItem->getItem()) != nullptr
&& ElytraItem::isFlyEnabled(chestItem);
if (elytraFlying && elytraBoostCooldown == 0)
{
elytraBoostCooldown = 20;
item->count--;
if (item->count <= 0)
player->inventory->items[player->inventory->selected] = nullptr;
}
}
}
else if ((packet->getY() < server->getMaxBuildHeight() - 1) || (packet->getFace() != Facing::UP && packet->getY() < server->getMaxBuildHeight()))
{
@@ -1412,6 +1475,33 @@ if (cmd == L"tp" || cmd == L"teleport")
shared_ptr<GameCommandPacket> packet = GiveItemCommand::preparePacket(target, item, amount, aux);
server->getCommandDispatcher()->performCommand(player, eGameCommand_Give, packet->data);
}
#ifndef _CONTENT_PACKAGE
else if (cmd == L"spectator")
{
player->m_spectatorMode = !player->m_spectatorMode;
if (player->m_spectatorMode)
{
player->abilities.mayfly = true;
player->abilities.flying = true;
player->abilities.invulnerable = true;
player->abilities.spectatorMode = true;
player->abilities.setFlyingSpeed(0.1f);
player->noPhysics = true;
player->addEffect(new MobEffectInstance(MobEffect::nightVision->id, 0x7fffffff, 0, true));
info(L"Spectator mode enabled.");
}
else
{
player->gameMode->getGameModeForPlayer()->updatePlayerAbilities(&player->abilities);
player->abilities.spectatorMode = false;
player->abilities.setFlyingSpeed(0.05f);
player->noPhysics = false;
player->removeEffect(MobEffect::nightVision->id);
info(L"Spectator mode disabled.");
}
player->onUpdateAbilities();
}
#endif
}
void PlayerConnection::handleAnimate(shared_ptr<AnimatePacket> packet)
+2
View File
@@ -28,6 +28,8 @@ private:
shared_ptr<ServerPlayer> player;
int tickCount;
int aboveGroundTickCount;
int elytraDurabilityTicks;
int elytraBoostCooldown;
bool didTick;
bool hasDoneFirstTickFourKit;
+1
View File
@@ -191,6 +191,7 @@ ServerPlayer::ServerPlayer(MinecraftServer *server, Level *level, const wstring&
connection = nullptr;
lastMoveX = lastMoveZ = 0;
spewTimer = 0;
m_spectatorMode = false;
lastRecordedHealthAndAbsorption = FLT_MIN;
lastSentHealth = -99999999;
lastSentFood = -99999999;
+1
View File
@@ -31,6 +31,7 @@ public:
vector<int> entitiesToRemove;
unordered_set<ChunkPos, ChunkPosKeyHash, ChunkPosKeyEq> seenChunks;
int spewTimer;
bool m_spectatorMode;
// 4J-Added, for 'Adventure Time' achievement.
Biome *currentBiome;
+19 -3
View File
@@ -43,6 +43,7 @@ StitchedTexture::StitchedTexture(const wstring &name, const wstring &filename) :
frameOverride = nullptr;
flags = 0;
frames = nullptr;
m_bInterpolate = false;
m_fileName = filename;
}
@@ -84,7 +85,8 @@ void StitchedTexture::init(Texture *source, vector<Texture *> *frames, int x, in
{
this->source = source;
this->frames = frames;
frame = -1; // Force an update of animated textures
frame = -1;
m_bInterpolate = false;
this->x = x;
this->y = y;
this->width = width;
@@ -209,12 +211,21 @@ void StitchedTexture::cycleFrames()
current = frameOverride->at(frame);
int newFrame = current.first;
if (oldFrame != newFrame && newFrame >= 0 && newFrame < frames->size())
if (oldFrame != newFrame && newFrame >= 0 && newFrame < (int)frames->size())
{
source->blit(x, y, frames->at(newFrame), rotated);
}
}
else if (m_bInterpolate)
{
int curIdx = current.first;
int nextIdx = frameOverride->at((frame + 1) % frameOverride->size()).first;
if (curIdx >= 0 && curIdx < (int)frames->size() && nextIdx >= 0 && nextIdx < (int)frames->size())
{
float t = static_cast<float>(subFrame) / static_cast<float>(current.second);
source->blitInterpolated(x, y, frames->at(curIdx), frames->at(nextIdx), t);
}
}
}
else
{
@@ -324,6 +335,11 @@ void StitchedTexture::loadAnimationFrames(const wstring &string)
for(auto& it : tokens)
{
token = trimString(it);
if (token == L"interp:1")
{
m_bInterpolate = true;
continue;
}
int multiPos = token.find_first_of('*');
if (multiPos > 0)
{
+1
View File
@@ -42,6 +42,7 @@ protected:
protected:
int frame;
int subFrame;
bool m_bInterpolate;
public:
static StitchedTexture *create(const wstring &name);
+32
View File
@@ -367,6 +367,38 @@ void Texture::writeAsPNG(const wstring &filename)
#endif
}
void Texture::blitInterpolated(int x, int y, Texture *srcA, Texture *srcB, float t)
{
ByteBuffer *bufA = srcA->getData(0);
ByteBuffer *bufB = srcB->getData(0);
if (!bufA || !bufB) return;
bufA->position(0);
bufB->position(0);
int sw = srcA->getWidth();
int sh = srcA->getHeight();
for (int srcY = 0; srcY < sh; srcY++)
{
int dstY = y + srcY;
for (int srcX = 0; srcX < sw; srcX++)
{
int srcPos = (srcY * sw + srcX) * 4;
int dstPos = (dstY * width + (x + srcX)) * 4;
for (int c = 0; c < 4; c++)
{
int a = bufA->get(srcPos + c) & 0xFF;
int b = bufB->get(srcPos + c) & 0xFF;
data[0]->put(dstPos + c, (BYTE)(a + (int)((b - a) * t)));
}
}
}
if (immediateUpdate) updateOnGPU();
else updated = false;
}
void Texture::blit(int x, int y, Texture *source)
{
blit(x, y, source, false);
+1
View File
@@ -82,6 +82,7 @@ public:
void writeAsPNG(const wstring &filename);
void blit(int x, int y, Texture *source);
void blit(int x, int y, Texture *source, bool rotated);
void blitInterpolated(int x, int y, Texture *srcA, Texture *srcB, float t);
void transferFromBuffer(intArray buffer);
void transferFromImage(BufferedImage *image);
int getManagerId();
+27 -4
View File
@@ -15,6 +15,7 @@
#include "LevelRenderer.h"
#include "Options.h"
#include "../Minecraft.World/TallGrass2.h"
#include "../Minecraft.World/FlowerPotTileEntity.h"
bool TileRenderer::fancy = true;
@@ -932,9 +933,6 @@ bool TileRenderer::tesselateFlowerPotInWorld(FlowerPotTile *tt, int x, int y, in
switch (type)
{
case FlowerPotTile::TYPE_FLOWER_RED:
plant = Tile::rose;
break;
case FlowerPotTile::TYPE_FLOWER_YELLOW:
plant = Tile::flower;
break;
@@ -954,7 +952,32 @@ bool TileRenderer::tesselateFlowerPotInWorld(FlowerPotTile *tt, int x, int y, in
}
else
{
if (type == FlowerPotTile::TYPE_CACTUS)
if (type == FlowerPotTile::TYPE_FLOWER_RED)
{
int aux = 0;
shared_ptr<TileEntity> te = level->getTileEntity(x, y, z);
shared_ptr<FlowerPotTileEntity> fpte = te ? std::dynamic_pointer_cast<FlowerPotTileEntity>(te) : nullptr;
if (fpte && fpte->hasFlower())
aux = fpte->getFlowerAuxValue();
tesselateCrossTexture(Tile::rose, aux, x, y, z, 0.75f);
}
else if (type == FlowerPotTile::TYPE_FLOWER_BLUE_ORCHID)
{
tesselateCrossTexture(Tile::rose, Rose::BLUE_ORCHID, x, y, z, 0.75f);
}
else if (type == FlowerPotTile::TYPE_FLOWER_ALLIUM)
{
tesselateCrossTexture(Tile::rose, Rose::ALLIUM, x, y, z, 0.75f);
}
else if (type == FlowerPotTile::TYPE_FLOWER_AZURE_BLUET)
{
tesselateCrossTexture(Tile::rose, Rose::AZURE_BLUET, x, y, z, 0.75f);
}
else if (type == FlowerPotTile::TYPE_FLOWER_OXEYE_DAISY)
{
tesselateCrossTexture(Tile::rose, Rose::OXEYE_DAISY, x, y, z, 0.75f);
}
else if (type == FlowerPotTile::TYPE_CACTUS)
{
// Force drawing of all faces else the cactus misses faces
@@ -1547,6 +1547,8 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
Logger::init();
// 4J-Win64: set CWD to exe dir so asset paths resolve correctly
{
char szExeDir[MAX_PATH] = {};
@@ -1718,6 +1720,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
if( FAILED( InitDevice() ) )
{
CleanupDevice();
Logger::shutdown();
return 0;
}
// Restore fullscreen state from previous session. Route through the
@@ -1747,6 +1750,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}
}
Logger::shutdown();
return (int) msg.wParam;
#endif
@@ -1787,6 +1791,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
if (pMinecraft == nullptr)
{
CleanupDevice();
Logger::shutdown();
return 1;
}
g_bResizeReady = true;
@@ -451,6 +451,8 @@ set(_MINECRAFT_CLIENT_COMMON_NET_MINECRAFT_CLIENT
"${CMAKE_CURRENT_SOURCE_DIR}/KeyMapping.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Lighting.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Lighting.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Logger.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Logger.h"
"${CMAKE_CURRENT_SOURCE_DIR}/MemoryTracker.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MemoryTracker.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.cpp"
+10
View File
@@ -351,6 +351,16 @@ typedef XUID GameSessionUID;
#include "Logger.h"
#ifndef _FINAL_BUILD
#undef OutputDebugString
#undef OutputDebugStringA
#undef OutputDebugStringW
#define OutputDebugStringA(s) Logger::interceptA(s)
#define OutputDebugStringW(s) Logger::interceptW(s)
#define OutputDebugString(s) Logger::interceptW(s)
#endif
#ifdef _FINAL_BUILD
#define printf BREAKTHECOMPILE
#define wprintf BREAKTHECOMPILE
+1
View File
@@ -9,6 +9,7 @@ Abilities::Abilities()
mayfly = false;
instabuild = false;
mayBuild = true;
spectatorMode = false;
flyingSpeed = 0.05f;
walkingSpeed = 0.1f;
+1
View File
@@ -10,6 +10,7 @@ public:
bool mayfly;
bool instabuild;
bool mayBuild;
bool spectatorMode;
private:
float flyingSpeed;
+3 -12
View File
@@ -49,10 +49,7 @@ void Animal::aiStep()
setInLoveValue(getInLoveValue()-1);
if (getInLoveValue() % 10 == 0)
{
double xa = random->nextGaussian() * 0.02;
double ya = random->nextGaussian() * 0.02;
double za = random->nextGaussian() * 0.02;
level->addParticle(eParticleType_heart, x + random->nextFloat() * bbWidth * 2 - bbWidth, y + .5f + random->nextFloat() * bbHeight, z + random->nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za);
level->broadcastEntityEvent(shared_from_this(), EntityEvent::IN_LOVE_HEARTS);
}
}
else
@@ -106,7 +103,7 @@ void Animal::checkHurtTarget(shared_ptr<Entity> target, float d)
loveTime++;
if (loveTime % 4 == 0)
{
level->addParticle(eParticleType_heart, x + random->nextFloat() * bbWidth * 2 - bbWidth, y + .5f + random->nextFloat() * bbHeight, z + random->nextFloat() * bbWidth * 2 - bbWidth, 0, 0, 0);
level->broadcastEntityEvent(shared_from_this(), EntityEvent::IN_LOVE_HEARTS);
}
if (loveTime == 20 * 3) breedWith(a);
@@ -145,13 +142,7 @@ void Animal::breedWith(shared_ptr<Animal> target)
offspring->setAge(-20 * 60 * 20);
offspring->moveTo(x, y, z, yRot, xRot);
offspring->setDespawnProtected();
for (int i = 0; i < 7; i++)
{
double xa = random->nextGaussian() * 0.02;
double ya = random->nextGaussian() * 0.02;
double za = random->nextGaussian() * 0.02;
level->addParticle(eParticleType_heart, x + random->nextFloat() * bbWidth * 2 - bbWidth, y + .5f + random->nextFloat() * bbHeight, z + random->nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za);
}
level->broadcastEntityEvent(shared_from_this(), EntityEvent::IN_LOVE_HEARTS);
level->addEntity(offspring);
level->addEntity(std::make_shared<ExperienceOrb>(level, x, y, z, random->nextInt(4) + 1));
+3 -9
View File
@@ -9,6 +9,7 @@
#include "ExperienceOrb.h"
#include "GenericStats.h"
#include "EntityEvent.h"
BreedGoal::BreedGoal(Animal *animal, double speedModifier)
{
@@ -108,15 +109,8 @@ void BreedGoal::breed()
offspring->setDespawnProtected();
level->addEntity(offspring);
Random *random = animal->getRandom();
for (int i = 0; i < 7; i++)
{
double xa = random->nextGaussian() * 0.02;
double ya = random->nextGaussian() * 0.02;
double za = random->nextGaussian() * 0.02;
level->addParticle(eParticleType_heart, animal->x + random->nextFloat() * animal->bbWidth * 2 - animal->bbWidth, animal->y + .5f + random->nextFloat() * animal->bbHeight, animal->z + random->nextFloat()
* animal->bbWidth * 2 - animal->bbWidth, xa, ya, za);
}
level->broadcastEntityEvent(animal->shared_from_this(), EntityEvent::IN_LOVE_HEARTS);
// 4J-PB - Fix for 106869- Customer Encountered: TU12: Content: Gameplay: Breeding animals does not give any Experience Orbs.
Random *random = animal->getRandom();
level->addEntity(std::make_shared<ExperienceOrb>(level, animal->x, animal->y, animal->z, random->nextInt(7) + 1));
}
+1
View File
@@ -48,6 +48,7 @@ public:
e_ChatDeathDragonBreath,
e_ChatDeathAnvil,
e_ChatDeathFallingBlock,
e_ChatDeathFlyIntoWall,
e_ChatDeathThorns,
e_ChatDeathFellAccidentLadder,
+2
View File
@@ -320,6 +320,7 @@ enum eINSTANCEOF
eTYPE_DAYLIGHTDETECTORTILEENTITY = eTYPE_TILEENTITY | 0x10,
eTYPE_HOPPERTILEENTITY = eTYPE_TILEENTITY | 0x11,
eTYPE_BANNERTILEENTITY = eTYPE_TILEENTITY | 0x12,
eTYPE_FLOWERPOTTILEENTITY = eTYPE_TILEENTITY | 0x13,
eTYPE_DISPENSERTILEENTITY = eTYPE_TILEENTITY | BIT_DISPENSERTILEENTITY,
eTYPE_DROPPERTILEENTITY = eTYPE_DISPENSERTILEENTITY | 0x1,
@@ -548,6 +549,7 @@ public:
classes->push_back( SUBCLASS(eTYPE_DAYLIGHTDETECTORTILEENTITY )->addParent( eTYPE_TILEENTITY ) );
classes->push_back( SUBCLASS(eTYPE_HOPPERTILEENTITY )->addParent( eTYPE_TILEENTITY ) );
classes->push_back( SUBCLASS(eTYPE_BANNERTILEENTITY )->addParent( eTYPE_TILEENTITY ) );
classes->push_back( SUBCLASS(eTYPE_FLOWERPOTTILEENTITY )->addParent( eTYPE_TILEENTITY ) );
classes->push_back( SUBCLASS(eTYPE_DISPENSERTILEENTITY )->addParent( eTYPE_TILEENTITY ) );
classes->push_back( SUBCLASS(eTYPE_DROPPERTILEENTITY )->addParent( eTYPE_DISPENSERTILEENTITY ) );
+9
View File
@@ -569,6 +569,15 @@ void CustomLevelSource::postProcess(ChunkSource *parent, int xt, int zt)
}
PIXEndNamedEvent();
if (true)
{
int fx = xo + pprandom->nextInt(16) + 8;
int fy = 40 + pprandom->nextInt(10);
int fz = zo + pprandom->nextInt(16) + 8;
FossilFeature fossil;
fossil.place(level, pprandom, fx, fy, fz);
}
PIXBeginNamedEvent(0,"Biome decorate");
biome->decorate(level, pprandom, xo, zo);
PIXEndNamedEvent();
+1
View File
@@ -22,6 +22,7 @@ DamageSource *DamageSource::dragonbreath = (new DamageSource(ChatPacket::e_ChatD
DamageSource *DamageSource::wither = (new DamageSource(ChatPacket::e_ChatDeathWither))->bypassArmor();
DamageSource *DamageSource::anvil = (new DamageSource(ChatPacket::e_ChatDeathAnvil));
DamageSource *DamageSource::fallingBlock = (new DamageSource(ChatPacket::e_ChatDeathFallingBlock));
DamageSource *DamageSource::flyIntoWall = new DamageSource(ChatPacket::e_ChatDeathFlyIntoWall);
DamageSource *DamageSource::mobAttack(shared_ptr<LivingEntity> mob)
{
+1
View File
@@ -29,6 +29,7 @@ public:
static DamageSource *wither;
static DamageSource *anvil;
static DamageSource *fallingBlock;
static DamageSource *flyIntoWall;
static DamageSource *mobAttack(shared_ptr<LivingEntity> mob);
static DamageSource *playerAttack(shared_ptr<Player> player);
+13 -3
View File
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "net.minecraft.world.entity.h"
#include "net.minecraft.world.entity.player.h"
#include "net.minecraft.world.entity.item.h"
#include "net.minecraft.world.item.enchantment.h"
#include "net.minecraft.world.level.h"
@@ -146,9 +147,18 @@ void Explosion::explode()
if(canDamage) e->hurt(DamageSource::explosion(this), static_cast<int>((pow * pow + pow) / 2 * 8 * r + 1));
double kbPower = ProtectionEnchantment::getExplosionKnockbackAfterDampener(e, pow);
e->xd += xa *kbPower;
e->yd += ya *kbPower;
e->zd += za *kbPower;
bool isCreativeFlying = false;
if (e->instanceof(eTYPE_PLAYER))
{
shared_ptr<Player> p = dynamic_pointer_cast<Player>(e);
if (p && p->abilities.flying) isCreativeFlying = true;
}
if (!isCreativeFlying)
{
e->xd += xa * kbPower;
e->yd += ya * kbPower;
e->zd += za * kbPower;
}
if (e->instanceof(eTYPE_PLAYER))
+19
View File
@@ -19,6 +19,25 @@ FireworksItem::FireworksItem(int id) : Item(id)
{
}
shared_ptr<ItemInstance> FireworksItem::use(shared_ptr<ItemInstance> instance, Level *level, shared_ptr<Player> player)
{
if (player->isElytraFlying() && player->m_elytraRocketCooldown == 0)
{
player->m_elytraRocketCooldown = 20;
player->startFireworkBoost(instance);
player->playSound(eSoundType_FIREWORKS_LAUNCH, 3.0f, 1.0f);
if (!level->isClientSide)
{
shared_ptr<FireworksRocketEntity> rocket(new FireworksRocketEntity(level, player->x, player->y, player->z, instance));
level->addEntity(rocket);
if (!player->abilities.instabuild)
instance->count--;
}
return instance;
}
return instance;
}
bool FireworksItem::useOn(shared_ptr<ItemInstance> instance, shared_ptr<Player> player, Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, bool bTestUseOnOnly)
{
// 4J-JEV: Fix for xb1 #173493 - CU7: Content: UI: Missing tooltip for Firework Rocket.
+1
View File
@@ -27,5 +27,6 @@ public:
FireworksItem(int id);
bool useOn(shared_ptr<ItemInstance> instance, shared_ptr<Player> player, Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, bool bTestUseOnOnly=false);
virtual shared_ptr<ItemInstance> use(shared_ptr<ItemInstance> instance, Level *level, shared_ptr<Player> player);
void appendHoverText(shared_ptr<ItemInstance> itemInstance, shared_ptr<Player> player, vector<HtmlString> *lines, bool advanced);
};
+54 -26
View File
@@ -4,14 +4,20 @@
#include "net.minecraft.world.level.h"
#include "net.minecraft.world.level.tile.h"
#include "FlowerPotTile.h"
#include "FlowerPotTileEntity.h"
FlowerPotTile::FlowerPotTile(int id) : Tile(id, Material::decoration, isSolidRender() )
FlowerPotTile::FlowerPotTile(int id) : BaseEntityTile(id, Material::decoration, isSolidRender())
{
setLightBlock(0);
updateDefaultShape();
sendTileData();
}
shared_ptr<TileEntity> FlowerPotTile::newTileEntity(Level *level)
{
return std::make_shared<FlowerPotTileEntity>();
}
void FlowerPotTile::createBlockStateDefinition()
{
if (!m_blockStateDefinition)
@@ -71,6 +77,15 @@ bool FlowerPotTile::use(Level *level, int x, int y, int z, shared_ptr<Player> pl
{
level->setData(x, y, z, type, Tile::UPDATE_CLIENTS);
shared_ptr<TileEntity> teBase = level->getTileEntity(x, y, z);
shared_ptr<FlowerPotTileEntity> te = teBase ? std::dynamic_pointer_cast<FlowerPotTileEntity>(teBase) : nullptr;
if (te == nullptr)
{
te = std::make_shared<FlowerPotTileEntity>();
level->setTileEntity(x, y, z, te);
}
te->setFlowerItem(item->getItem()->id, item->getAuxValue());
if (!player->abilities.instabuild)
{
if (--item->count <= 0)
@@ -87,30 +102,24 @@ bool FlowerPotTile::use(Level *level, int x, int y, int z, shared_ptr<Player> pl
int FlowerPotTile::cloneTileId(Level *level, int x, int y, int z)
{
shared_ptr<ItemInstance> item = getItemFromType(level->getData(x, y, z));
shared_ptr<TileEntity> te = level->getTileEntity(x, y, z);
shared_ptr<FlowerPotTileEntity> fpte = te ? std::dynamic_pointer_cast<FlowerPotTileEntity>(te) : nullptr;
if (fpte && fpte->hasFlower())
return fpte->getFlowerItemId();
if (item == nullptr)
{
return Item::flower_pot_Id;
}
else
{
return item->id;
}
shared_ptr<ItemInstance> item = getItemFromType(level->getData(x, y, z));
return item ? item->id : Item::flower_pot_Id;
}
int FlowerPotTile::cloneTileData(Level *level, int x, int y, int z)
{
shared_ptr<ItemInstance> item = getItemFromType(level->getData(x, y, z));
shared_ptr<TileEntity> te = level->getTileEntity(x, y, z);
shared_ptr<FlowerPotTileEntity> fpte = te ? std::dynamic_pointer_cast<FlowerPotTileEntity>(te) : nullptr;
if (fpte && fpte->hasFlower())
return fpte->getFlowerAuxValue();
if (item == nullptr)
{
return Item::flower_pot_Id;
}
else
{
return item->getAuxValue();
}
shared_ptr<ItemInstance> item = getItemFromType(level->getData(x, y, z));
return item ? item->getAuxValue() : 0;
}
bool FlowerPotTile::useOwnCloneData()
@@ -133,15 +142,26 @@ void FlowerPotTile::neighborChanged(Level *level, int x, int y, int z, int type)
}
}
void FlowerPotTile::onRemove(Level *level, int x, int y, int z, int id, int data)
{
if (data > 0)
{
shared_ptr<TileEntity> te = level->getTileEntity(x, y, z);
shared_ptr<FlowerPotTileEntity> fpte = te ? std::dynamic_pointer_cast<FlowerPotTileEntity>(te) : nullptr;
shared_ptr<ItemInstance> item;
if (fpte && fpte->hasFlower())
item = std::make_shared<ItemInstance>(fpte->getFlowerItemId(), 1, fpte->getFlowerAuxValue());
else
item = getItemFromType(data);
if (item != nullptr)
popResource(level, x, y, z, item);
}
BaseEntityTile::onRemove(level, x, y, z, id, data);
}
void FlowerPotTile::spawnResources(Level *level, int x, int y, int z, int data, float odds, int playerBonusLevel)
{
Tile::spawnResources(level, x, y, z, data, odds, playerBonusLevel);
if (data > 0)
{
shared_ptr<ItemInstance> item = getItemFromType(data);
if (item != nullptr) popResource(level, x, y, z, item);
}
}
int FlowerPotTile::getResource(int data, Random *random, int playerBonusLevel)
@@ -154,7 +174,15 @@ shared_ptr<ItemInstance> FlowerPotTile::getItemFromType(int type)
switch (type)
{
case TYPE_FLOWER_RED:
return std::make_shared<ItemInstance>(Tile::rose);
return std::make_shared<ItemInstance>(Tile::rose, 1, 0);
case TYPE_FLOWER_BLUE_ORCHID:
return std::make_shared<ItemInstance>(Tile::rose, 1, Rose::BLUE_ORCHID);
case TYPE_FLOWER_ALLIUM:
return std::make_shared<ItemInstance>(Tile::rose, 1, Rose::ALLIUM);
case TYPE_FLOWER_AZURE_BLUET:
return std::make_shared<ItemInstance>(Tile::rose, 1, Rose::AZURE_BLUET);
case TYPE_FLOWER_OXEYE_DAISY:
return std::make_shared<ItemInstance>(Tile::rose, 1, Rose::OXEYE_DAISY);
case TYPE_FLOWER_YELLOW:
return std::make_shared<ItemInstance>(Tile::flower);
case TYPE_CACTUS:
+8 -2
View File
@@ -1,8 +1,8 @@
#pragma once
#include "Tile.h"
#include "BaseEntityTile.h"
class FlowerPotTile : public Tile
class FlowerPotTile : public BaseEntityTile
{
public:
static const int TYPE_FLOWER_RED = 1;
@@ -16,8 +16,13 @@ public:
static const int TYPE_CACTUS = 9;
static const int TYPE_DEAD_BUSH = 10;
static const int TYPE_FERN = 11;
static const int TYPE_FLOWER_BLUE_ORCHID = 12;
static const int TYPE_FLOWER_ALLIUM = 13;
static const int TYPE_FLOWER_AZURE_BLUET = 14;
static const int TYPE_FLOWER_OXEYE_DAISY = 15;
FlowerPotTile(int id);
shared_ptr<TileEntity> newTileEntity(Level *level);
virtual void createBlockStateDefinition() override;
virtual int defaultBlockState() override;
virtual int convertBlockStateToLegacyData(BlockState *state) override;
@@ -34,6 +39,7 @@ public:
bool useOwnCloneData();
bool mayPlace(Level *level, int x, int y, int z);
void neighborChanged(Level *level, int x, int y, int z, int type);
void onRemove(Level *level, int x, int y, int z, int id, int data);
using Tile::spawnResources;
void spawnResources(Level *level, int x, int y, int z, int data, float odds, int playerBonusLevel);
int getResource(int data, Random *random, int playerBonusLevel);
+60
View File
@@ -0,0 +1,60 @@
#include "stdafx.h"
#include "com.mojang.nbt.h"
#include "net.minecraft.network.packet.h"
#include "FlowerPotTileEntity.h"
#include "TileEntityDataPacket.h"
FlowerPotTileEntity::FlowerPotTileEntity() : flowerItemId(-1), flowerAuxValue(0)
{
}
void FlowerPotTileEntity::setFlowerItem(int itemId, int auxValue)
{
flowerItemId = itemId;
flowerAuxValue = auxValue;
}
int FlowerPotTileEntity::getFlowerItemId() const
{
return flowerItemId;
}
int FlowerPotTileEntity::getFlowerAuxValue() const
{
return flowerAuxValue;
}
bool FlowerPotTileEntity::hasFlower() const
{
return flowerItemId >= 0;
}
void FlowerPotTileEntity::save(CompoundTag *tag)
{
TileEntity::save(tag);
tag->putInt(L"Item", flowerItemId);
tag->putInt(L"Data", flowerAuxValue);
}
void FlowerPotTileEntity::load(CompoundTag *tag)
{
TileEntity::load(tag);
flowerItemId = tag->getInt(L"Item");
flowerAuxValue = tag->getInt(L"Data");
}
shared_ptr<Packet> FlowerPotTileEntity::getUpdatePacket()
{
CompoundTag *tag = new CompoundTag();
save(tag);
return std::make_shared<TileEntityDataPacket>(x, y, z, TileEntityDataPacket::TYPE_FLOWER_POT, tag);
}
shared_ptr<TileEntity> FlowerPotTileEntity::clone()
{
shared_ptr<FlowerPotTileEntity> e = std::make_shared<FlowerPotTileEntity>();
TileEntity::clone(e);
e->flowerItemId = flowerItemId;
e->flowerAuxValue = flowerAuxValue;
return e;
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include "TileEntity.h"
class FlowerPotTileEntity : public TileEntity
{
public:
eINSTANCEOF GetType() { return eTYPE_FLOWERPOTTILEENTITY; }
static TileEntity *create() { return new FlowerPotTileEntity(); }
private:
int flowerItemId;
int flowerAuxValue;
public:
FlowerPotTileEntity();
void setFlowerItem(int itemId, int auxValue);
int getFlowerItemId() const;
int getFlowerAuxValue() const;
bool hasFlower() const;
void save(CompoundTag *tag);
void load(CompoundTag *tag);
shared_ptr<Packet> getUpdatePacket();
virtual shared_ptr<TileEntity> clone();
};
+1 -1
View File
@@ -25,7 +25,7 @@ const float FoodConstants::FOOD_SATURATION_MAX = 1.0f;
const float FoodConstants::FOOD_SATURATION_SUPERNATURAL = 1.2f;
// some exhaustion guidelines
const float FoodConstants::EXHAUSTION_HEAL = 3.0f;
const float FoodConstants::EXHAUSTION_HEAL = 4.0f;
const float FoodConstants::EXHAUSTION_JUMP = .2f;
const float FoodConstants::EXHAUSTION_SPRINT_JUMP = FoodConstants::EXHAUSTION_JUMP * 4;
const float FoodConstants::EXHAUSTION_MINE = .025f;
+2 -1
View File
@@ -68,7 +68,8 @@ void FoodData::tick(shared_ptr<Player> player)
else if (player->level->getGameRules()->getBoolean(GameRules::RULE_NATURAL_REGENERATION) && foodLevel >= FoodConstants::HEAL_LEVEL && player->isHurt())
{
tickTimer++;
if (tickTimer >= FoodConstants::HEALTH_TICK_COUNT)
int threshold = (saturationLevel > 0.0f) ? 10 : FoodConstants::HEALTH_TICK_COUNT;
if (tickTimer >= threshold)
{
player->heal(1);
addExhaustion(FoodConstants::EXHAUSTION_HEAL);
+235
View File
@@ -0,0 +1,235 @@
#include "stdafx.h"
#include "net.minecraft.world.level.h"
#include "net.minecraft.world.level.tile.h"
#include "RotatedPillarTile.h"
#include "FossilFeature.h"
struct FossilBlock
{
signed char x, y, z;
signed char data;
};
struct FossilStructure
{
int width, height, length;
const FossilBlock *blocks;
int blockCount;
};
static const int AXIS_Y = RotatedPillarTile::FACING_Y;
static const int AXIS_X = RotatedPillarTile::FACING_X;
static const int AXIS_Z = RotatedPillarTile::FACING_Z;
static const int COAL = -1;
static const FossilBlock skull01[] = {
{1,1,0,AXIS_Y},{4,1,0,AXIS_Y},{1,2,0,AXIS_Y},{2,2,0,AXIS_Y},{3,2,0,AXIS_Y},{4,2,0,AXIS_Y},
{2,3,0,AXIS_X},{3,3,0,AXIS_X},
{1,0,1,AXIS_X},{2,0,1,AXIS_X},{3,0,1,AXIS_X},{4,0,1,AXIS_X},
{0,1,1,AXIS_Y},{5,1,1,AXIS_Y},{0,2,1,AXIS_Y},{5,2,1,AXIS_Y},{0,3,1,AXIS_Y},{5,3,1,AXIS_Y},
{1,4,1,AXIS_X},{2,4,1,AXIS_X},{3,4,1,AXIS_X},{4,4,1,AXIS_X},
{1,0,2,AXIS_X},{2,0,2,AXIS_X},{3,0,2,AXIS_X},{4,0,2,AXIS_X},
{0,1,2,AXIS_Z},{5,1,2,AXIS_Z},{0,2,2,AXIS_Z},{5,2,2,AXIS_Z},{0,3,2,AXIS_Z},{5,3,2,AXIS_Z},
{1,4,2,AXIS_X},{2,4,2,AXIS_X},{3,4,2,AXIS_X},{4,4,2,AXIS_X},
{1,0,3,AXIS_X},{2,0,3,AXIS_X},{3,0,3,AXIS_X},{4,0,3,AXIS_X},
{0,1,3,AXIS_Z},{5,1,3,AXIS_Z},{0,2,3,AXIS_Z},{5,2,3,AXIS_Z},{0,3,3,AXIS_Z},{5,3,3,AXIS_Z},
{1,4,3,AXIS_X},{2,4,3,AXIS_X},{3,4,3,AXIS_X},{4,4,3,AXIS_X},
{1,0,4,AXIS_X},{4,0,4,AXIS_X},
{0,1,4,AXIS_Z},{5,1,4,AXIS_Z},{0,2,4,AXIS_Z},{5,2,4,AXIS_Z},{0,3,4,AXIS_Z},{5,3,4,AXIS_Z},
{1,4,4,AXIS_X},{2,4,4,AXIS_X},{3,4,4,AXIS_X},{4,4,4,AXIS_X},
{1,0,5,AXIS_X},{4,0,5,AXIS_X},
{0,1,5,AXIS_Y},{5,1,5,AXIS_Y},{0,2,5,AXIS_Y},{5,2,5,AXIS_Y},{0,3,5,AXIS_Y},{5,3,5,AXIS_Y},
{1,4,5,AXIS_X},{2,4,5,AXIS_X},{3,4,5,AXIS_X},{4,4,5,AXIS_X},
{1,1,6,AXIS_Y},{2,1,6,AXIS_X},{3,1,6,AXIS_X},{4,1,6,AXIS_Y},
{1,2,6,AXIS_Y},{2,2,6,AXIS_X},{3,2,6,AXIS_X},{4,2,6,AXIS_Y},
{1,3,6,AXIS_Y},{2,3,6,AXIS_X},{3,3,6,AXIS_X},{4,3,6,AXIS_Y},
};
static const FossilBlock skull02[] = {
{1,1,0,AXIS_Y},{5,1,0,AXIS_Y},{1,2,0,AXIS_Y},{2,2,0,AXIS_X},{3,2,0,AXIS_X},{4,2,0,AXIS_X},{5,2,0,AXIS_Y},
{1,3,0,AXIS_Y},{3,3,0,AXIS_Y},{5,3,0,AXIS_Y},{2,4,0,AXIS_X},{4,4,0,AXIS_X},
{1,0,1,AXIS_X},{2,0,1,AXIS_X},{3,0,1,AXIS_X},{4,0,1,AXIS_X},{5,0,1,AXIS_X},
{0,1,1,AXIS_Y},{6,1,1,AXIS_Y},{0,2,1,AXIS_Y},{6,2,1,AXIS_Y},{0,3,1,AXIS_Y},{6,3,1,AXIS_Y},
{1,4,1,AXIS_X},{2,4,1,AXIS_X},{3,4,1,AXIS_X},{4,4,1,AXIS_X},{5,4,1,AXIS_X},
{1,0,2,AXIS_X},{2,0,2,AXIS_X},{3,0,2,AXIS_X},{4,0,2,AXIS_X},{5,0,2,AXIS_X},
{0,1,2,AXIS_Z},{6,1,2,AXIS_Z},{0,2,2,AXIS_Z},{6,2,2,AXIS_Z},{0,3,2,AXIS_Z},{6,3,2,AXIS_Z},
{1,4,2,AXIS_X},{2,4,2,AXIS_X},{3,4,2,AXIS_X},{4,4,2,AXIS_X},{5,4,2,AXIS_X},
{1,0,3,AXIS_X},{2,0,3,AXIS_X},{3,0,3,AXIS_X},{4,0,3,AXIS_X},{5,0,3,AXIS_X},
{0,1,3,AXIS_Y},{6,1,3,AXIS_Y},{0,2,3,AXIS_Y},{6,2,3,AXIS_Y},{0,3,3,AXIS_Y},{6,3,3,AXIS_Y},
{1,4,3,AXIS_X},{2,4,3,AXIS_X},{3,4,3,AXIS_X},{4,4,3,AXIS_X},{5,4,3,AXIS_X},
{1,1,4,AXIS_Y},{2,1,4,AXIS_X},{3,1,4,AXIS_X},{4,1,4,AXIS_X},{5,1,4,AXIS_Y},
{1,2,4,AXIS_Y},{2,2,4,AXIS_X},{3,2,4,AXIS_X},{4,2,4,AXIS_X},{5,2,4,AXIS_Y},
{1,3,4,AXIS_Y},{2,3,4,AXIS_X},{3,3,4,AXIS_X},{4,3,4,AXIS_X},{5,3,4,AXIS_Y},
};
static const FossilBlock skull03[] = {
{0,0,0,AXIS_Y},{4,0,0,AXIS_Y},
{0,1,0,AXIS_Y},{1,1,0,AXIS_X},{2,1,0,AXIS_X},{3,1,0,AXIS_X},{4,1,0,AXIS_Y},
{0,2,0,AXIS_Y},{2,2,0,AXIS_Y},{4,2,0,AXIS_Y},
{0,3,0,AXIS_X},{1,3,0,AXIS_X},{2,3,0,AXIS_X},{3,3,0,AXIS_X},{4,3,0,AXIS_X},
{1,0,1,AXIS_X},{2,0,1,AXIS_X},{3,0,1,AXIS_X},
{0,1,1,AXIS_Z},{4,1,1,AXIS_Z},{0,2,1,AXIS_Z},{4,2,1,AXIS_Z},
{1,3,1,AXIS_X},{2,3,1,AXIS_X},{3,3,1,AXIS_X},
{1,0,2,AXIS_X},{2,0,2,AXIS_X},{3,0,2,AXIS_X},
{0,1,2,AXIS_Z},{4,1,2,AXIS_Z},{0,2,2,AXIS_Z},{4,2,2,AXIS_Z},
{1,3,2,AXIS_X},{2,3,2,AXIS_X},{3,3,2,AXIS_X},
{1,0,3,AXIS_X},{2,0,3,AXIS_X},{3,0,3,AXIS_X},
{0,1,3,AXIS_Z},{4,1,3,AXIS_Z},{0,2,3,AXIS_Z},{4,2,3,AXIS_Z},
{1,3,3,AXIS_X},{2,3,3,AXIS_X},{3,3,3,AXIS_X},
{1,0,4,AXIS_X},{2,0,4,AXIS_X},{3,0,4,AXIS_X},
{0,1,4,AXIS_Y},{1,1,4,AXIS_X},{2,1,4,AXIS_X},{3,1,4,AXIS_X},{4,1,4,AXIS_Y},
{0,2,4,AXIS_Y},{1,2,4,AXIS_X},{2,2,4,AXIS_X},{3,2,4,AXIS_X},{4,2,4,AXIS_Y},
};
static const FossilBlock skull04[] = {
{0,0,0,AXIS_Y},{3,0,0,AXIS_Y},
{0,1,0,AXIS_Y},{1,1,0,AXIS_X},{2,1,0,AXIS_X},{3,1,0,AXIS_Y},
{0,2,0,AXIS_Y},{3,2,0,AXIS_Y},
{0,3,0,AXIS_X},{1,3,0,AXIS_X},{2,3,0,AXIS_X},{3,3,0,AXIS_X},
{1,0,1,AXIS_X},{2,0,1,AXIS_X},
{0,1,1,AXIS_Y},{3,1,1,AXIS_Y},{0,2,1,AXIS_Y},{3,2,1,AXIS_Y},
{1,3,1,AXIS_X},{2,3,1,AXIS_X},
{1,0,2,AXIS_X},{2,0,2,AXIS_X},
{0,1,2,AXIS_Y},{3,1,2,AXIS_Y},{0,2,2,AXIS_Y},{3,2,2,AXIS_Y},
{1,3,2,AXIS_X},{2,3,2,AXIS_X},
{1,1,3,AXIS_Y},{2,1,3,AXIS_Y},{1,2,3,AXIS_Y},{2,2,3,AXIS_Y},
};
static const FossilBlock spine01[] = {
{1,2,0,AXIS_Z},
{0,0,1,AXIS_Y},{2,0,1,AXIS_Y},{0,1,1,AXIS_Y},{2,1,1,AXIS_Y},{1,2,1,AXIS_Z},
{1,2,2,AXIS_Z},
{0,0,3,AXIS_Y},{2,0,3,AXIS_Y},{0,1,3,AXIS_Y},{2,1,3,AXIS_Y},{1,2,3,AXIS_Z},
{1,2,4,AXIS_Z},
{0,0,5,AXIS_Y},{2,0,5,AXIS_Y},{0,1,5,AXIS_Y},{2,1,5,AXIS_Y},{1,2,5,AXIS_Z},
{1,2,6,AXIS_Z},
{0,0,7,AXIS_Y},{2,0,7,AXIS_Y},{0,1,7,AXIS_Y},{2,1,7,AXIS_Y},{1,2,7,AXIS_Z},
{1,2,8,AXIS_Z},
{0,0,9,AXIS_Y},{2,0,9,AXIS_Y},{0,1,9,AXIS_Y},{2,1,9,AXIS_Y},{1,2,9,AXIS_Z},
{1,2,10,AXIS_Z},
{0,0,11,AXIS_Y},{2,0,11,AXIS_Y},{0,1,11,AXIS_Y},{2,1,11,AXIS_Y},{1,2,11,AXIS_Z},
{1,2,12,AXIS_Z},
};
static const FossilBlock spine02[] = {
{2,3,0,AXIS_Z},
{1,0,1,AXIS_X},{3,0,1,AXIS_X},{0,1,1,AXIS_Y},{4,1,1,AXIS_Y},{0,2,1,AXIS_Y},{4,2,1,AXIS_Y},
{1,3,1,AXIS_X},{2,3,1,AXIS_Z},{3,3,1,AXIS_X},
{2,3,2,AXIS_Z},
{1,0,3,AXIS_X},{3,0,3,AXIS_X},{0,1,3,AXIS_Y},{4,1,3,AXIS_Y},{0,2,3,AXIS_Y},{4,2,3,AXIS_Y},
{1,3,3,AXIS_X},{2,3,3,AXIS_Z},{3,3,3,AXIS_X},
{2,3,4,AXIS_Z},
{1,0,5,AXIS_X},{3,0,5,AXIS_X},{0,1,5,AXIS_Y},{4,1,5,AXIS_Y},{0,2,5,AXIS_Y},{4,2,5,AXIS_Y},
{1,3,5,AXIS_X},{2,3,5,AXIS_Z},{3,3,5,AXIS_X},
{2,3,6,AXIS_Z},
{1,0,7,AXIS_X},{3,0,7,AXIS_X},{0,1,7,AXIS_Y},{4,1,7,AXIS_Y},{0,2,7,AXIS_Y},{4,2,7,AXIS_Y},
{1,3,7,AXIS_X},{2,3,7,AXIS_Z},{3,3,7,AXIS_X},
{2,3,8,AXIS_Z},
{1,0,9,AXIS_X},{3,0,9,AXIS_X},{0,1,9,AXIS_Y},{4,1,9,AXIS_Y},{0,2,9,AXIS_Y},{4,2,9,AXIS_Y},
{1,3,9,AXIS_X},{2,3,9,AXIS_Z},{3,3,9,AXIS_X},
{2,3,10,AXIS_Z},
{1,0,11,AXIS_X},{3,0,11,AXIS_X},{0,1,11,AXIS_Y},{4,1,11,AXIS_Y},{0,2,11,AXIS_Y},{4,2,11,AXIS_Y},
{1,3,11,AXIS_X},{2,3,11,AXIS_Z},{3,3,11,AXIS_X},
{2,3,12,AXIS_Z},
};
static const FossilBlock spine03[] = {
{3,3,0,AXIS_Z},
{0,0,1,AXIS_Y},{1,0,1,AXIS_X},{5,0,1,AXIS_X},{6,0,1,AXIS_Y},
{0,1,1,AXIS_Y},{6,1,1,AXIS_Y},{0,2,1,AXIS_Y},{6,2,1,AXIS_Y},
{0,3,1,AXIS_X},{1,3,1,AXIS_X},{2,3,1,AXIS_X},{3,3,1,AXIS_Z},{4,3,1,AXIS_X},{5,3,1,AXIS_X},{6,3,1,AXIS_X},
{3,3,2,AXIS_Z},
{0,0,3,AXIS_Y},{1,0,3,AXIS_X},{5,0,3,AXIS_X},{6,0,3,AXIS_Y},
{0,1,3,AXIS_Y},{6,1,3,AXIS_Y},{0,2,3,AXIS_Y},{6,2,3,AXIS_Y},
{0,3,3,AXIS_X},{1,3,3,AXIS_X},{2,3,3,AXIS_X},{3,3,3,AXIS_Z},{4,3,3,AXIS_X},{5,3,3,AXIS_X},{6,3,3,AXIS_X},
{3,3,4,AXIS_Z},
{0,0,5,AXIS_Y},{1,0,5,AXIS_X},{5,0,5,AXIS_X},{6,0,5,AXIS_Y},
{0,1,5,AXIS_Y},{6,1,5,AXIS_Y},{0,2,5,AXIS_Y},{6,2,5,AXIS_Y},
{0,3,5,AXIS_X},{1,3,5,AXIS_X},{2,3,5,AXIS_X},{3,3,5,AXIS_Z},{4,3,5,AXIS_X},{5,3,5,AXIS_X},{6,3,5,AXIS_X},
{3,3,6,AXIS_Z},
{0,0,7,AXIS_Y},{1,0,7,AXIS_X},{5,0,7,AXIS_X},{6,0,7,AXIS_Y},
{0,1,7,AXIS_Y},{6,1,7,AXIS_Y},{0,2,7,AXIS_Y},{6,2,7,AXIS_Y},
{0,3,7,AXIS_X},{1,3,7,AXIS_X},{2,3,7,AXIS_X},{3,3,7,AXIS_Z},{4,3,7,AXIS_X},{5,3,7,AXIS_X},{6,3,7,AXIS_X},
{3,3,8,AXIS_Z},
{0,0,9,AXIS_Y},{1,0,9,AXIS_X},{5,0,9,AXIS_X},{6,0,9,AXIS_Y},
{0,1,9,AXIS_Y},{6,1,9,AXIS_Y},{0,2,9,AXIS_Y},{6,2,9,AXIS_Y},
{0,3,9,AXIS_X},{1,3,9,AXIS_X},{2,3,9,AXIS_X},{3,3,9,AXIS_Z},{4,3,9,AXIS_X},{5,3,9,AXIS_X},{6,3,9,AXIS_X},
{3,3,10,AXIS_Z},
{0,0,11,AXIS_Y},{1,0,11,AXIS_X},{5,0,11,AXIS_X},{6,0,11,AXIS_Y},
{0,1,11,AXIS_Y},{6,1,11,AXIS_Y},{0,2,11,AXIS_Y},{6,2,11,AXIS_Y},
{0,3,11,AXIS_X},{1,3,11,AXIS_X},{2,3,11,AXIS_X},{3,3,11,AXIS_Z},{4,3,11,AXIS_X},{5,3,11,AXIS_X},{6,3,11,AXIS_X},
{3,3,12,AXIS_Z},
};
static const FossilBlock spine04[] = {
{4,4,0,AXIS_Z},
{1,0,1,AXIS_X},{2,0,1,AXIS_X},{6,0,1,AXIS_X},{7,0,1,AXIS_X},
{0,1,1,AXIS_Y},{8,1,1,AXIS_Y},{0,2,1,AXIS_Y},{8,2,1,AXIS_Y},{0,3,1,AXIS_Y},{8,3,1,AXIS_Y},
{0,4,1,AXIS_X},{1,4,1,AXIS_X},{2,4,1,AXIS_X},{3,4,1,AXIS_X},{4,4,1,AXIS_Z},{5,4,1,AXIS_X},{6,4,1,AXIS_X},{7,4,1,AXIS_X},{8,4,1,AXIS_X},
{4,4,2,AXIS_Z},
{1,0,3,AXIS_X},{2,0,3,AXIS_X},{6,0,3,AXIS_X},{7,0,3,AXIS_X},
{0,1,3,AXIS_Y},{8,1,3,AXIS_Y},{0,2,3,AXIS_Y},{8,2,3,AXIS_Y},{0,3,3,AXIS_Y},{8,3,3,AXIS_Y},
{0,4,3,AXIS_X},{1,4,3,AXIS_X},{2,4,3,AXIS_X},{3,4,3,AXIS_X},{4,4,3,AXIS_Z},{5,4,3,AXIS_X},{6,4,3,AXIS_X},{7,4,3,AXIS_X},{8,4,3,AXIS_X},
{4,4,4,AXIS_Z},
{1,0,5,AXIS_X},{2,0,5,AXIS_X},{6,0,5,AXIS_X},{7,0,5,AXIS_X},
{0,1,5,AXIS_Y},{8,1,5,AXIS_Y},{0,2,5,AXIS_Y},{8,2,5,AXIS_Y},{0,3,5,AXIS_Y},{8,3,5,AXIS_Y},
{0,4,5,AXIS_X},{1,4,5,AXIS_X},{2,4,5,AXIS_X},{3,4,5,AXIS_X},{4,4,5,AXIS_Z},{5,4,5,AXIS_X},{6,4,5,AXIS_X},{7,4,5,AXIS_X},{8,4,5,AXIS_X},
{4,4,6,AXIS_Z},
{1,0,7,AXIS_X},{2,0,7,AXIS_X},{6,0,7,AXIS_X},{7,0,7,AXIS_X},
{0,1,7,AXIS_Y},{8,1,7,AXIS_Y},{0,2,7,AXIS_Y},{8,2,7,AXIS_Y},{0,3,7,AXIS_Y},{8,3,7,AXIS_Y},
{0,4,7,AXIS_X},{1,4,7,AXIS_X},{2,4,7,AXIS_X},{3,4,7,AXIS_X},{4,4,7,AXIS_Z},{5,4,7,AXIS_X},{6,4,7,AXIS_X},{7,4,7,AXIS_X},{8,4,7,AXIS_X},
{4,4,8,AXIS_Z},
{1,0,9,AXIS_X},{2,0,9,AXIS_X},{6,0,9,AXIS_X},{7,0,9,AXIS_X},
{0,1,9,AXIS_Y},{8,1,9,AXIS_Y},{0,2,9,AXIS_Y},{8,2,9,AXIS_Y},{0,3,9,AXIS_Y},{8,3,9,AXIS_Y},
{0,4,9,AXIS_X},{1,4,9,AXIS_X},{2,4,9,AXIS_X},{3,4,9,AXIS_X},{4,4,9,AXIS_Z},{5,4,9,AXIS_X},{6,4,9,AXIS_X},{7,4,9,AXIS_X},{8,4,9,AXIS_X},
{4,4,10,AXIS_Z},
{1,0,11,AXIS_X},{2,0,11,AXIS_X},{6,0,11,AXIS_X},{7,0,11,AXIS_X},
{0,1,11,AXIS_Y},{8,1,11,AXIS_Y},{0,2,11,AXIS_Y},{8,2,11,AXIS_Y},{0,3,11,AXIS_Y},{8,3,11,AXIS_Y},
{0,4,11,AXIS_X},{1,4,11,AXIS_X},{2,4,11,AXIS_X},{3,4,11,AXIS_X},{4,4,11,AXIS_Z},{5,4,11,AXIS_X},{6,4,11,AXIS_X},{7,4,11,AXIS_X},{8,4,11,AXIS_X},
{4,4,12,AXIS_Z},
};
static const FossilStructure skullStructures[4] = {
{6, 5, 7, skull01, (int)(sizeof(skull01)/sizeof(skull01[0]))},
{7, 5, 5, skull02, (int)(sizeof(skull02)/sizeof(skull02[0]))},
{5, 4, 5, skull03, (int)(sizeof(skull03)/sizeof(skull03[0]))},
{4, 4, 4, skull04, (int)(sizeof(skull04)/sizeof(skull04[0]))},
};
static const FossilStructure spineStructures[4] = {
{3, 3, 13, spine01, (int)(sizeof(spine01)/sizeof(spine01[0]))},
{5, 4, 13, spine02, (int)(sizeof(spine02)/sizeof(spine02[0]))},
{7, 4, 13, spine03, (int)(sizeof(spine03)/sizeof(spine03[0]))},
{9, 5, 13, spine04, (int)(sizeof(spine04)/sizeof(spine04[0]))},
};
bool FossilFeature::place(Level *level, Random *random, int x, int y, int z)
{
bool useSpine = random->nextInt(2) == 0;
bool useCoal = random->nextInt(2) == 0;
int variant = random->nextInt(4);
const FossilStructure &s = useSpine ? spineStructures[variant] : skullStructures[variant];
int ox = x - s.width / 2;
int oy = y;
int oz = z - s.length / 2;
for (int i = 0; i < s.blockCount; i++)
{
const FossilBlock &b = s.blocks[i];
int bx = ox + b.x;
int by = oy + b.y;
int bz = oz + b.z;
if (by < 1 || by >= Level::maxBuildHeight)
continue;
if (useCoal)
level->setTileAndData(bx, by, bz, Tile::coal_ore_Id, 0, Tile::UPDATE_CLIENTS);
else
level->setTileAndData(bx, by, bz, Tile::bone_block_Id, b.data, Tile::UPDATE_CLIENTS);
}
return true;
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "Feature.h"
class FossilFeature : public Feature
{
public:
bool place(Level *level, Random *random, int x, int y, int z) override;
};
@@ -487,6 +487,15 @@ void HellRandomLevelSource::postProcess(ChunkSource *parent, int xt, int zt)
FlowerFeature(Tile::mushroom_red_Id).place(level, pprandom, x, y, z);
}
OreFeature magmaFeature(Tile::magma_Id, 0, 160, Tile::netherrack_Id);
for (int i = 0; i < 4; i++)
{
int x = xo + pprandom->nextInt(16);
int y = pprandom->nextInt(9) + 27;
int z = zo + pprandom->nextInt(16);
magmaFeature.place(level, pprandom, x, y, z);
}
OreFeature quartzFeature(Tile::quartz_ore_Id, 0, 13, Tile::netherrack_Id);
for (int i = 0; i < 16; i++)
{
+1
View File
@@ -19,6 +19,7 @@ bool HugeMushroomFeature::place(Level *level, Random *random, int x, int y, int
if (forcedType >= 0) type = forcedType;
int treeHeight = random->nextInt(3) + 4;
if (random->nextBoolean()) treeHeight *= 2;
bool free = true;
if (y < 1 || y + treeHeight + 1 >= Level::maxBuildHeight) return false;
+218
View File
@@ -0,0 +1,218 @@
#include "stdafx.h"
#include "net.minecraft.world.level.h"
#include "net.minecraft.world.level.tile.h"
#include "net.minecraft.world.level.tile.entity.h"
#include "Biome.h"
#include "Item.h"
#include "ItemInstance.h"
#include "WeighedTreasure.h"
#include "Villager.h"
#include "Zombie.h"
#include "IglooFeature.h"
bool IglooFeature::place(Level *level, Random *random, int x, int y, int z)
{
while (y > 2 && level->isEmptyTile(x, y - 1, z))
y--;
Biome *biome = level->getBiome(x, z);
if (biome != Biome::iceFlats && biome != Biome::iceMountains &&
biome != Biome::coldTaiga && biome != Biome::coldTaigaHills)
return false;
for (int dx = -3; dx <= 3; dx++)
for (int dz = -3; dz <= 3; dz++)
if (abs(dx) + abs(dz) < 6)
level->setTileAndData(x + dx, y, z + dz, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
for (int dy = 1; dy <= 2; dy++)
{
for (int dx = -3; dx <= 3; dx++)
{
for (int dz = -3; dz <= 3; dz++)
{
bool onPerimeter = (abs(dx) == 3 || abs(dz) == 3) && abs(dx) + abs(dz) < 6;
if (!onPerimeter)
continue;
if (dx == 0 && dz == 3)
continue;
if ((dx == 3 || dx == -3) && dz == 0 && dy == 1)
level->setTileAndData(x + dx, y + dy, z + dz, Tile::ice_Id, 0, Tile::UPDATE_CLIENTS);
else
level->setTileAndData(x + dx, y + dy, z + dz, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
}
}
}
level->setTileAndData(x, y + 3, z + 3, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 1, y, z + 4, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x, y, z + 4, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 1, y, z + 4, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 1, y + 1, z + 4, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 1, y + 1, z + 4, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 1, y + 2, z + 4, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 1, y + 2, z + 4, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x, y + 3, z + 4, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
for (int dx = -2; dx <= 2; dx++)
for (int dz = -2; dz <= 2; dz++)
if (abs(dx) == 2 || abs(dz) == 2)
level->setTileAndData(x + dx, y + 3, z + dz, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
for (int dx = -1; dx <= 1; dx++)
for (int dz = -1; dz <= 1; dz++)
level->setTileAndData(x + dx, y + 4, z + dz, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
for (int dy = 1; dy <= 2; dy++)
for (int dx = -2; dx <= 2; dx++)
for (int dz = -2; dz <= 2; dz++)
level->setTileAndData(x + dx, y + dy, z + dz, 0, 0, Tile::UPDATE_CLIENTS);
for (int dx = -1; dx <= 1; dx++)
for (int dz = -1; dz <= 1; dz++)
level->setTileAndData(x + dx, y + 3, z + dz, 0, 0, Tile::UPDATE_CLIENTS);
for (int dx = -1; dx <= 1; dx++)
for (int dz = -1; dz <= 1; dz++)
level->setTileAndData(x + dx, y + 1, z + dz, Tile::carpet_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 1, y + 1, z - 2, Tile::carpet_Id, 8, Tile::UPDATE_CLIENTS);
level->setTileAndData(x, y + 1, z - 2, Tile::carpet_Id, 8, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 1, y + 1, z - 2, Tile::carpet_Id, 8, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, y + 1, z + 1, Tile::furnace_Id, 4, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, y + 1, z, Tile::redstone_torch_Id, 5, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, y + 1, z - 1, Tile::crafting_table_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 2, y + 1, z, Tile::bed_Id, 2, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 2, y + 1, z - 1, Tile::bed_Id, 2 | 8, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 2, y + 1, z - 2, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, y + 1, z - 2, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 2, y + 1, z + 2, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, y + 1, z + 2, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 2, y + 2, z - 2, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, y + 2, z - 2, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 2, y + 2, z + 2, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, y + 2, z + 2, Tile::snow_Id, 0, Tile::UPDATE_CLIENTS);
if (random->nextInt(2) == 0)
placeBasement(level, random, x, y, z);
return true;
}
void IglooFeature::placeBasement(Level *level, Random *random, int x, int y, int z)
{
int by = y - 9;
int rz = z + 2;
for (int dx = -3; dx <= 3; dx++)
{
for (int dz = -4; dz <= 4; dz++)
{
for (int dy = 0; dy <= 4; dy++)
{
bool isWall = abs(dx) == 3 || abs(dz) == 4 || dy == 0 || dy == 4;
if (isWall)
{
int data = 0;
if (random->nextInt(5) == 0)
data = 2;
else if (random->nextInt(4) == 0)
data = 1;
level->setTileAndData(x + dx, by + dy, rz + dz, Tile::stonebrick_Id, data, Tile::UPDATE_CLIENTS);
}
else
{
level->setTileAndData(x + dx, by + dy, rz + dz, 0, 0, Tile::UPDATE_CLIENTS);
}
}
}
}
level->setTileAndData(x, y, z - 1, Tile::trapdoor_Id, 4, Tile::UPDATE_CLIENTS);
for (int i = 1; i <= 5; i++)
level->setTileAndData(x, y - i, z - 1, Tile::ladder_Id, 3, Tile::UPDATE_CLIENTS);
for (int dy = 1; dy <= 3; dy++)
level->setTileAndData(x, by + dy, z - 1, Tile::ladder_Id, 3, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, by + 1, rz - 2, Tile::chest_Id, 4, Tile::UPDATE_CLIENTS);
auto chestEntity = dynamic_pointer_cast<ChestTileEntity>(level->getTileEntity(x + 2, by + 1, rz - 2));
if (chestEntity)
{
static WeighedTreasure *iglooTreasure[] = {
new WeighedTreasure(Item::coal_Id, 0, 1, 4, 15),
new WeighedTreasure(Item::apple_Id, 0, 1, 3, 15),
new WeighedTreasure(Item::wheat_Id, 0, 2, 3, 10),
new WeighedTreasure(Item::gold_nugget_Id, 0, 1, 3, 10),
new WeighedTreasure(Item::rotten_flesh_Id,0, 1, 1, 10),
new WeighedTreasure(Item::stone_axe_Id, 0, 1, 1, 2),
new WeighedTreasure(Item::emerald_Id, 0, 1, 1, 1),
};
WeighedTreasureArray treasureArray(iglooTreasure, 7);
int rolls = 2 + random->nextInt(7);
WeighedTreasure::addChestItems(random, treasureArray, chestEntity, rolls);
chestEntity->setItem(0, make_shared<ItemInstance>(Item::golden_apple_Id, 1, 0));
}
level->setTileAndData(x - 2, by + 2, rz - 2, Tile::brewing_stand_Id, 0, Tile::UPDATE_CLIENTS);
auto brewEntity = dynamic_pointer_cast<BrewingStandTileEntity>(level->getTileEntity(x - 2, by + 2, rz - 2));
if (brewEntity)
brewEntity->setItem(1, make_shared<ItemInstance>(Item::potion_Id, 1, 16392));
level->setTileAndData(x - 2, by + 1, rz, Tile::cauldron_Id, 2, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 2, by + 1, rz - 3, Tile::spruce_stairs_Id, 7, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 2, by + 1, rz - 2, Tile::wooden_slab_Id, 9, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 2, by + 1, rz - 1, Tile::spruce_stairs_Id, 6, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, by + 1, rz - 1, Tile::carpet_Id, 14, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, by + 1, rz, Tile::carpet_Id, 14, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, by + 1, rz + 1, Tile::carpet_Id, 14, Tile::UPDATE_CLIENTS);
for (int cdx = -2; cdx <= 2; cdx++)
{
bool isBar = (cdx % 2 != 0);
level->setTileAndData(x + cdx, by + 1, rz + 2, isBar ? Tile::iron_bars_Id : Tile::stonebrick_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + cdx, by + 2, rz + 2, isBar ? Tile::iron_bars_Id : Tile::stonebrick_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + cdx, by + 3, rz + 2, Tile::stonebrick_Id, 0, Tile::UPDATE_CLIENTS);
}
for (int dy = 1; dy <= 3; dy++)
{
level->setTileAndData(x - 2, by + dy, rz + 3, Tile::stonebrick_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x, by + dy, rz + 3, Tile::stonebrick_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 2, by + dy, rz + 3, Tile::stonebrick_Id, 0, Tile::UPDATE_CLIENTS);
}
level->setTileAndData(x + 2, by + 3, rz + 1, Tile::web_Id, 0, Tile::UPDATE_CLIENTS);
level->setTileAndData(x - 1, by + 3, z - 1, Tile::torch_Id, 3, Tile::UPDATE_CLIENTS);
level->setTileAndData(x + 1, by + 3, z - 1, Tile::torch_Id, 3, Tile::UPDATE_CLIENTS);
level->setTileAndData(x, by + 3, rz + 1, Tile::torch_Id, 4, Tile::UPDATE_CLIENTS);
level->setTileAndData(x, by + 2, rz + 1, Tile::wall_standing_sign_Id, 2, Tile::UPDATE_CLIENTS);
auto signEntity = dynamic_pointer_cast<SignTileEntity>(level->getTileEntity(x, by + 2, rz + 1));
if (signEntity)
{
wstring empty = L"";
wstring line1 = L"<----";
wstring line2 = L"---->";
signEntity->SetMessage(0, empty);
signEntity->SetMessage(1, line1);
signEntity->SetMessage(2, line2);
signEntity->SetMessage(3, empty);
}
level->setTileAndData(x - 2, by + 2, rz - 3, Tile::flower_pot_Id, 9, Tile::UPDATE_CLIENTS);
auto zombieVillager = std::make_shared<Zombie>(level);
zombieVillager->setVillager(true);
zombieVillager->moveTo(x - 1 + 0.5, by + 1, rz + 3 + 0.5, 0, 0);
level->addEntity(zombieVillager);
auto villager = std::make_shared<Villager>(level);
villager->moveTo(x + 1 + 0.5, by + 1, rz + 3 + 0.5, 0, 0);
level->addEntity(villager);
}
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include "Feature.h"
class IglooFeature : public Feature
{
public:
bool place(Level *level, Random *random, int x, int y, int z) override;
private:
void placeBasement(Level *level, Random *random, int x, int y, int z);
};
+10 -5
View File
@@ -753,23 +753,28 @@ void LivingEntity::removeEffect(int effectId)
void LivingEntity::onEffectAdded(MobEffectInstance *effect)
{
effectsDirty = true;
if (!level->isClientSide) MobEffect::effects[effect->getId()]->addAttributeModifiers(dynamic_pointer_cast<LivingEntity>(shared_from_this()), getAttributes(), effect->getAmplifier());
int _id0 = effect->getId();
if (!level->isClientSide && _id0 >= 0 && _id0 < MobEffect::NUM_EFFECTS && MobEffect::effects[_id0])
MobEffect::effects[_id0]->addAttributeModifiers(dynamic_pointer_cast<LivingEntity>(shared_from_this()), getAttributes(), effect->getAmplifier());
}
void LivingEntity::onEffectUpdated(MobEffectInstance *effect, bool doRefreshAttributes)
{
effectsDirty = true;
if (doRefreshAttributes && !level->isClientSide)
int _id1 = effect->getId();
if (doRefreshAttributes && !level->isClientSide && _id1 >= 0 && _id1 < MobEffect::NUM_EFFECTS && MobEffect::effects[_id1])
{
MobEffect::effects[effect->getId()]->removeAttributeModifiers(dynamic_pointer_cast<LivingEntity>(shared_from_this()), getAttributes(), effect->getAmplifier());
MobEffect::effects[effect->getId()]->addAttributeModifiers(dynamic_pointer_cast<LivingEntity>(shared_from_this()), getAttributes(), effect->getAmplifier());
MobEffect::effects[_id1]->removeAttributeModifiers(dynamic_pointer_cast<LivingEntity>(shared_from_this()), getAttributes(), effect->getAmplifier());
MobEffect::effects[_id1]->addAttributeModifiers(dynamic_pointer_cast<LivingEntity>(shared_from_this()), getAttributes(), effect->getAmplifier());
}
}
void LivingEntity::onEffectRemoved(MobEffectInstance *effect)
{
effectsDirty = true;
if (!level->isClientSide) MobEffect::effects[effect->getId()]->removeAttributeModifiers(dynamic_pointer_cast<LivingEntity>(shared_from_this()), getAttributes(), effect->getAmplifier());
int _id2 = effect->getId();
if (!level->isClientSide && _id2 >= 0 && _id2 < MobEffect::NUM_EFFECTS && MobEffect::effects[_id2])
MobEffect::effects[_id2]->removeAttributeModifiers(dynamic_pointer_cast<LivingEntity>(shared_from_this()), getAttributes(), effect->getAmplifier());
}
void LivingEntity::heal(float heal)
+11 -1
View File
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "net.minecraft.world.level.levelgen.structure.h"
#include "net.minecraft.world.level.biome.h"
#include "JavaMath.h"
#include "Mth.h"
@@ -37,7 +38,16 @@ bool MineShaftFeature::isFeatureChunk(int x, int z, bool bIsSuperflat)
forcePlacement = levelGenOptions->isFeatureChunk(x,z,eFeature_Mineshaft);
}
return forcePlacement || (random->nextDouble() < chance && random->nextInt(80) < max(abs(x), abs(z)));
double effectiveChance = chance;
if (level != nullptr)
{
Biome *b = level->getBiome(x * 16, z * 16);
if (b == Biome::mesa || b == Biome::mesaPlateauF || b == Biome::mesaPlateau ||
b == Biome::mesaBryce || b == Biome::mesaPlateauFM || b == Biome::mesaPlateauM)
effectiveChance = 0.9;
}
return forcePlacement || (random->nextDouble() < effectiveChance && random->nextInt(80) < max(abs(x), abs(z)));
}
StructureStart *MineShaftFeature::createStructureStart(int x, int z)
+15 -4
View File
@@ -1,6 +1,12 @@
#include "stdafx.h"
#include "net.minecraft.world.effect.h"
static MobEffect *safeEffect(int id)
{
if (id < 0 || id >= MobEffect::NUM_EFFECTS) return nullptr;
return MobEffect::effects[id];
}
void MobEffectInstance::_init(int id, int duration, int amplifier)
{
this->id = id;
@@ -104,7 +110,8 @@ bool MobEffectInstance::tick(shared_ptr<LivingEntity> target)
{
if (duration > 0)
{
if (MobEffect::effects[id]->isDurationEffectTick(duration, amplifier))
MobEffect *effect = safeEffect(id);
if (effect && effect->isDurationEffectTick(duration, amplifier))
{
applyEffect(target);
}
@@ -122,19 +129,22 @@ void MobEffectInstance::applyEffect(shared_ptr<LivingEntity> mob)
{
if (duration > 0)
{
MobEffect::effects[id]->applyEffectTick(mob, amplifier);
MobEffect *effect = safeEffect(id);
if (effect) effect->applyEffectTick(mob, amplifier);
}
}
int MobEffectInstance::getDescriptionId()
{
return MobEffect::effects[id]->getDescriptionId();
MobEffect *effect = safeEffect(id);
return effect ? effect->getDescriptionId() : 0;
}
// 4J Added
int MobEffectInstance::getPostfixDescriptionId()
{
return MobEffect::effects[id]->getPostfixDescriptionId();
MobEffect *effect = safeEffect(id);
return effect ? effect->getPostfixDescriptionId() : 0;
}
int MobEffectInstance::hashCode()
@@ -182,6 +192,7 @@ CompoundTag *MobEffectInstance::save(CompoundTag *tag)
MobEffectInstance *MobEffectInstance::load(CompoundTag *tag)
{
int id = tag->getByte(L"Id");
if (id < 0 || id >= MobEffect::NUM_EFFECTS) return nullptr;
int amplifier = tag->getByte(L"Amplifier");
int duration = tag->getInt(L"Duration");
boolean ambient = tag->getBoolean(L"Ambient");
-2
View File
@@ -32,8 +32,6 @@ void OreRecipies::_init()
ADD_OBJECT(map[7],Tile::hayBlock);
ADD_OBJECT(map[7],new ItemInstance(Item::wheat, 9));
ADD_OBJECT(map[8],Tile::slimeBlock);
ADD_OBJECT(map[8],new ItemInstance(Item::slime_ball, 9));
}
void OreRecipies::addRecipes(Recipes *r)
{
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#define MAX_ORE_RECIPES 9
#define MAX_ORE_RECIPES 8
class OreRecipies
{
+7
View File
@@ -80,5 +80,12 @@ void PlainsBiome::decorate(Level* level, Random* rand, int xo, int zo)
DOUBLE_PLANT_GENERATOR->place(level, rand, j1, l1, k1);
}
}
if (rand->nextInt(10) == 0)
decorator->treeCount = 1;
else
decorator->treeCount = 0;
Biome::decorate(level, rand, xo, zo);
decorator->treeCount = -999;
}
+52 -18
View File
@@ -91,6 +91,9 @@ void Player::_init()
m_elytraImpactYd = 0.0f;
m_wasElytraFlying = false;
m_elytraFallProtectTicks = 0;
m_elytraMaxY = 0.0f;
m_fireworkBoostTicks = 0;
m_elytraRocketCooldown = 0;
takeXpDelay = 0;
experienceLevel = totalExperience = 0;
@@ -1016,6 +1019,7 @@ void Player::aiStep()
{
if (jumpTriggerTime > 0) jumpTriggerTime--;
if (m_elytraFallProtectTicks > 0) m_elytraFallProtectTicks--;
if (m_elytraRocketCooldown > 0) m_elytraRocketCooldown--;
if (level->difficulty == Difficulty::PEACEFUL && getHealth() < getMaxHealth() && level->getGameRules()->getBoolean(GameRules::RULE_NATURAL_REGENERATION))
@@ -1025,7 +1029,7 @@ void Player::aiStep()
inventory->tick();
oBob = bob;
if (jumping && !onGround && yd < 0.0 && !isElytraFlying() && !abilities.flying && jumpTriggerTime == 0)
if (jumping && !onGround && yd < 0.0 && fallDistance > 0.0f && !isElytraFlying() && !abilities.flying && jumpTriggerTime == 0)
{
shared_ptr<ItemInstance> chestItem = inventory->armor[LivingEntity::SLOT_CHEST - 1];
if (chestItem != nullptr && chestItem->getItem() != nullptr)
@@ -1044,20 +1048,12 @@ void Player::aiStep()
{
ticksElytraFlying++;
if (!level->isClientSide && ticksElytraFlying % 20 == 0)
{
shared_ptr<ItemInstance> chestItem = inventory->armor[LivingEntity::SLOT_CHEST - 1];
if (chestItem != nullptr && dynamic_cast<ElytraItem*>(chestItem->getItem()) != nullptr)
{
chestItem->hurtAndBreak(1, dynamic_pointer_cast<LivingEntity>(shared_from_this()));
if (!ElytraItem::isFlyEnabled(chestItem))
setElytraFlying(false);
}
else
{
setElytraFlying(false);
}
}
shared_ptr<ItemInstance> chestItem = inventory->armor[LivingEntity::SLOT_CHEST - 1];
if (chestItem == nullptr
|| chestItem->count <= 0
|| dynamic_cast<ElytraItem*>(chestItem->getItem()) == nullptr
|| !ElytraItem::isFlyEnabled(chestItem))
setElytraFlying(false);
}
@@ -2171,6 +2167,8 @@ void Player::travel(float xa, float ya)
double preHorizSpeed = Mth::sqrt(xd * xd + zd * zd);
if ((float)y > m_elytraMaxY) m_elytraMaxY = (float)y;
if (yd > -0.5)
fallDistance = 1.0f;
@@ -2217,10 +2215,19 @@ void Player::travel(float xa, float ya)
if (jumping && abilities.instabuild)
yd += (double)abilities.getFlyingSpeed() * 3.0;
if (m_fireworkBoostTicks > 0)
{
Vec3 *look = getLookAngle();
xd += look->x * 0.1 + (look->x * 1.5 - xd) * 0.5;
yd += look->y * 0.1 + (look->y * 1.5 - yd) * 0.5;
zd += look->z * 0.1 + (look->z * 1.5 - zd) * 0.5;
m_fireworkBoostTicks--;
}
m_elytraImpactYd = (float)yd;
move(xd, yd, zd);
if (horizontalCollision && !verticalCollision)
if (horizontalCollision)
{
double postHorizSpeed = Mth::sqrt(xd * xd + zd * zd);
double speedLost = preHorizSpeed - postHorizSpeed;
@@ -2428,6 +2435,14 @@ void Player::causeFallDamage(float distance)
{
if (abilities.mayfly) return;
if (isElytraFlying())
{
int dmg = Mth::ceil(distance - 3.0f);
if (dmg > 0)
onElytraFallDamage(dmg);
return;
}
if (distance >= 2)
{
distanceFall += static_cast<int>(Math::round(distance * 100.0));
@@ -2835,9 +2850,26 @@ bool Player::isElytraFlying()
return getPlayerFlag(FLAG_ELYTRA_FLYING);
}
void Player::startFireworkBoost(shared_ptr<ItemInstance> firework)
{
int flight = 0;
if (firework != nullptr && firework->hasTag())
{
CompoundTag *fw = firework->getTag()->getCompound(FireworksItem::TAG_FIREWORKS);
if (fw != nullptr && fw->contains(FireworksItem::TAG_FLIGHT))
flight = fw->getByte(FireworksItem::TAG_FLIGHT);
}
m_fireworkBoostTicks = (SharedConstants::TICKS_PER_SECOND / 2) * (flight + 1) + random->nextInt(6) + random->nextInt(7);
}
void Player::onElytraKineticDamage(float damage)
{
hurt(DamageSource::fall, damage);
hurt(DamageSource::flyIntoWall, damage);
}
void Player::onElytraFallDamage(int amount)
{
hurt(DamageSource::fall, (float)amount);
}
void Player::setElytraFlying(bool flying)
@@ -2848,6 +2880,7 @@ void Player::setElytraFlying(bool flying)
m_wasElytraFlying = false;
setSize(0.6f, 0.6f);
fallDistance = 0.0f;
m_elytraMaxY = (float)y;
}
else
{
@@ -2855,8 +2888,9 @@ void Player::setElytraFlying(bool flying)
m_wasElytraFlying = true;
m_elytraFallProtectTicks = 60;
m_fireworkBoostTicks = 0;
m_elytraRocketCooldown = 0;
setSize(0.6f, 1.8f);
}
}
+8
View File
@@ -88,10 +88,18 @@ public:
float m_elytraImpactYd;
bool m_wasElytraFlying;
int m_elytraFallProtectTicks;
float m_elytraMaxY;
public:
int m_fireworkBoostTicks;
int m_elytraRocketCooldown;
public:
void startFireworkBoost(shared_ptr<ItemInstance> firework);
bool isElytraFlying();
virtual void setElytraFlying(bool flying);
virtual void onElytraKineticDamage(float damage);
virtual void onElytraFallDamage(int amount);
public:
+14
View File
@@ -9,6 +9,7 @@ PlayerAbilitiesPacket::PlayerAbilitiesPacket()
_isFlying = false;
_canFly = false;
instabuild = false;
_noPhysics = false;
flyingSpeed = 0.0f;
walkingSpeed = 0.0f;
}
@@ -19,6 +20,7 @@ PlayerAbilitiesPacket::PlayerAbilitiesPacket(Abilities *abilities)
setFlying(abilities->flying);
setCanFly(abilities->mayfly);
setInstabuild(abilities->instabuild);
setNoPhysics(abilities->spectatorMode);
setFlyingSpeed(abilities->getFlyingSpeed());
setWalkingSpeed(abilities->getWalkingSpeed());
}
@@ -31,6 +33,7 @@ void PlayerAbilitiesPacket::read(DataInputStream *dis)
setFlying((bitfield & FLAG_FLYING) > 0);
setCanFly((bitfield & FLAG_CAN_FLY) > 0);
setInstabuild((bitfield & FLAG_INSTABUILD) > 0);
setNoPhysics((bitfield & FLAG_NOPHYSICS) > 0);
setFlyingSpeed(dis->readFloat());
setWalkingSpeed(dis->readFloat());
}
@@ -43,6 +46,7 @@ void PlayerAbilitiesPacket::write(DataOutputStream *dos)
if (isFlying()) bitfield |= FLAG_FLYING;
if (canFly()) bitfield |= FLAG_CAN_FLY;
if (canInstabuild()) bitfield |= FLAG_INSTABUILD;
if (isNoPhysics()) bitfield |= FLAG_NOPHYSICS;
dos->writeByte(bitfield);
dos->writeFloat(flyingSpeed);
@@ -124,6 +128,16 @@ void PlayerAbilitiesPacket::setWalkingSpeed(float walkingSpeed)
this->walkingSpeed = walkingSpeed;
}
bool PlayerAbilitiesPacket::isNoPhysics()
{
return _noPhysics;
}
void PlayerAbilitiesPacket::setNoPhysics(bool noPhysics)
{
_noPhysics = noPhysics;
}
bool PlayerAbilitiesPacket::canBeInvalidated()
{
return true;
+4
View File
@@ -11,11 +11,13 @@ private:
static const int FLAG_FLYING = 1 << 1;
static const int FLAG_CAN_FLY = 1 << 2;
static const int FLAG_INSTABUILD = 1 << 3;
static const int FLAG_NOPHYSICS = 1 << 4;
bool invulnerable;
bool _isFlying;
bool _canFly;
bool instabuild;
bool _noPhysics;
float flyingSpeed;
float walkingSpeed;
@@ -40,6 +42,8 @@ public:
void setFlyingSpeed(float flySpeed);
float getWalkingSpeed();
void setWalkingSpeed(float walkingSpeed);
bool isNoPhysics();
void setNoPhysics(bool noPhysics);
bool canBeInvalidated();
bool isInvalidatedBy(shared_ptr<Packet> packet);
+2
View File
@@ -10,6 +10,8 @@ const int PlayerActionPacket::STOP_DESTROY_BLOCK = 2;
const int PlayerActionPacket::DROP_ALL_ITEMS = 3;
const int PlayerActionPacket::DROP_ITEM = 4;
const int PlayerActionPacket::RELEASE_USE_ITEM = 5;
const int PlayerActionPacket::ELYTRA_IMPACT = 6;
const int PlayerActionPacket::ELYTRA_FALL_DAMAGE = 7;
PlayerActionPacket::PlayerActionPacket()
{
+2
View File
@@ -12,6 +12,8 @@ public:
static const int DROP_ALL_ITEMS;
static const int DROP_ITEM;
static const int RELEASE_USE_ITEM;
static const int ELYTRA_IMPACT;
static const int ELYTRA_FALL_DAMAGE;
int x, y, z, face, action;
+1 -1
View File
@@ -392,7 +392,7 @@ vector<pair<int, int> > *PotionItem::getUniquePotionValues()
int effectsHashCode = 1;
for(auto& effect : *effects)
{
effectsHashCode = 31*effectsHashCode + (effect ? 0 : effect->hashCode());
effectsHashCode = 31*effectsHashCode + (effect ? effect->hashCode() : 0);
delete effect;
}
+18
View File
@@ -782,6 +782,24 @@ void RandomLevelSource::postProcess(ChunkSource *parent, int xt, int zt)
}
PIXEndNamedEvent();
if (pprandom->nextInt(64) == 0)
{
int fx = xo + pprandom->nextInt(16) + 8;
int fy = 40 + pprandom->nextInt(10);
int fz = zo + pprandom->nextInt(16) + 8;
FossilFeature fossil;
fossil.place(level, pprandom, fx, fy, fz);
}
if (pprandom->nextInt(48) == 0)
{
int ix = xo + pprandom->nextInt(16) + 8;
int iy = level->maxBuildHeight;
int iz = zo + pprandom->nextInt(16) + 8;
IglooFeature igloo;
igloo.place(level, pprandom, ix, iy, iz);
}
PIXBeginNamedEvent(0,"Biome decorate");
biome->decorate(level, pprandom, xo, zo);
PIXEndNamedEvent();
+52
View File
@@ -517,6 +517,58 @@ void Recipes::_compileRecipes()
L'#', Tile::snow,
L'S');
addShapedRecipy(new ItemInstance(Tile::red_nether_brick, 1), //
L"sscicig",
L"WB", //
L"BW", //
L'W', Item::netherwart_seeds, L'B', new ItemInstance(Item::nether_brick_Id, 1, 0),
L'S');
addShapedRecipy(new ItemInstance(Tile::end_bricks, 4), //
L"ssctg",
L"##", //
L"##", //
L'#', Tile::endStone,
L'S');
addShapedRecipy(new ItemInstance(Tile::nether_wart_block, 1), //
L"ssscig",
L"###", //
L"###", //
L"###", //
L'#', Item::netherwart_seeds,
L'D');
addShapedRecipy(new ItemInstance((Tile*)Tile::magma, 1), //
L"sscig",
L"##", //
L"##", //
L'#', Item::magma_cream,
L'D');
addShapedRecipy(new ItemInstance(Tile::slimeBlock, 1), //
L"ssscig",
L"###", //
L"###", //
L"###", //
L'#', Item::slime_ball,
L'D');
addShapedRecipy(new ItemInstance(Item::slime_ball, 9), //
L"sctg",
L"#", //
L'#', Tile::slimeBlock,
L'D');
addShapedRecipy(new ItemInstance(Tile::clay, 1), //
L"sscig",
L"##", //
+15
View File
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "net.minecraft.world.item.h"
#include "net.minecraft.world.level.tile.h"
#include "DyePowderItem.h"
#include "Recipy.h"
#include "Recipes.h"
#include "StructureRecipies.h"
@@ -16,6 +17,20 @@ void StructureRecipies::addRecipes(Recipes *r)
L'S');
r->addShapedRecipy(new ItemInstance((Tile*)Tile::bone_block, 1), //
L"sssczg",
L"###", //
L"###", //
L"###", //
L'#', new ItemInstance(Item::dye, 1, DyePowderItem::WHITE),
L'S');
r->addShapelessRecipy(new ItemInstance(Item::dye, 9, DyePowderItem::WHITE), //
L"tg",
(Tile*)Tile::bone_block,
L'D');
r->addShapedRecipy(new ItemInstance(Tile::sandStone, 4, SandStoneTile::TYPE_SMOOTHSIDE), //
L"ssczg",
L"##", //
+1
View File
@@ -111,6 +111,7 @@ void ThrownPotion::onHit(HitResult *res)
for(auto& effect : *mobEffects)
{
int id = effect->getId();
if (id < 0 || id >= MobEffect::NUM_EFFECTS || !MobEffect::effects[id]) continue;
if (MobEffect::effects[id]->isInstantenous())
{
MobEffect::effects[id]->applyInstantenousEffect(getOwner(), e, effect->getAmplifier(), scale);
+1 -1
View File
@@ -576,7 +576,7 @@ void Tile::staticCtor()
Tile::log2 = (new TreeTile2(162))->setDestroyTime(2.0f)->setSoundType(Tile::SOUND_WOOD)->setIconName(L"log")->setDescriptionId(IDS_TILE_LOG)->sendTileData()->setUseDescriptionId(IDS_DESC_LOG);
Tile::woodStairsAcacia = (new StairTile(163, Tile::wood, TreeTile::ACACIA_TRUNK))->setBaseItemTypeAndMaterial(Item::eBaseItemType_stairs, Item::eMaterial_acaciawood)->setIconName(L"stairsWoodAcacia")->setDescriptionId(IDS_TILE_STAIRS_ACACIAWOOD)->sendTileData()->setUseDescriptionId(IDS_DESC_STAIRS);
Tile::woodStairsDark = (new StairTile(164, Tile::wood, TreeTile::DARK_TRUNK))->setBaseItemTypeAndMaterial(Item::eBaseItemType_stairs, Item::eMaterial_darkwood)->setIconName(L"stairsWoodDark")->setDescriptionId(IDS_TILE_STAIRS_DARKWOOD)->sendTileData()->setUseDescriptionId(IDS_DESC_STAIRS);
Tile::slimeBlock = (new SlimeTile(165))->setSoundType(SOUND_SLIME)->setIconName(L"slime")->setDescriptionId(IDS_TILE_SLIME_BLOCK)->setUseDescriptionId(IDS_DESC_SLIME_BLOCK)->disableMipmap();
Tile::slimeBlock = (new SlimeTile(165))->setBaseItemTypeAndMaterial(Item::eBaseItemType_block, Item::eMaterial_slime)->setSoundType(SOUND_SLIME)->setIconName(L"slime")->setDescriptionId(IDS_TILE_SLIME_BLOCK)->setUseDescriptionId(IDS_DESC_SLIME_BLOCK)->disableMipmap();
Tile::barrier = (new BarrierTile(166, Material::stone, false)) ->setIndestructible()->setExplodeable(6000000)->setSoundType(Tile::SOUND_STONE)->setIconName(L"barrier")->setDescriptionId(IDS_TILE_BARRIER)->setNotCollectStatistics()->setUseDescriptionId(IDS_DESC_BARRIER);
Tile::iron_trapdoor = (new TrapDoorTile(167, Material::metal))->setBaseItemTypeAndMaterial(Item::eBaseItemType_door, Item::eMaterial_trap)->setDestroyTime(5.0f)->setSoundType(Tile::SOUND_METAL)->setIconName(L"iron_trapdoor")->setDescriptionId(IDS_TILE_IRON_TRAPDOOR)->setNotCollectStatistics()->sendTileData()->setUseDescriptionId(IDS_DESC_TRAPDOOR);
+1
View File
@@ -33,6 +33,7 @@ void TileEntity::staticCtor()
TileEntity::setId(HopperTileEntity::create, eTYPE_HOPPERTILEENTITY, L"Hopper");
TileEntity::setId(ComparatorTileEntity::create, eTYPE_COMPARATORTILEENTITY, L"Comparator");
TileEntity::setId(BannerTileEntity::create, eTYPE_BANNERTILEENTITY, L"Banner");
TileEntity::setId(FlowerPotTileEntity::create, eTYPE_FLOWERPOTTILEENTITY, L"FlowerPot");
}
void TileEntity::setId(tileEntityCreateFn createFn, eINSTANCEOF clas, wstring id)
+1
View File
@@ -13,6 +13,7 @@ public:
static const int TYPE_BEACON = 3;
static const int TYPE_SKULL = 4;
static const int TYPE_BANNER = 5;
static const int TYPE_FLOWER_POT = 6;
int x, y, z;
int type;
+4
View File
@@ -14,6 +14,10 @@ void VillageFeature::staticCtor()
{
allowedBiomes.push_back( Biome::plains );
allowedBiomes.push_back( Biome::desert );
allowedBiomes.push_back( Biome::savanna );
allowedBiomes.push_back( Biome::savannaPlateau );
allowedBiomes.push_back( Biome::savannaM );
allowedBiomes.push_back( Biome::savannaPlateauM );
}
void VillageFeature::_init(int iXZSize)
+42 -20
View File
@@ -268,6 +268,7 @@ VillagePieces::VillagePiece::VillagePiece()
heightPosition = -1;
spawnedVillagerCount = 0;
isDesertVillage = false;
isAcaciaVillage = false;
startPiece = nullptr;
// for reflection
}
@@ -276,11 +277,13 @@ VillagePieces::VillagePiece::VillagePiece(StartPiece *startPiece, int genDepth)
{
heightPosition = -1;
isDesertVillage = false;
isAcaciaVillage = false;
spawnedVillagerCount = 0;
this->startPiece = startPiece;
if (startPiece != nullptr)
{
this->isDesertVillage = startPiece->isDesertVillage;
this->isAcaciaVillage = startPiece->isAcaciaVillage;
}
}
@@ -289,6 +292,7 @@ void VillagePieces::VillagePiece::addAdditonalSaveData(CompoundTag *tag)
tag->putInt(L"HPos", heightPosition);
tag->putInt(L"VCount", spawnedVillagerCount);
tag->putBoolean(L"Desert", isDesertVillage);
tag->putBoolean(L"Acacia", isAcaciaVillage);
}
void VillagePieces::VillagePiece::readAdditonalSaveData(CompoundTag *tag)
@@ -296,6 +300,7 @@ void VillagePieces::VillagePiece::readAdditonalSaveData(CompoundTag *tag)
heightPosition = tag->getInt(L"HPos");
spawnedVillagerCount = tag->getInt(L"VCount");
isDesertVillage = tag->getBoolean(L"Desert");
isAcaciaVillage = tag->getBoolean(L"Acacia");
}
StructurePiece *VillagePieces::VillagePiece::generateHouseNorthernLeft(StartPiece *startPiece, list<StructurePiece *> *pieces, Random *random, int yOff, int zOff)
@@ -413,29 +418,30 @@ int VillagePieces::VillagePiece::biomeBlock(int tile, int data)
if (isDesertVillage)
{
if (tile == Tile::log_Id)
{
return Tile::sandstone_Id;
}
else if (tile == Tile::cobblestone_Id)
{
return Tile::sandstone_Id;
}
else if (tile == Tile::planks_Id)
{
return Tile::sandstone_Id;
}
else if (tile == Tile::oak_stairs_Id)
{
return Tile::sandstone_stairs_Id;
}
else if (tile == Tile::stone_stairs_Id)
{
return Tile::sandstone_stairs_Id;
}
else if (tile == Tile::gravel_Id)
{
return Tile::sandstone_Id;
}
}
else if (isAcaciaVillage)
{
if (tile == Tile::log_Id)
return Tile::log2_Id;
else if (tile == Tile::planks_Id)
return Tile::planks_Id;
else if (tile == Tile::oak_stairs_Id)
return Tile::acacia_stairs_Id;
else if (tile == Tile::fence_Id)
return Tile::acacia_fence_Id;
else if (tile == Tile::fence_gate_Id)
return Tile::acacia_fence_gate_Id;
}
return tile;
}
@@ -445,17 +451,18 @@ int VillagePieces::VillagePiece::biomeData(int tile, int data)
if (isDesertVillage)
{
if (tile == Tile::log_Id)
{
return 0;
}
else if (tile == Tile::cobblestone_Id)
{
return SandStoneTile::TYPE_DEFAULT;
}
else if (tile == Tile::planks_Id)
{
return SandStoneTile::TYPE_SMOOTHSIDE;
}
}
else if (isAcaciaVillage)
{
if (tile == Tile::log_Id)
return (data & 0xC) | 0;
else if (tile == Tile::planks_Id)
return 4;
}
return data;
}
@@ -580,6 +587,8 @@ VillagePieces::StartPiece::StartPiece(BiomeSource *biomeSource, int genDepth, Ra
Biome *biome = biomeSource->getBiome(west, north);
isDesertVillage = biome == Biome::desert || biome == Biome::desertHills;
isAcaciaVillage = biome == Biome::savanna || biome == Biome::savannaPlateau ||
biome == Biome::savannaM || biome == Biome::savannaPlateauM;
}
VillagePieces::StartPiece::~StartPiece()
@@ -718,8 +727,21 @@ bool VillagePieces::StraightRoad::postProcess(Level *level, Random *random, Boun
if (chunkBB->isInside(x, 64, z))
{
int y = level->getTopSolidBlock(x, z) - 1;
level->setTileAndData(x, y, z, roadTile, 0, Tile::UPDATE_CLIENTS);
// level->setTileAndData(x, y - 1, z, baseTile, 0, Tile::UPDATE_CLIENTS);
int tileAtY = level->getTile(x, y, z);
if (tileAtY == Tile::water_Id || tileAtY == Tile::flowing_water_Id)
{
level->setTileAndData(x, y, z, Tile::planks_Id, 0, Tile::UPDATE_CLIENTS);
int fill = y - 1;
while (fill >= 0 && (level->getTile(x, fill, z) == Tile::water_Id || level->getTile(x, fill, z) == Tile::flowing_water_Id))
{
level->setTileAndData(x, fill, z, Tile::planks_Id, 0, Tile::UPDATE_CLIENTS);
fill--;
}
}
else
{
level->setTileAndData(x, y, z, roadTile, 0, Tile::UPDATE_CLIENTS);
}
}
}
}
+2
View File
@@ -70,6 +70,7 @@ private:
private:
int spawnedVillagerCount;
bool isDesertVillage;
bool isAcaciaVillage;
protected:
StartPiece *startPiece;
@@ -124,6 +125,7 @@ public:
// these fields are only used in generation step and aren't serialized :{
BiomeSource *biomeSource;
bool isDesertVillage;
bool isAcaciaVillage;
int villageSize;
bool isLibraryAdded;
@@ -1500,6 +1500,10 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_LEVEL_LEVELGEN_FEATURE
"${CMAKE_CURRENT_SOURCE_DIR}/EndPodiumFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Feature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Feature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/FossilFeature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/FossilFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/IglooFeature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/IglooFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/FlowerFeature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/FlowerFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/GroundBushFeature.cpp"
@@ -1866,6 +1870,8 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_LEVEL_TILE
"${CMAKE_CURRENT_SOURCE_DIR}/FireTile.h"
"${CMAKE_CURRENT_SOURCE_DIR}/FlowerPotTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/FlowerPotTile.h"
"${CMAKE_CURRENT_SOURCE_DIR}/FlowerPotTileEntity.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/FlowerPotTileEntity.h"
"${CMAKE_CURRENT_SOURCE_DIR}/FurnaceTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/FurnaceTile.h"
"${CMAKE_CURRENT_SOURCE_DIR}/GlassTile.cpp"
@@ -36,6 +36,8 @@
#include "RoofTreeFeature.h"
#include "DesertWellFeature.h"
#include "FossilFeature.h"
#include "IglooFeature.h"
#include "MegaTreeFeature.h"
#include "VinesFeature.h"
#include "GroundBushFeature.h"
@@ -22,3 +22,4 @@
#include "EnderChestTileEntity.h"
#include "ItemFrame.h"
#include "BannerTileEntity.h"
#include "FlowerPotTileEntity.h"