Compare commits

...

81 commits

Author SHA1 Message Date
Fireblade c3e02fb2d6
Merge pull request #144 from DrPerkyLegit/fix/name-render
Some checks failed
Nightly Release / Build Client (push) Has been cancelled
Nightly Release / Build Server (push) Has been cancelled
Sync branches with main / sync (push) Has been cancelled
Nightly Release / Release Server (push) Has been cancelled
Nightly Release / Release Client (push) Has been cancelled
Nightly Release / cleanup (push) Has been cancelled
2026-06-01 17:43:59 -04:00
DrPerkyLegit 78a55e97ef make names render when forced 2026-06-01 17:40:47 -04:00
piebot 4b93dbeedd
chore: release v1.0.8b (#143)
Some checks failed
Nightly Release / Build Client (push) Waiting to run
Nightly Release / Build Server (push) Waiting to run
Nightly Release / Release Client (push) Blocked by required conditions
Nightly Release / Release Server (push) Blocked by required conditions
Nightly Release / cleanup (push) Blocked by required conditions
Sync branches with main / sync (push) Waiting to run
Stable Release / Build Client (push) Has been cancelled
Stable Release / Build Server (push) Has been cancelled
Stable Release / Release Server (push) Has been cancelled
Stable Release / Release Client (push) Has been cancelled
Stable Release / cleanup (push) Has been cancelled
2026-06-01 16:48:00 +03:00
piebot c268ef1cc3
add new acknowledgement for new logo (thanks rdust_dusted!) (#142) 2026-06-01 16:20:01 +03:00
piebot f3d4e20b7a
chore: update logo ingame (#141) 2026-06-01 16:18:05 +03:00
piebot c0196abe3b
chore: update logo in banner (#140) 2026-06-01 16:17:06 +03:00
Fireblade 7f967ed66f
Merge pull request #139 from DrPerkyLegit/fix/s2c-particles
Some checks are pending
Nightly Release / Build Client (push) Waiting to run
Nightly Release / Build Server (push) Waiting to run
Nightly Release / Release Client (push) Blocked by required conditions
Nightly Release / Release Server (push) Blocked by required conditions
Nightly Release / cleanup (push) Blocked by required conditions
Sync branches with main / sync (push) Waiting to run
2026-05-31 20:51:49 -04:00
DrPerkyLegit 61f363e803 fix particles being sent from the server 2026-05-31 20:50:30 -04:00
Fireblade baa6745f45
Merge pull request #138 from DrPerkyLegit/fix/armor-stands
Fix/armor stands
2026-05-31 19:32:27 -04:00
DrPerkyLegit 7d93753451
Merge branch 'neoStudiosLCE:main' into fix/armor-stands 2026-05-31 19:31:19 -04:00
DrPerkyLegit 76000424e1 fix armor stands no gravity field 2026-05-31 19:27:41 -04:00
DrPerkyLegit a465d22390 Reapply "noPhysics field now works"
This reverts commit 31abba9e04.
2026-05-31 17:23:50 -04:00
DrPerkyLegit 31abba9e04 Revert "noPhysics field now works"
This reverts commit e9b2f724c6.
2026-05-31 17:21:14 -04:00
DrPerkyLegit e9b2f724c6 noPhysics field now works 2026-05-31 16:46:48 -04:00
piebot 4a7d95d8e9
chore: update neoLegacy logo (#137)
Some checks are pending
Nightly Release / Build Client (push) Waiting to run
Nightly Release / Release Server (push) Blocked by required conditions
Nightly Release / Release Client (push) Blocked by required conditions
Nightly Release / cleanup (push) Blocked by required conditions
Sync branches with main / sync (push) Waiting to run
Nightly Release / Build Server (push) Waiting to run
2026-05-31 21:53:07 +03:00
Fireblade d421708b5f
Merge pull request #136 from DrPerkyLegit/fix/armor-stands
Fix/armor stands
2026-05-31 14:33:10 -04:00
DrPerkyLegit f8c9349510 items render correctly on the head 2026-05-31 13:57:04 -04:00
DrPerkyLegit 78759b9f15 render elytra on armor stands 2026-05-31 12:36:32 -04:00
Lord Cambion 2417eb4562
feat: better kill command, Host Privileges check (#135)
i changed a bit the kill command because it was not working properly,
then i added a check for HostPrivileges for each command
2026-05-31 18:48:53 +03:00
DrPerkyLegit 5857fab1f6 fix default arm rotations 2026-05-31 11:32:55 -04:00
DrPerkyLegit db4f09ffb8 items now render in the hand when they exist 2026-05-31 11:30:27 -04:00
Lord Cambion 128651de24
fix: Ocelot Can Be Tamed (#132)
Some checks failed
Nightly Release / Build Client (push) Has been cancelled
Nightly Release / Build Server (push) Has been cancelled
Nightly Release / Release Server (push) Has been cancelled
Nightly Release / Release Client (push) Has been cancelled
Sync branches with main / sync (push) Has been cancelled
Nightly Release / cleanup (push) Has been cancelled
* Revert "fix: ocelot couldnt be tamed"

This reverts commit 7701841381.

* fix: better implementd ocelots taming.
2026-05-30 16:59:03 +03:00
Lord Cambion 1cd3f977e4
fix(TU31): prismarine animation (#134)
tranq forgot to update the name of the files
2026-05-30 16:58:23 +03:00
Lord Cambion b7393ab153
feat: dye recipes using flowers (#131)
Some checks failed
Sync branches with main / sync (push) Has been cancelled
Nightly Release / cleanup (push) Has been cancelled
Nightly Release / Release Server (push) Has been cancelled
Nightly Release / Release Client (push) Has been cancelled
Nightly Release / Build Client (push) Has been cancelled
Nightly Release / Build Server (push) Has been cancelled
2026-05-28 22:31:49 +03:00
/home/neo edee888662
fix: ocelot couldnt be tamed (#130) 2026-05-28 21:23:00 +03:00
Lord_Cambion 7701841381 fix: ocelot couldnt be tamed 2026-05-28 20:09:18 +02:00
DrPerkyLegit 60aba187a7
fix custom recipe names not working (#129) 2026-05-28 17:20:24 +03:00
Lord Cambion 012ada2e88
Merge pull request #128 from neoStudiosLCE/bugfix/boat
Some checks are pending
Nightly Release / Build Client (push) Waiting to run
Nightly Release / Release Server (push) Blocked by required conditions
Nightly Release / cleanup (push) Blocked by required conditions
Nightly Release / Build Server (push) Waiting to run
Nightly Release / Release Client (push) Blocked by required conditions
Sync branches with main / sync (push) Waiting to run
Update: BlockPos.cpp comments
2026-05-27 19:58:57 +02:00
Lord_Cambion 6e29b9f778 Update: BlockPos.cpp comments
changed from italian to english
2026-05-27 19:58:09 +02:00
Lord Cambion c19d5bb58e
fix: boat not following correctly the player when speeding (#127) 2026-05-27 20:22:12 +03:00
Lord_Cambion 2d07c7abee fix: boat not following correctly the player when speeding 2026-05-27 19:20:09 +02:00
Lord_Cambion 311503ec46 fix: /kill now kills the player if in creative
Some checks failed
Nightly Release / Build Client (push) Has been cancelled
Nightly Release / Build Server (push) Has been cancelled
Sync branches with main / sync (push) Has been cancelled
Nightly Release / Release Server (push) Has been cancelled
Nightly Release / Release Client (push) Has been cancelled
Nightly Release / cleanup (push) Has been cancelled
2026-05-26 19:02:54 +02:00
Necmi bb37600c87
fix: game startup not checking fullscren values correct (#122)
* fix outdated fullscreenload & added a bool to check at startupfullscreen

* fix outdated methods & add back accidental deletes + debug things

* used old vars & added deleted showwindow & updatewindow

* added deleted few things
2026-05-26 19:00:08 +03:00
Zero 544befe162
Fix multiple memory leaks and stale pooled allocations (#123) 2026-05-26 15:47:43 +03:00
Fireblade 285fab70b2
chore: update revelations url
Some checks are pending
Nightly Release / Build Client (push) Waiting to run
Nightly Release / Release Client (push) Blocked by required conditions
Nightly Release / Build Server (push) Waiting to run
Nightly Release / Release Server (push) Blocked by required conditions
Nightly Release / cleanup (push) Blocked by required conditions
Sync branches with main / sync (push) Waiting to run
2026-05-25 15:30:55 -04:00
Necmi ac3ece01c7
fix: stop elytra sound when going to mainmenu (#118) 2026-05-25 22:17:36 +03:00
Joud Kandeel ef0dad4ffc
fix: memory leaks and heavily optimize the game (#117)
* fixed performance issue on getting texture height for rendering the player model as it loades the player texture on every frame

* updated the lifetime of the texture

* fixed 20 MB memory leak

* delay window display until engine init is done
2026-05-25 22:13:28 +03:00
pieeebot 6ed34078fd chore: release v1.0.7b
Some checks failed
Nightly Release / Build Client (push) Waiting to run
Nightly Release / Build Server (push) Waiting to run
Nightly Release / Release Client (push) Blocked by required conditions
Nightly Release / Release Server (push) Blocked by required conditions
Nightly Release / cleanup (push) Blocked by required conditions
Sync branches with main / sync (push) Waiting to run
Stable Release / Build Client (push) Has been cancelled
Stable Release / Build Server (push) Has been cancelled
Stable Release / Release Client (push) Has been cancelled
Stable Release / Release Server (push) Has been cancelled
Stable Release / cleanup (push) Has been cancelled
2026-05-25 21:10:22 +03:00
pieeebot cd50236b8a Revert "feat: Feat/expanded worlds (#107)"
This reverts commit 98c33aa677.
2026-05-25 21:06:22 +03:00
pieeebot 4d745ab65c Revert "fix: remove round robin chunk cache (#114)"
This reverts commit bb62a9f559.
2026-05-25 21:05:50 +03:00
Lord_Cambion f904fb1972 fix: fences turn grass into dirt
problem: the game used is solid and it was wrong because blocks like fences or walls are also flagged as solit blocks because their material.
2026-05-25 18:34:32 +02:00
Lord_Cambion 4003a8e548 Merge branch 'main' of https://github.com/neoStudiosLCE/neoLegacy
* 'main' of https://github.com/neoStudiosLCE/neoLegacy:
  chore: release v1.0.6b
  fix: remove round robin chunk cache (#114)
2026-05-25 18:18:17 +02:00
Lord_Cambion 0bd0cd2452 feat: double the entity limit in your worlds 2026-05-25 18:18:10 +02:00
pieeebot f5d9db3397 chore: release v1.0.6b 2026-05-25 18:56:59 +03:00
DrPerkyLegit bb62a9f559
fix: remove round robin chunk cache (#114) 2026-05-25 18:54:30 +03:00
pieeebot 25e1358311 chore: release v1.0.5b 2026-05-25 16:06:12 +03:00
/home/neo af674463b4
ci: trigger on commit on main 2026-05-25 15:49:47 +03:00
DrPerkyLegit c9920f6679
fix: blue flashing on motd page (#111) 2026-05-25 15:46:44 +03:00
Nytreon eef6b1c129
fix(TU31): pistons not updating when they should (#113)
* Fixed pistons not updating when they should

I removed the code that 4J added to make pistons ignore updates because it seems they removed it in later versions for parity with java edition! This allows for 0 tick piston interactions amount other things.

* Update PistonBaseTile.h

I forgot to update the header 🥹
2026-05-25 15:46:19 +03:00
Lord_Cambion e1383cc6a3 fix: poison kill player
Some checks are pending
Sync branches with main / sync (push) Waiting to run
i fixed before this behaviour but somehow it is broken.

now i am clamping if 1 or 2 hp player is left with 1 hp.
2026-05-25 02:16:33 +02:00
Lord_Cambion ed63aaf8c4 fix: player ticks if game paused
before: player will tick if the game is paused allowing him to take damage from poison or lava.

now: player will not tick anymore if game is paused, so will not take damage anymore
2026-05-25 02:04:06 +02:00
Lord Cambion 9c55f80368
feat: Comparator +Item Frame (#106)
* feat: rotation in 8 directions

i implemented rotation in 8 directions for the item frames using decompilation

* fix: map render + normal items

map renders only explorated zones.
also fixed the size of the item and place inside item frame

* feat: itemframe drops items when hurt

* feat: comparator detects itemframe
2026-05-25 00:16:05 +03:00
DrPerkyLegit 98c33aa677
feat: Feat/expanded worlds (#107)
* it works kinda but its laggy

* attempt at making it faster

* Revert "attempt at making it faster"

This reverts commit 32a68ed3ae.

* Revert "it works kinda but its laggy"

This reverts commit 2830b973d4.

* round robin client chunk cache, expanded world type
2026-05-24 21:50:12 +03:00
Lord_Cambion 5d196d97cf update italian comments to english
Some checks failed
Sync branches with main / sync (push) Has been cancelled
2026-05-22 22:15:46 +02:00
Lord_Cambion 8446d10fa9 update: english comments i forgot to change! 2026-05-22 21:21:32 +02:00
DrPerkyLegit b67cbb85f3
feat: multiplayer feat/less hardcoded lists (#89)
Some checks are pending
Sync branches with main / sync (push) Waiting to run
* CustomPayloadPacket Changes

commented all code for old equip packets
cleaned up custom payload key creation
added 2 new payload packet definitions for upcoming changes

* server sided recipe list

* code cleanup for recipes

* add dtor for recipe classes to fix memory leak

* forgot this part to the dtor commit

* dtor changes tested and fixed

* server side creative menu list
2026-05-22 18:39:27 +03:00
DrPerkyLegit 9f37450178
chore: switch all entity ids to dedicated ints (#86)
* switch all entity ids to dedicated ints

* Increment NETWORK_PROTOCOL_VERSION to 79
2026-05-22 18:38:53 +03:00
neoapps-dev 28d9500eca cmake(sdk): includes 2026-05-22 17:53:44 +03:00
neoapps-dev 0b762588d8 feat(CMake): add SDK generation 2026-05-22 16:38:10 +03:00
NSDeathman d7d38d4f8f
fix: doubled grass upper block destroying (#104) 2026-05-22 14:07:06 +03:00
PUFF_MON 2cc554c11b
fix: Incorrect Rabbit Stew strings (#102)
Some checks are pending
Sync branches with main / sync (push) Waiting to run
2026-05-21 20:39:14 +03:00
Riley M. a2f200fd98
fix: nix flake (#101)
* fix: unbroke import paths in EnchantmentMenu.cpp

* fix: patch nix flakes for new 4JLibs

* style: format nix flake

* refactor(nix): rely on build-linux.sh functions for nix builds

* fix(nix): patch dev shell for build-linux.sh

* feat(nix): derive package version from network version
2026-05-21 19:49:56 +03:00
Huckle d55a38eb84
feat: Make -ip and -port args join server on game launch (#96)
Some checks failed
Sync branches with main / sync (push) Has been cancelled
feat: Add -quitondisconnect arg

Co-authored-by: TheHuckle <crazyh.dev@gmail.com>
2026-05-20 17:45:57 +03:00
NSDeathman dc5ad7aa6e
feat(TU31): added craft recipes for andesite, diorite and granite (and polished) blocks (#97) 2026-05-20 13:05:12 +03:00
piebot c326eabbb4
chore: update revelations link
Some checks failed
Sync branches with main / sync (push) Waiting to run
Stable Release / Build Server (push) Has been cancelled
Stable Release / Build Client (push) Has been cancelled
Stable Release / Release Server (push) Has been cancelled
Stable Release / cleanup (push) Has been cancelled
Stable Release / Release Client (push) Has been cancelled
2026-05-19 15:15:01 +03:00
car keys 092d9481dc
chore: fix broken link (#92) 2026-05-19 15:12:34 +03:00
pieeebot b91b0c9810 chore: fix patch note 2026-05-19 12:19:42 +03:00
pieeebot db6d5a76c2 chore: release v1.0.4b 2026-05-19 12:18:34 +03:00
NSDeathman 42ee0b519e
feat(TU31): Creepers can be ignited with flint and steel (#84)
Some checks are pending
Sync branches with main / sync (push) Waiting to run
* TU31 feature: Creepers can be ignited with flint and steel

* make mobInteract more accurate to decomp

---------

Co-authored-by: piebot <274605694+pieeebot@users.noreply.github.com>
2026-05-18 22:02:31 +03:00
NSDeathman d36a027e00
feat(TU31): Villagers turn into witches when struck by lightning (#83)
* Villagers turn into witches when struck by lightning

* fix: include statement for if a villager has a custom nametag

* fix: fix unneccesary line

* Build fix

---------

Co-authored-by: piebot <274605694+pieeebot@users.noreply.github.com>
2026-05-18 21:13:26 +03:00
/home/neo 4cb96bcb44
revert last commit
Some checks failed
Sync branches with main / sync (push) Has been cancelled
2026-05-17 02:12:16 +03:00
NSDeathman 3bc06a62a2
Bug fix: now fences and glass planes do not turn grass to dirt (#80) 2026-05-17 01:41:02 +03:00
NSDeathman ce9ee06d41
feat(TU31): Village roads have base block underneath like in TU31 (#73)
Some checks are pending
Sync branches with main / sync (push) Waiting to run
https://minecraft.wiki/w/Xbox_360_Edition_TU31

"World generation: Gravel roads in villages have cobblestone underneath, to prevent them from collapsing into caves."
2026-05-16 12:32:47 +03:00
DrPerkyLegit fd43009ab6
chore: bump network version to 570 (#78)
Updated the build number from 560 to 570.

All clients will be prompted with version miss-matches when joining smartcmd servers and cannot connect to clients older than this point
2026-05-16 12:17:52 +03:00
Fireblade 1661747dad
Merge pull request #77 from Firebladedoge229/fix/dedicated-server-multiplayer
Some checks are pending
Sync branches with main / sync (push) Waiting to run
fix: skin geometry crash on multiplayer servers
2026-05-15 17:28:17 -04:00
Fireblade faea0e7caa fix: skin geometry crash on multiplayer servers
fixes #72
2026-05-15 17:25:26 -04:00
NSDeathman 8b9058b13f
feat(TU31): Poppy & Dandelion now yield 1 dye instead of 2 like TU31 (#76)
Some checks are pending
Sync branches with main / sync (push) Waiting to run
2026-05-15 20:13:02 +03:00
NSDeathman e176a9f5ec
fix(TU31): fix podzol down face texture (#71)
Some checks are pending
Sync branches with main / sync (push) Waiting to run
2026-05-15 15:23:17 +03:00
PUFF_MON 9b1e25ac01
feat: Change cursor icon (#69) 2026-05-14 21:58:05 +03:00
pieeebot 9db673dc8d chore: release v1.0.3b 2026-05-14 15:46:32 +03:00
Fireblade f2193765d0
fix: dedicated server (#67)
* fix: dedicated server

* prioritize item.h when building item mappings
2026-05-14 13:27:56 +03:00
123 changed files with 3001 additions and 1034 deletions

View file

@ -62,7 +62,7 @@ body:
- type: input
id: itsrevela
attributes:
label: Is this reproducable in itsRevela/LCE-Revelations? (https://github.com/itsRevela/LCE-Revelations)
label: Is this reproducable in itsRevela/LCE-Revelations? (https://git.revela.dev/itsRevela/LCE-Revelations)
description: If this was a "no idea" or similar, it will be rejected.
validations:
required: true

BIN
.github/banner.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 656 KiB

After

Width:  |  Height:  |  Size: 673 KiB

View file

@ -1,9 +1,8 @@
name: Nightly Release
on:
push:
branches:
- experimental
- main
workflow_dispatch:
permissions:

2
BUMP
View file

@ -1 +1 @@
1.0.2b
1.0.8b

View file

@ -235,10 +235,14 @@ if(TARGET Minecraft.Server)
endif()
set(_item_map_inputs
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/Tile.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/Item.h"
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/Tile.h"
)
if(CMAKE_CROSSCOMPILING AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
string(REPLACE ";" "\\;" _item_map_inputs "${_item_map_inputs}")
endif()
#neo: added ItemNameMap generation
add_custom_command(
OUTPUT "${CMAKE_BINARY_DIR}/generated/ItemNameMap.h"
@ -262,6 +266,32 @@ if(PLATFORM_NAME STREQUAL "Windows64")
add_dependencies(Minecraft.Server GenerateItemNameMap)
endif()
#neo: added - SDK generation
set(SDK_INPUT_DIRS
"${CMAKE_SOURCE_DIR}/Minecraft.World"
"${CMAKE_SOURCE_DIR}/Minecraft.Client"
"${CMAKE_SOURCE_DIR}/include"
"${CMAKE_SOURCE_DIR}/Minecraft.Client/${PLATFORM_NAME}/4JLibs"
)
set(SDK_OUTPUT "${CMAKE_BINARY_DIR}/Minecraft.Client/$<CONFIG>/sdk.h")
add_custom_command(
OUTPUT "${SDK_OUTPUT}"
COMMAND ${CMAKE_COMMAND}
"-DINPUT_DIRS=${SDK_INPUT_DIRS}"
"-DOUTPUT_FILE=${SDK_OUTPUT}"
-P "${CMAKE_SOURCE_DIR}/cmake/GenerateSdk.cmake"
DEPENDS
"${CMAKE_SOURCE_DIR}/cmake/GenerateSdk.cmake"
COMMENT "Generating sdk.h..."
VERBATIM
)
add_custom_target(GenerateSdk ALL
DEPENDS "${SDK_OUTPUT}"
)
set_property(TARGET GenerateSdk PROPERTY FOLDER "Build")
target_include_directories(Minecraft.Client PRIVATE
"${CMAKE_CURRENT_BINARY_DIR}/generated"
)

View file

@ -8,7 +8,6 @@ ArmorStandModel::ArmorStandModel(float scale) : HumanoidModel(scale)
{
texWidth = 64;
texHeight = 64;
head = new ModelPart(this, 0, 0);
head->addBox(-1.0f, -7.0f, -1.0f, 2, 7, 2, scale);

View file

@ -16,6 +16,7 @@
#include "PlayerRenderer.h"
#include "../Minecraft.World/SkullItem.h"
#include "../Minecraft.World/SkullTileEntity.h"
#include "../Minecraft.World/ElytraItem.h"
static const float DEG_TO_RAD = 3.14159265f / 180.0f;
@ -84,9 +85,22 @@ void ArmorStandRenderer::render(shared_ptr<Entity> entity,
double x, double y, double z,
float rot, float a)
{
shared_ptr<LivingEntity> mob = dynamic_pointer_cast<LivingEntity>(entity);
float brightness = SharedConstants::TEXTURE_LIGHTING ? 1 : mob->getBrightness(a);
glColor3f(brightness, brightness, brightness);
shared_ptr<ItemInstance> item = mob->getCarriedItem();
prepareCarriedItem(mob, item);
LivingEntityRenderer::render(entity, x, y, z, rot, a);
}
void ArmorStandRenderer::prepareCarriedItem(shared_ptr<Entity> mob, shared_ptr<ItemInstance> item)
{
armorLayer->armorModel1->holdingRightHand = armorLayer->armorModel2->holdingRightHand = item != nullptr ? 1 : 0;
}
void ArmorStandRenderer::renderModel(shared_ptr<LivingEntity> mob,
float wp, float ws, float bob,
float headRotMinusBodyRot,
@ -165,7 +179,109 @@ void ArmorStandRenderer::renderModel(shared_ptr<LivingEntity> mob,
void ArmorStandRenderer::additionalRendering(shared_ptr<LivingEntity> mob, float a)
{
{
shared_ptr<ItemInstance> chestItem = mob->getEquipmentSlots()[ArmorStand::SLOT_CHEST];
if (chestItem != nullptr && dynamic_cast<ElytraItem*>(chestItem->getItem()) != nullptr)
{
static ResourceLocation elytraTexture(L"item/elytra.png");
bindTexture(&elytraTexture);
float brightness2 = SharedConstants::TEXTURE_LIGHTING ? 1 : mob->getBrightness(a);
glColor3f(brightness2, brightness2, brightness2);
ArmorStandModel* standModel = ((ArmorStandModel*)this->model);
ArmorStand* stand = dynamic_cast<ArmorStand*>(mob.get());
float wf = 0.2617994f;
float wf1 = -0.2617994f;
float wf2 = standModel->body->y;
float wf3 = 0.0f;
stand->rotateElytraX += (wf - stand->rotateElytraX) * 0.3f;
stand->rotateElytraY += (wf3 - stand->rotateElytraY) * 0.3f;
stand->rotateElytraZ += (wf1 - stand->rotateElytraZ) * 0.3f;
standModel->elytraRight->y = wf2;
standModel->elytraRight->xRot = stand->rotateElytraX;
standModel->elytraRight->yRot = stand->rotateElytraY;
standModel->elytraRight->zRot = stand->rotateElytraZ;
standModel->elytraLeft->y = wf2;
standModel->elytraLeft->xRot = stand->rotateElytraX;
standModel->elytraLeft->yRot = -stand->rotateElytraY;
standModel->elytraLeft->zRot = -stand->rotateElytraZ;
glPushMatrix();
glTranslatef(0, 0.0f, (2.0f + 0.125f) / 16.0f);
standModel->renderElytra(1 / 16.0f, true);
glPopMatrix();
}
}
std::shared_ptr<ItemInstance> item = mob->getCarriedItem();
if (item != nullptr)
{
glPushMatrix();
ArmorStandModel* standModel = ((ArmorStandModel*)model);
if (standModel->young) {
float s = 0.5f;
glTranslatef(0 / 16.0f, 10 / 16.0f, 0 / 16.0f);
glRotatef(-20, -1, 0, 0);
glScalef(s, s, s);
}
standModel->arm1->translateTo(1 / 16.0f);
glTranslatef(-1 / 16.0f, 7 / 16.0f, 1 / 16.0f);
if (item->id < 256 && TileRenderer::canRender(Tile::tiles[item->id]->getRenderShape()) && item->id != Tile::barrier_Id)
{
float s = 8 / 16.0f;
glTranslatef(-0 / 16.0f, 3 / 16.0f, -5 / 16.0f);
s *= 0.75f;
glRotatef(20, 1, 0, 0);
glRotatef(45, 0, 1, 0);
glScalef(-s, -s, s);
}
else if (item->id == Item::bow_Id)
{
float s = 10 / 16.0f;
glTranslatef(0 / 16.0f, 2 / 16.0f, 5 / 16.0f);
glRotatef(-20, 0, 1, 0);
glScalef(s, -s, s);
glRotatef(-100, 1, 0, 0);
glRotatef(45, 0, 1, 0);
}
else if (Item::items[item->id]->isHandEquipped())
{
float s = 10 / 16.0f;
glTranslatef(0, 3 / 16.0f, 0);
glScalef(s, -s, s);
glRotatef(-100, 1, 0, 0);
glRotatef(45, 0, 1, 0);
}
else
{
float s = 6 / 16.0f;
glTranslatef(+4 / 16.0f, +3 / 16.0f, -3 / 16.0f);
glScalef(s, s, s);
glRotatef(60, 0, 0, 1);
glRotatef(-90, 1, 0, 0);
glRotatef(20, 0, 0, 1);
}
this->entityRenderDispatcher->itemInHandRenderer->renderItem(mob, item, 0);
if (item->getItem()->hasMultipleSpriteLayers())
{
this->entityRenderDispatcher->itemInHandRenderer->renderItem(mob, item, 1);
}
glPopMatrix();
}
}

View file

@ -47,5 +47,7 @@ public:
float headRotMinusBodyRot,
float headRotx, float scale) override;
virtual int prepareArmor(shared_ptr<LivingEntity> mob, int layer, float a) override;
void prepareCarriedItem(shared_ptr<Entity> mob, shared_ptr<ItemInstance> item);
virtual void additionalRendering(shared_ptr<LivingEntity> mob, float a) override;
};

View file

@ -61,6 +61,8 @@
#include "Windows64/Network/WinsockNetLayer.h"
#endif
#include "../Minecraft.World/Recipes.h"
#ifdef _DURANGO
#include "../Minecraft.World/DurangoStats.h"
@ -137,6 +139,9 @@ ClientConnection::ClientConnection(Minecraft *minecraft, Socket *socket, int iUs
maxPlayers = 20;
m_isForkServer = false;
m_recivedRecipeRegistyUpdate = false;
m_recivedCreativeRegistyUpdate = false;
this->minecraft = minecraft;
if( iUserIndex < 0 )
@ -246,6 +251,14 @@ void ClientConnection::handleLogin(shared_ptr<LoginPacket> packet)
{
if (done) return;
if (!m_recivedRecipeRegistyUpdate) {
Recipes::getInstance()->loadFromLocal();
}
if (!m_recivedCreativeRegistyUpdate) {
IUIScene_CreativeMenu::loadFromLocal();
}
PlayerUID OnlineXuid;
ProfileManager.GetXUID(m_userIndex,&OnlineXuid,true); // online xuid
MOJANG_DATA *pMojangData = nullptr;
@ -4025,6 +4038,16 @@ void ClientConnection::handleCustomPayload(shared_ptr<CustomPayloadPacket> custo
}
}
}
else if (CustomPayloadPacket::UPDATE_RECIPE_REGISTRY.compare(customPayloadPacket->identifier) == 0) {
this->m_recivedRecipeRegistyUpdate = true;
Recipes::getInstance()->loadFromPacket(customPayloadPacket->data);
}
else if (CustomPayloadPacket::UPDATE_CREATIVE_REGISTRY.compare(customPayloadPacket->identifier) == 0) {
this->m_recivedCreativeRegistyUpdate = true;
IUIScene_CreativeMenu::loadFromPacket(customPayloadPacket->data);
}
}
Connection *ClientConnection::getConnection()
@ -4300,22 +4323,19 @@ void ClientConnection::handleSetPlayerTeamPacket(shared_ptr<SetPlayerTeamPacket>
void ClientConnection::handleParticleEvent(shared_ptr<LevelParticlesPacket> packet)
{
const ParticleType* type = packet->getType();
if (type == nullptr) return;
ePARTICLE_TYPE particleId = (ePARTICLE_TYPE)Integer::parseInt(packet->getName());
ePARTICLE_TYPE particleId = (ePARTICLE_TYPE)type->getId();
for (int i = 0; i < packet->getCount(); i++)
{
double xVarience = random->nextGaussian() * packet->getXDist();
double yVarience = random->nextGaussian() * packet->getYDist();
double zVarience = random->nextGaussian() * packet->getZDist();
double xa = random->nextGaussian() * packet->getMaxSpeed();
double ya = random->nextGaussian() * packet->getMaxSpeed();
double za = random->nextGaussian() * packet->getMaxSpeed();
for (int i = 0; i < packet->getCount(); i++)
{
double xVarience = random->nextGaussian() * packet->getXDist();
double yVarience = random->nextGaussian() * packet->getYDist();
double zVarience = random->nextGaussian() * packet->getZDist();
double xa = random->nextGaussian() * packet->getMaxSpeed();
double ya = random->nextGaussian() * packet->getMaxSpeed();
double za = random->nextGaussian() * packet->getMaxSpeed();
level->addParticle(particleId, packet->getX() + xVarience, packet->getY() + yVarience, packet->getZ() + zVarience, xa, ya, za);
}
level->addParticle(particleId, packet->getX() + xVarience, packet->getY() + yVarience, packet->getZ() + zVarience, xa, ya, za);
}
}
void ClientConnection::handleUpdateAttributes(shared_ptr<UpdateAttributesPacket> packet)

View file

@ -49,6 +49,8 @@ private:
std::unordered_set<int> m_trackedEntityIds;
std::unordered_set<int64_t> m_visibleChunks;
bool m_isForkServer; // true when connected to a fork server (received MC|ForkHello)
bool m_recivedRecipeRegistyUpdate;
bool m_recivedCreativeRegistyUpdate;
static int64_t chunkKey(int x, int z) { return ((int64_t)x << 32) | ((int64_t)z & 0xFFFFFFFF); }

View file

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "../../Minecraft.World/net.minecraft.world.entity.item.h"
#include "../../Minecraft.World/net.minecraft.world.entity.player.h"
#include "../../Minecraft.World/net.minecraft.world.level.tile.entity.h"
@ -27,6 +27,9 @@
#include "../GameMode.h"
#include "../Xbox/Social/SocialManager.h"
#include "Tutorial/TutorialMode.h"
#ifdef _WINDOWS64
#include "../Windows64/Network/WinsockNetLayer.h" // HUCKLE - added for quit on disconnect
#endif
#if defined _XBOX || defined _WINDOWS64
#include "../Xbox/XML/ATGXmlParser.h"
#include "../Xbox/XML/xmlFilesCallback.h"
@ -450,7 +453,7 @@ void CMinecraftApp::SetAction(int iPad, eXuiAction action, LPVOID param)
bool CMinecraftApp::IsAppPaused()
{
#if defined(_XBOX_ONE) || defined(__ORBIS__)
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
bool paused = m_bIsAppPaused;
EnterCriticalSection(&m_saveNotificationCriticalSection);
if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 )
@ -946,7 +949,9 @@ void CMinecraftApp::InitGameSettings()
memset(pProfileSettings,0,sizeof(C_4JProfile::PROFILESETTINGS));
SetDefaultOptions(pProfileSettings,i);
Win64_LoadSettings(GameSettingsA[i]);
#ifndef MINECRAFT_SERVER_BUILD
ApplyGameSettingsChanged(i);
#endif
#elif defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__
C4JStorage::PROFILESETTINGS *pProfileSettings=StorageManager.GetDashboardProfileSettings(i);
// 4J-PB - don't cause an options write to happen here
@ -3386,6 +3391,15 @@ void CMinecraftApp::HandleXuiActions(void)
SetAction(i,eAppAction_Idle);
// HUCKLE - added for quit game on disconnect
#ifdef _WINDOWS64
if(g_Win64MultiplayerQuitOnDisconnect == true)
{
app.ExitGame();
return;
}
#endif
// If we're already leaving don't exit
if (g_NetworkManager.IsLeavingGame())
{
@ -9611,8 +9625,9 @@ bool CMinecraftApp::DLCContentRetrieved(eDLCMarketplaceType eType)
void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, DWORD dwSkinBoxC)
{
EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER);
Model *pModel = renderer->getModel();
EntityRenderDispatcher *dispatcher = EntityRenderDispatcher::instance;
EntityRenderer *renderer = dispatcher ? dispatcher->getRenderer(eTYPE_PLAYER) : nullptr;
Model *pModel = renderer ? renderer->getModel() : nullptr;
vector<ModelPart *> *pvModelPart = new vector<ModelPart *>;
vector<SKIN_BOX *> *pvSkinBoxes = new vector<SKIN_BOX *>;
@ -9643,8 +9658,9 @@ void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, D
vector<ModelPart *> * CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, vector<SKIN_BOX *> *pvSkinBoxA)
{
EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER);
Model *pModel = renderer->getModel();
EntityRenderDispatcher *dispatcher = EntityRenderDispatcher::instance;
EntityRenderer *renderer = dispatcher ? dispatcher->getRenderer(eTYPE_PLAYER) : nullptr;
Model *pModel = renderer ? renderer->getModel() : nullptr;
vector<ModelPart *> *pvModelPart = new vector<ModelPart *>;
EnterCriticalSection( &csAdditionalModelParts );

View file

@ -916,7 +916,7 @@ void IUIScene_CraftingMenu::UpdateHighlight()
// special case for the torch coal/charcoal
int id=pTempItemInstAdditional->getDescriptionId();
LPCWSTR itemstring;
wstring itemstring;
switch(id)
{
@ -945,11 +945,15 @@ void IUIScene_CraftingMenu::UpdateHighlight()
}
break;
default:
itemstring=app.GetString(id );
if (pTempItemInstAdditional->hasCustomHoverName()) {
itemstring = pTempItemInstAdditional->getHoverName();
} else {
itemstring = app.GetString(id);
}
break;
}
setItemText(itemstring);
setItemText(itemstring.c_str());
}
else
{

View file

@ -1,3 +1,4 @@
#include "IUIScene_CreativeMenu.h"
#include "stdafx.h"
#include "IUIScene_CreativeMenu.h"
@ -22,6 +23,56 @@ vector< shared_ptr<ItemInstance> > IUIScene_CreativeMenu::categoryGroups[eCreati
#define ITEM_AUX(id, aux) list->push_back( shared_ptr<ItemInstance>(new ItemInstance(id, 1, aux)) );
#define DEF(index) list = &categoryGroups[index];
void IUIScene_CreativeMenu::_wipeCreativeItems() {
for (int i = 0; i < eCreativeInventoryGroupsCount; i++) {
IUIScene_CreativeMenu::categoryGroups[i].clear();
}
}
void IUIScene_CreativeMenu::loadFromLocal() {
IUIScene_CreativeMenu::_wipeCreativeItems();
IUIScene_CreativeMenu::staticCtor();
}
void IUIScene_CreativeMenu::loadFromPacket(byteArray packetData) {
ByteArrayInputStream bais(packetData);
DataInputStream input(&bais);
IUIScene_CreativeMenu::_wipeCreativeItems();
for (int i = 0; i < eCreativeInventoryGroupsCount; i++) {
int itemCount = input.readShort();
for (int j = 0; j < itemCount; j++) {
int itemId = input.readShort();
int itemAux = input.readShort();
shared_ptr<ItemInstance> item = std::make_shared<ItemInstance>(itemId, 1, 0);
item->setRawAuxValue(itemAux);
item->tag = Packet::readNbt(&input);
IUIScene_CreativeMenu::categoryGroups[i].emplace_back(item);
}
}
}
std::shared_ptr<CustomPayloadPacket> IUIScene_CreativeMenu::createUpdatePacket() {
ByteArrayOutputStream baos;
DataOutputStream dos(&baos);
for (int i = 0; i < eCreativeInventoryGroupsCount; i++) {
dos.writeShort(IUIScene_CreativeMenu::categoryGroups[i].size());
for (shared_ptr<ItemInstance>& item : IUIScene_CreativeMenu::categoryGroups[i]) {
dos.writeShort(item->id);
dos.writeShort(item->getAuxValue());
Packet::writeNbt(item->tag, &dos);
}
}
return std::make_shared<CustomPayloadPacket>(CustomPayloadPacket::UPDATE_CREATIVE_REGISTRY, baos.toByteArray());
}
void IUIScene_CreativeMenu::staticCtor()
{
vector< shared_ptr<ItemInstance> > *list;
@ -801,55 +852,56 @@ void IUIScene_CreativeMenu::staticCtor()
ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2EXTENDED, MASK_JUMPBOOST))
// end of tu31 potions
if (specs == nullptr) {
specs = new TabSpec * [eCreativeInventoryTab_COUNT];
specs = new TabSpec*[eCreativeInventoryTab_COUNT];
// Top Row
ECreative_Inventory_Groups blocksGroup[] = {eCreativeInventory_BuildingBlocks};
specs[eCreativeInventoryTab_BuildingBlocks] = new TabSpec(L"Structures", IDS_GROUPNAME_BUILDING_BLOCKS, 1, blocksGroup);
// Top Row
ECreative_Inventory_Groups blocksGroup[] = { eCreativeInventory_BuildingBlocks };
specs[eCreativeInventoryTab_BuildingBlocks] = new TabSpec(L"Structures", IDS_GROUPNAME_BUILDING_BLOCKS, 1, blocksGroup);
#ifndef _CONTENT_PACKAGE
ECreative_Inventory_Groups decorationsGroup[] = {eCreativeInventory_Decoration};
ECreative_Inventory_Groups debugDecorationsGroup[] = {eCreativeInventory_ArtToolsDecorations};
specs[eCreativeInventoryTab_Decorations] = new TabSpec(L"Decoration", IDS_GROUPNAME_DECORATIONS, 1, decorationsGroup, 0, nullptr, 1, debugDecorationsGroup);
ECreative_Inventory_Groups decorationsGroup[] = { eCreativeInventory_Decoration };
ECreative_Inventory_Groups debugDecorationsGroup[] = { eCreativeInventory_ArtToolsDecorations };
specs[eCreativeInventoryTab_Decorations] = new TabSpec(L"Decoration", IDS_GROUPNAME_DECORATIONS, 1, decorationsGroup, 0, nullptr, 1, debugDecorationsGroup);
#else
ECreative_Inventory_Groups decorationsGroup[] = {eCreativeInventory_Decoration};
specs[eCreativeInventoryTab_Decorations] = new TabSpec(L"Decoration", IDS_GROUPNAME_DECORATIONS, 1, decorationsGroup);
ECreative_Inventory_Groups decorationsGroup[] = { eCreativeInventory_Decoration };
specs[eCreativeInventoryTab_Decorations] = new TabSpec(L"Decoration", IDS_GROUPNAME_DECORATIONS, 1, decorationsGroup);
#endif
ECreative_Inventory_Groups redAndTranGroup[] = {eCreativeInventory_Transport, eCreativeInventory_Redstone};
specs[eCreativeInventoryTab_RedstoneAndTransport] = new TabSpec(L"RedstoneAndTransport", IDS_GROUPNAME_REDSTONE_AND_TRANSPORT, 2, redAndTranGroup);
ECreative_Inventory_Groups redAndTranGroup[] = { eCreativeInventory_Transport, eCreativeInventory_Redstone };
specs[eCreativeInventoryTab_RedstoneAndTransport] = new TabSpec(L"RedstoneAndTransport", IDS_GROUPNAME_REDSTONE_AND_TRANSPORT, 2, redAndTranGroup);
ECreative_Inventory_Groups materialsGroup[] = {eCreativeInventory_Materials};
specs[eCreativeInventoryTab_Materials] = new TabSpec(L"Materials", IDS_GROUPNAME_MATERIALS, 1, materialsGroup);
ECreative_Inventory_Groups materialsGroup[] = { eCreativeInventory_Materials };
specs[eCreativeInventoryTab_Materials] = new TabSpec(L"Materials", IDS_GROUPNAME_MATERIALS, 1, materialsGroup);
ECreative_Inventory_Groups foodGroup[] = {eCreativeInventory_Food};
specs[eCreativeInventoryTab_Food] = new TabSpec(L"Food", IDS_GROUPNAME_FOOD, 1, foodGroup);
ECreative_Inventory_Groups foodGroup[] = { eCreativeInventory_Food };
specs[eCreativeInventoryTab_Food] = new TabSpec(L"Food", IDS_GROUPNAME_FOOD, 1, foodGroup);
ECreative_Inventory_Groups toolsGroup[] = {eCreativeInventory_ToolsArmourWeapons};
specs[eCreativeInventoryTab_ToolsWeaponsArmor] = new TabSpec(L"Tools", IDS_GROUPNAME_TOOLS_WEAPONS_ARMOR, 1, toolsGroup);
ECreative_Inventory_Groups toolsGroup[] = { eCreativeInventory_ToolsArmourWeapons };
specs[eCreativeInventoryTab_ToolsWeaponsArmor] = new TabSpec(L"Tools", IDS_GROUPNAME_TOOLS_WEAPONS_ARMOR, 1, toolsGroup);
ECreative_Inventory_Groups brewingGroup[] = {eCreativeInventory_Brewing, eCreativeInventory_Potions_Level2_Extended, eCreativeInventory_Potions_Extended, eCreativeInventory_Potions_Level2, eCreativeInventory_Potions_Basic};
ECreative_Inventory_Groups brewingGroup[] = { eCreativeInventory_Brewing, eCreativeInventory_Potions_Level2_Extended, eCreativeInventory_Potions_Extended, eCreativeInventory_Potions_Level2, eCreativeInventory_Potions_Basic };
// Just use the text LT - the graphic doesn't fit in splitscreen either
// In 480p there's not enough room for the LT button, so use text instead
//if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen())
{
specs[eCreativeInventoryTab_Brewing] = new TabSpec(L"Brewing", IDS_GROUPNAME_POTIONS_480, 5, brewingGroup);
// Just use the text LT - the graphic doesn't fit in splitscreen either
// In 480p there's not enough room for the LT button, so use text instead
//if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen())
{
specs[eCreativeInventoryTab_Brewing] = new TabSpec(L"Brewing", IDS_GROUPNAME_POTIONS_480, 5, brewingGroup);
}
// else
// {
// specs[eCreativeInventoryTab_Brewing] = new TabSpec(L"icon_brewing.png", IDS_GROUPNAME_POTIONS, 1, brewingGroup, 4, potionsGroup);
// }
#ifndef _CONTENT_PACKAGE
ECreative_Inventory_Groups miscGroup[] = { eCreativeInventory_Misc };
ECreative_Inventory_Groups debugMiscGroup[] = { eCreativeInventory_ArtToolsMisc };
specs[eCreativeInventoryTab_Misc] = new TabSpec(L"Misc", IDS_GROUPNAME_MISCELLANEOUS, 1, miscGroup, 0, nullptr, 1, debugMiscGroup);
#else
ECreative_Inventory_Groups miscGroup[] = { eCreativeInventory_Misc };
specs[eCreativeInventoryTab_Misc] = new TabSpec(L"Misc", IDS_GROUPNAME_MISCELLANEOUS, 1, miscGroup);
#endif
}
// else
// {
// specs[eCreativeInventoryTab_Brewing] = new TabSpec(L"icon_brewing.png", IDS_GROUPNAME_POTIONS, 1, brewingGroup, 4, potionsGroup);
// }
#ifndef _CONTENT_PACKAGE
ECreative_Inventory_Groups miscGroup[] = {eCreativeInventory_Misc};
ECreative_Inventory_Groups debugMiscGroup[] = {eCreativeInventory_ArtToolsMisc};
specs[eCreativeInventoryTab_Misc] = new TabSpec(L"Misc", IDS_GROUPNAME_MISCELLANEOUS, 1, miscGroup, 0, nullptr, 1, debugMiscGroup);
#else
ECreative_Inventory_Groups miscGroup[] = {eCreativeInventory_Misc};
specs[eCreativeInventoryTab_Misc] = new TabSpec(L"Misc", IDS_GROUPNAME_MISCELLANEOUS, 1, miscGroup);
#endif
}
IUIScene_CreativeMenu::IUIScene_CreativeMenu()

View file

@ -1,6 +1,7 @@
#pragma once
#include "IUIScene_AbstractContainerMenu.h"
#include "../../../Minecraft.World/AbstractContainerMenu.h"
#include "../../../Minecraft.World/CustomPayloadPacket.h"
// 4J Stu - This class is for code that is common between XUI and Iggy
class SimpleContainer;
@ -100,10 +101,16 @@ protected:
bool m_bCarryingCreativeItem;
int m_creativeSlotX, m_creativeSlotY, m_inventorySlotX, m_inventorySlotY;
static void _wipeCreativeItems();
public:
static void staticCtor();
IUIScene_CreativeMenu();
static void loadFromLocal();
static void loadFromPacket(byteArray packetData);
static std::shared_ptr<CustomPayloadPacket> createUpdatePacket();
protected:
ECreativeInventoryTabs m_curTab;
int m_tabDynamicPos[eCreativeInventoryTab_COUNT];

View file

@ -5,6 +5,7 @@
#include "UIScene.h"
#include "UIControl_Slider.h"
#include "UIControl_TexturePackList.h"
#include "UIControl_CheckBox.h"
#include "UIControl_AchievementsList.h"
#include "UIScene_AchievementsMenu.h"
#include "../../../Minecraft.World/StringHelpers.h"
@ -836,6 +837,7 @@ void UIController::tickInput()
{
#ifdef _WINDOWS64
m_mouseClickConsumedByScene = false;
UIControl* currHitCtrl = NULL;
if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
{
UIScene *pScene = nullptr;
@ -1010,6 +1012,7 @@ void UIController::tickInput()
hitControlId = -1;
hitArea = INT_MAX;
hitCtrl = NULL;
hitCtrl = ctrl;
break; // ButtonList takes priority
}
if (type == UIControl::eAchievementList)
@ -1022,6 +1025,7 @@ void UIController::tickInput()
hitControlId = -1;
hitArea = INT_MAX;
hitCtrl = NULL;
hitCtrl = ctrl;
break;
}
if (type == UIControl::eTexturePackList)
@ -1070,6 +1074,8 @@ void UIController::tickInput()
}
}
}
currHitCtrl = hitCtrl;
UpdateCursorIcon(currHitCtrl);
}
}
@ -1196,6 +1202,27 @@ void UIController::tickInput()
}
}
void UIController::UpdateCursorIcon(UIControl *hitCtrl)
{
// from WinUser.h
if (hitCtrl && (hitCtrl->getControlType() == UIControl::eButton || hitCtrl->getControlType() == UIControl::eButtonList))
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_HAND));
else if (hitCtrl && (hitCtrl->getControlType() == UIControl::eSlider || hitCtrl->getControlType() == UIControl::eTexturePackList))
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_SIZEWE));
else if (hitCtrl && hitCtrl->getControlType() == UIControl::eTextInput)
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_IBEAM));
else if (hitCtrl && hitCtrl->getControlType() == UIControl::eCheckBox) // Show the cross sign shaped cursor only when the checkbox is disabled/grayed out
{
UIControl_CheckBox *pCheck = static_cast<UIControl_CheckBox *>(hitCtrl);
if (pCheck && !pCheck->IsEnabled())
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_NO));
else
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_HAND));
}
else
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_ARROW));
}
void UIController::handleInput()
{
// For each user, loop over each key type and send messages based on the state
@ -2078,6 +2105,7 @@ bool UIController::NavigateToScene(int iPad, EUIScene scene, void *initData, EUI
SetMenuDisplayed(menuDisplayedPad,true);
bool success = m_groups[static_cast<int>(group)]->NavigateToScene(iPad, scene, initData, layer);
if(success && group == eUIGroup_Fullscreen) setFullscreenMenuDisplayed(true);
UpdateCursorIcon(nullptr);
LeaveCriticalSection(&m_navigationLock);
timer.PrintElapsedTime(L"Navigate to scene");
@ -2117,6 +2145,7 @@ bool UIController::NavigateBack(int iPad, bool forceUsePad, EUIScene eScene, EUI
navComplete = m_groups[static_cast<int>(eUIGroup_Fullscreen)]->NavigateBack(iPad, eScene, eLayer);
if(!m_groups[static_cast<int>(eUIGroup_Fullscreen)]->GetMenuDisplayed()) SetMenuDisplayed(XUSER_INDEX_ANY,false);
}
UpdateCursorIcon(nullptr);
return navComplete;
}

View file

@ -262,6 +262,7 @@ public:
// INPUT
private:
void tickInput();
void UpdateCursorIcon(UIControl *hitCtrl);
void handleInput();
void handleKeyPress(unsigned int iPad, unsigned int key);

View file

@ -2,6 +2,12 @@
#include "UI.h"
#include "UIScene_Intro.h"
// HUCKLE - added below for joining game on launch
#ifdef _WINDOWS64
#include "../../Windows64/Network/WinsockNetLayer.h"
#include "../../User.h"
#endif
UIScene_Intro::UIScene_Intro(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
@ -104,6 +110,82 @@ void UIScene_Intro::handleInput(int iPad, int key, bool repeat, bool pressed, bo
}
#elif defined _XBOX_ONE
ui.NavigateToScene(0,eUIScene_MainMenu);
#elif defined _WINDOWS64
// HUCKLE - added this for auto joining servers on game launch
// THANKS so much to DrPerky and GeorgeV22 for helping with this bit, honestly got stuck for 4 hours :sob:
if(g_Win64MultiplayerJoin == true)
{
int primaryPad = ProfileManager.GetPrimaryPad();
if (!ProfileManager.IsSignedIn(primaryPad) || ProfileManager.IsGuest(primaryPad))
{
UINT uiIDA[1] = { IDS_OK };
ui.RequestErrorMessage(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 1);
ui.NavigateToScene(0, eUIScene_MainMenu);
return;
}
app.ClearSignInChangeUsersMask();
app.ReleaseSaveThumbnail();
ProfileManager.SetLockedProfile(primaryPad);
ProfileManager.QuerySigninStatus();
if (!app.DLCInstallProcessCompleted())
app.StartInstallDLCProcess(primaryPad);
Minecraft* pMinecraft = Minecraft::GetInstance();
pMinecraft->user->name = convStringToWstring(ProfileManager.GetGamertag(primaryPad));
app.ApplyGameSettingsChanged(primaryPad);
auto sessionInfo = std::make_unique<FriendSessionInfo>();
// label and name
const wchar_t* defaultName = L"";
size_t nameLen = wcslen(defaultName);
// ip and port
strncpy_s(sessionInfo->data.hostIP, g_Win64MultiplayerIP, sizeof(sessionInfo->data.hostIP) - 1);
sessionInfo->data.hostPort = g_Win64MultiplayerPort;
// display label
sessionInfo->displayLabel = new wchar_t[nameLen + 1];
wcscpy_s(sessionInfo->displayLabel, nameLen + 1, defaultName);
sessionInfo->displayLabelLength = static_cast<unsigned char>(nameLen);
sessionInfo->displayLabelViewableStartIndex = 0;
// name
wcsncpy_s(sessionInfo->data.hostName, XUSER_NAME_SIZE, defaultName, _TRUNCATE);
// session ids
sessionInfo->sessionId = static_cast<uint64_t>(inet_addr(g_Win64MultiplayerIP)) |
static_cast<uint64_t>(g_Win64MultiplayerPort) << 32;
// random props
sessionInfo->data.isReadyToJoin = true;
sessionInfo->data.isJoinable = true;
DWORD dwLocalUsersMask = 0;
dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(ProfileManager.GetPrimaryPad());
CGameNetworkManager::eJoinGameResult result = g_NetworkManager.JoinGame( sessionInfo.get(), dwLocalUsersMask );
if (result == CGameNetworkManager::JOINGAME_PENDING)
{
ConnectionProgressParams *param = new ConnectionProgressParams();
param->iPad = ProfileManager.GetPrimaryPad();
param->stringId = IDS_PROGRESS_CONNECTING;
param->showTooltips = true;
param->setFailTimer = false;
param->timerTime = 0;
param->cancelFunc = nullptr;
param->cancelFuncParam = nullptr;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_ConnectingProgress, param);
}
}
else
{
ui.NavigateToScene(0,eUIScene_SaveMessage);
}
#else
ui.NavigateToScene(0,eUIScene_SaveMessage);
#endif
@ -169,6 +251,82 @@ void UIScene_Intro::handleAnimationEnd()
{
m_bAnimationEnded = true;
}
#elif defined _WINDOWS64
// HUCKLE - added this for auto joining servers on game launch
// THANKS so much to DrPerky and GeorgeV22 for helping with this bit, honestly got stuck for 4 hours :sob:
if(g_Win64MultiplayerJoin == true)
{
int primaryPad = ProfileManager.GetPrimaryPad();
if (!ProfileManager.IsSignedIn(primaryPad) || ProfileManager.IsGuest(primaryPad))
{
UINT uiIDA[1] = { IDS_OK };
ui.RequestErrorMessage(IDS_MUST_SIGN_IN_TITLE, IDS_MUST_SIGN_IN_TEXT, uiIDA, 1);
ui.NavigateToScene(0, eUIScene_MainMenu);
return;
}
app.ClearSignInChangeUsersMask();
app.ReleaseSaveThumbnail();
ProfileManager.SetLockedProfile(primaryPad);
ProfileManager.QuerySigninStatus();
if (!app.DLCInstallProcessCompleted())
app.StartInstallDLCProcess(primaryPad);
Minecraft* pMinecraft = Minecraft::GetInstance();
pMinecraft->user->name = convStringToWstring(ProfileManager.GetGamertag(primaryPad));
app.ApplyGameSettingsChanged(primaryPad);
auto sessionInfo = std::make_unique<FriendSessionInfo>();
// label and name
const wchar_t* defaultName = L"";
size_t nameLen = wcslen(defaultName);
// ip and port
strncpy_s(sessionInfo->data.hostIP, g_Win64MultiplayerIP, sizeof(sessionInfo->data.hostIP) - 1);
sessionInfo->data.hostPort = g_Win64MultiplayerPort;
// display label
sessionInfo->displayLabel = new wchar_t[nameLen + 1];
wcscpy_s(sessionInfo->displayLabel, nameLen + 1, defaultName);
sessionInfo->displayLabelLength = static_cast<unsigned char>(nameLen);
sessionInfo->displayLabelViewableStartIndex = 0;
// name
wcsncpy_s(sessionInfo->data.hostName, XUSER_NAME_SIZE, defaultName, _TRUNCATE);
// session ids
sessionInfo->sessionId = static_cast<uint64_t>(inet_addr(g_Win64MultiplayerIP)) |
static_cast<uint64_t>(g_Win64MultiplayerPort) << 32;
// random props
sessionInfo->data.isReadyToJoin = true;
sessionInfo->data.isJoinable = true;
DWORD dwLocalUsersMask = 0;
dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(ProfileManager.GetPrimaryPad());
CGameNetworkManager::eJoinGameResult result = g_NetworkManager.JoinGame( sessionInfo.get(), dwLocalUsersMask );
if (result == CGameNetworkManager::JOINGAME_PENDING)
{
ConnectionProgressParams *param = new ConnectionProgressParams();
param->iPad = ProfileManager.GetPrimaryPad();
param->stringId = IDS_PROGRESS_CONNECTING;
param->showTooltips = true;
param->setFailTimer = false;
param->timerTime = 0;
param->cancelFunc = nullptr;
param->cancelFuncParam = nullptr;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_ConnectingProgress, param);
}
}
else
{
ui.NavigateToScene(0,eUIScene_SaveMessage);
}
#else
ui.NavigateToScene(0,eUIScene_SaveMessage);
#endif

View file

@ -6,7 +6,7 @@
#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
#include "..\..\..\Minecraft.World\net.minecraft.stats.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.effect.h"
#include "..\..\MultiplayerLocalPlayer.h"
#include "..\..\MultiPlayerLocalPlayer.h"
#include "..\..\Minecraft.h"
#include "..\..\Options.h"
#include "..\..\EntityRenderDispatcher.h"

View file

@ -82,6 +82,8 @@ UIScene_JoinMenu::UIScene_JoinMenu(int iPad, void *_initData, UILayer *parentLay
IggyValueSetBooleanRS(&path, visibleName, nullptr, false);
}
}
updateServerDescription();
}
}
}
@ -129,46 +131,46 @@ void UIScene_JoinMenu::updateTooltips()
void UIScene_JoinMenu::tick()
{
if( !m_friendInfoRequestIssued )
if (!m_friendInfoRequestIssued)
{
ui.NavigateToScene(m_iPad, eUIScene_Timer);
g_NetworkManager.GetFullFriendSessionInfo(m_selectedSession, &friendSessionUpdated, this);
m_friendInfoRequestIssued = true;
}
if( m_friendInfoUpdatedOK )
if (m_friendInfoUpdatedOK)
{
m_friendInfoUpdatedOK = false;
m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME),eControl_JoinGame);
m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME), eControl_JoinGame);
m_buttonListPlayers.init(eControl_GamePlayers);
m_buttonListPlayers.setYPos( m_buttonListPlayers.getYPos() + 300 );
m_buttonListPlayers.setYPos(m_buttonListPlayers.getYPos() + 300);
#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__
for( int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++ )
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++)
{
if( m_selectedSession->data.players[i] != nullptr )
if (m_selectedSession->data.players[i] != nullptr)
{
#ifndef _CONTENT_PACKAGE
if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards)))
#ifndef _CONTENT_PACKAGE
if (app.DebugSettingsOn() && (app.GetGameSettingsDebugMask() & (1L << eDebugSetting_DebugLeaderboards)))
{
m_buttonListPlayers.addItem(L"WWWWWWWWWWWWWWWW");
}
else
#endif
#endif
{
string playerName(m_selectedSession->data.players[i].getOnlineID());
#ifndef __PSVITA__
#ifndef __PSVITA__
// Append guest number (any players in an online game not signed into PSN are guests)
if( m_selectedSession->data.players[i].isSignedIntoPSN() == false )
if (m_selectedSession->data.players[i].isSignedIntoPSN() == false)
{
char suffix[5];
sprintf(suffix, " (%d)", m_selectedSession->data.players[i].getQuadrant() + 1);
playerName.append(suffix);
}
#endif
#endif
m_buttonListPlayers.addItem(playerName);
}
}
@ -179,9 +181,9 @@ void UIScene_JoinMenu::tick()
}
}
#elif defined(_DURANGO)
for( int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++ )
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++)
{
if ( m_selectedSession->searchResult.m_playerNames[i].size() )
if (m_selectedSession->searchResult.m_playerNames[i].size())
{
m_buttonListPlayers.addItem(m_selectedSession->searchResult.m_playerNames[i]);
}
@ -214,74 +216,74 @@ void UIScene_JoinMenu::tick()
m_labelLabels[eLabel_FireOn].init(app.GetString(IDS_LABEL_FIRE_SPREADS));
unsigned int uiGameHostSettings = m_selectedSession->data.m_uiGameHostSettings;
switch(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_Difficulty))
switch (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_Difficulty))
{
case Difficulty::EASY:
m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_EASY) );
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_EASY));
break;
case Difficulty::NORMAL:
m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_NORMAL) );
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_NORMAL));
break;
case Difficulty::HARD:
m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_HARD) );
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_HARD));
break;
case Difficulty::PEACEFUL:
default:
m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL) );
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL));
break;
}
int option = app.GetGameHostOption(uiGameHostSettings,eGameHostOption_GameType);
if(option == GameType::CREATIVE->getId())
int option = app.GetGameHostOption(uiGameHostSettings, eGameHostOption_GameType);
if (option == GameType::CREATIVE->getId())
{
m_labelValues[eLabel_GameType].init( app.GetString(IDS_CREATIVE) );
m_labelValues[eLabel_GameType].init(app.GetString(IDS_CREATIVE));
}
else if(option == GameType::ADVENTURE->getId())
else if (option == GameType::ADVENTURE->getId())
{
m_labelValues[eLabel_GameType].init( app.GetString(IDS_ADVENTURE) );
m_labelValues[eLabel_GameType].init(app.GetString(IDS_ADVENTURE));
}
else
{
m_labelValues[eLabel_GameType].init( app.GetString(IDS_SURVIVAL) );
m_labelValues[eLabel_GameType].init(app.GetString(IDS_SURVIVAL));
}
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_Gamertags)) m_labelValues[eLabel_GamertagsOn].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_GamertagsOn].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_Gamertags)) m_labelValues[eLabel_GamertagsOn].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_GamertagsOn].init(app.GetString(IDS_OFF));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_Structures)) m_labelValues[eLabel_Structures].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_Structures].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_Structures)) m_labelValues[eLabel_Structures].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_Structures].init(app.GetString(IDS_OFF));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_LevelType)) m_labelValues[eLabel_LevelType].init( app.GetString(IDS_LEVELTYPE_SUPERFLAT) );
else m_labelValues[eLabel_LevelType].init( app.GetString(IDS_LEVELTYPE_NORMAL) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_LevelType)) m_labelValues[eLabel_LevelType].init(app.GetString(IDS_LEVELTYPE_SUPERFLAT));
else m_labelValues[eLabel_LevelType].init(app.GetString(IDS_LEVELTYPE_NORMAL));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_PvP))m_labelValues[eLabel_PVP].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_PVP].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_PvP))m_labelValues[eLabel_PVP].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_PVP].init(app.GetString(IDS_OFF));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_TrustPlayers)) m_labelValues[eLabel_Trust].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_Trust].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_TrustPlayers)) m_labelValues[eLabel_Trust].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_Trust].init(app.GetString(IDS_OFF));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_TNT)) m_labelValues[eLabel_TNTOn].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_TNTOn].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_TNT)) m_labelValues[eLabel_TNTOn].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_TNTOn].init(app.GetString(IDS_OFF));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_FireSpreads)) m_labelValues[eLabel_FireOn].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_FireOn].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_FireSpreads)) m_labelValues[eLabel_FireOn].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_FireOn].init(app.GetString(IDS_OFF));
m_bIgnoreInput = false;
// Alert the app the we want to be informed of ethernet connections
app.SetLiveLinkRequired( true );
app.SetLiveLinkRequired(true);
TelemetryManager->RecordMenuShown(m_iPad, eUIScene_JoinMenu, 0);
addTimer(UPDATE_PLAYERS_TIMER_ID,UPDATE_PLAYERS_TIMER_TIME);
addTimer(UPDATE_PLAYERS_TIMER_ID, UPDATE_PLAYERS_TIMER_TIME);
}
if( m_friendInfoUpdatedERROR )
if (m_friendInfoUpdatedERROR)
{
m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME),eControl_JoinGame);
m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME), eControl_JoinGame);
m_buttonListPlayers.init(eControl_GamePlayers);
m_buttonListPlayers.setYPos( m_buttonListPlayers.getYPos() + 300 );
m_buttonListPlayers.setYPos(m_buttonListPlayers.getYPos() + 300);
m_labelLabels[eLabel_Difficulty].init(app.GetString(IDS_LABEL_DIFFICULTY));
m_labelLabels[eLabel_GameType].init(app.GetString(IDS_LABEL_GAME_TYPE));
@ -294,14 +296,14 @@ void UIScene_JoinMenu::tick()
m_labelLabels[eLabel_FireOn].init(app.GetString(IDS_LABEL_FIRE_SPREADS));
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL));
m_labelValues[eLabel_GameType].init( app.GetString(IDS_CREATIVE) );
m_labelValues[eLabel_GamertagsOn].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_Structures].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_LevelType].init( app.GetString(IDS_LEVELTYPE_NORMAL) );
m_labelValues[eLabel_PVP].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_Trust].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_TNTOn].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_FireOn].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_GameType].init(app.GetString(IDS_CREATIVE));
m_labelValues[eLabel_GamertagsOn].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_Structures].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_LevelType].init(app.GetString(IDS_LEVELTYPE_NORMAL));
m_labelValues[eLabel_PVP].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_Trust].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_TNTOn].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_FireOn].init(app.GetString(IDS_OFF));
m_friendInfoUpdatedERROR = false;
@ -310,9 +312,9 @@ void UIScene_JoinMenu::tick()
UINT uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
#ifdef _XBOX_ONE
ui.RequestErrorMessage( IDS_CONNECTION_FAILED, IDS_DISCONNECTED_SERVER_QUIT, uiIDA,1,m_iPad,ErrorDialogReturned,this);
ui.RequestErrorMessage(IDS_CONNECTION_FAILED, IDS_DISCONNECTED_SERVER_QUIT, uiIDA, 1, m_iPad, ErrorDialogReturned, this);
#else
ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA,1,m_iPad,ErrorDialogReturned,this);
ui.RequestErrorMessage(IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, m_iPad, ErrorDialogReturned, this);
#endif
}
@ -323,84 +325,7 @@ void UIScene_JoinMenu::tick()
{
IggyPlayerTickRS(s_movieServerDesc);
IggyValuePath *root = IggyPlayerRootPath(s_movieServerDesc);
if (root)
{
// scale the size before Iggy reads it
IggyValuePath textPath;
if (IggyValuePathMakeNameRef(&textPath, root, "HowToPlayText_0"))
{
IggyName nameX = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"x", -1);
IggyName nameY = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"y", -1);
IggyName nameW = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"width", -1);
IggyName nameH = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"height", -1);
if (m_loadedResolution == eSceneResolution_1080)
{
IggyValueSetF64RS(&textPath, nameX, nullptr, 333.0);// horizontal
IggyValueSetF64RS(&textPath, nameY, nullptr, 340.0);// vertical
IggyValueSetF64RS(&textPath, nameW, nullptr, 580.0);
IggyValueSetF64RS(&textPath, nameH, nullptr, 270.0);
}
else //720
{
IggyValueSetF64RS(&textPath, nameX, nullptr, 252.0);
IggyValueSetF64RS(&textPath, nameY, nullptr, 285.0);
IggyValueSetF64RS(&textPath, nameW, nullptr, 440.0);
IggyValueSetF64RS(&textPath, nameH, nullptr, 220.0);
}
}
// harcoded text for test it, later im gonna delete this and
// and convert it so that people can add their description when adding the server
if (!s_textInjected && s_funcLoadPage != 0)
{
IggyDataValue result;
IggyDataValue args[2];
args[0].type = IGGY_DATATYPE_number;
args[0].number = 0; // 0 is the what's new page on howtoplay don't change it
wstring testText = L"\nNothing yet...";
IggyStringUTF16 iggyStr;
wstring formattedText = app.FormatChatMessage(testText);
iggyStr.string = (IggyUTF16*)formattedText.c_str();
iggyStr.length = (unsigned int)formattedText.length();
args[1].type = IGGY_DATATYPE_string_UTF16;
args[1].string16 = iggyStr;
IggyResult res = IggyPlayerCallMethodRS(s_movieServerDesc, &result, root, s_funcLoadPage, 2, args);
if (res == IGGY_RESULT_SUCCESS)
{
s_textInjected = true;
}
}
// keeps the text fixed so it doesn't move from its place
IggyValuePath panelPath;
if (s_textInjected && IggyValuePathMakeNameRef(&panelPath, root, "DynamicHtmlText"))
{
IggyName nameX = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"x", -1);
IggyName nameY = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"y", -1);
IggyName nameW = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"width", -1);
IggyName nameH = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"height", -1);
if (m_loadedResolution == eSceneResolution_1080)
{
IggyValueSetF64RS(&panelPath, nameX, nullptr, 332.0);// horizontal
IggyValueSetF64RS(&panelPath, nameY, nullptr, 340.0);// vertical
IggyValueSetF64RS(&panelPath, nameW, nullptr, 580.0);
IggyValueSetF64RS(&panelPath, nameH, nullptr, 270.0);
}
else //720p
{
IggyValueSetF64RS(&panelPath, nameX, nullptr, 250.0);
IggyValueSetF64RS(&panelPath, nameY, nullptr, 290.0);
IggyValueSetF64RS(&panelPath, nameW, nullptr, 400.0);
IggyValueSetF64RS(&panelPath, nameH, nullptr, 230.0);
}
}
}
updateServerDescription();
}
}
#endif
@ -408,6 +333,88 @@ void UIScene_JoinMenu::tick()
UIScene::tick();
}
void UIScene_JoinMenu::updateServerDescription() {
IggyValuePath* root = IggyPlayerRootPath(s_movieServerDesc);
if (root)
{
// scale the size before Iggy reads it
IggyValuePath textPath;
if (IggyValuePathMakeNameRef(&textPath, root, "HowToPlayText_0"))
{
IggyName nameX = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"x", -1);
IggyName nameY = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"y", -1);
IggyName nameW = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"width", -1);
IggyName nameH = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"height", -1);
if (m_loadedResolution == eSceneResolution_1080)
{
IggyValueSetF64RS(&textPath, nameX, nullptr, 333.0);// horizontal
IggyValueSetF64RS(&textPath, nameY, nullptr, 340.0);// vertical
IggyValueSetF64RS(&textPath, nameW, nullptr, 580.0);
IggyValueSetF64RS(&textPath, nameH, nullptr, 270.0);
}
else //720
{
IggyValueSetF64RS(&textPath, nameX, nullptr, 252.0);
IggyValueSetF64RS(&textPath, nameY, nullptr, 285.0);
IggyValueSetF64RS(&textPath, nameW, nullptr, 440.0);
IggyValueSetF64RS(&textPath, nameH, nullptr, 220.0);
}
}
// harcoded text for test it, later im gonna delete this and
// and convert it so that people can add their description when adding the server
if (s_funcLoadPage != 0)
{
IggyDataValue result;
IggyDataValue args[2];
args[0].type = IGGY_DATATYPE_number;
args[0].number = 0; // 0 is the what's new page on howtoplay don't change it
wstring testText = L"\nNothing yet...";
IggyStringUTF16 iggyStr;
wstring formattedText = app.EscapeHTMLString(testText);
formattedText = app.FormatChatMessage(formattedText);
iggyStr.string = (IggyUTF16*)formattedText.c_str();
iggyStr.length = (unsigned int)formattedText.length();
args[1].type = IGGY_DATATYPE_string_UTF16;
args[1].string16 = iggyStr;
IggyResult res = IggyPlayerCallMethodRS(s_movieServerDesc, &result, root, s_funcLoadPage, 2, args);
if (res == IGGY_RESULT_SUCCESS)
{
s_textInjected = true;
}
}
// keeps the text fixed so it doesn't move from its place
IggyValuePath panelPath;
if (s_textInjected && IggyValuePathMakeNameRef(&panelPath, root, "DynamicHtmlText"))
{
IggyName nameX = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"x", -1);
IggyName nameY = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"y", -1);
IggyName nameW = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"width", -1);
IggyName nameH = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"height", -1);
if (m_loadedResolution == eSceneResolution_1080)
{
IggyValueSetF64RS(&panelPath, nameX, nullptr, 332.0);// horizontal
IggyValueSetF64RS(&panelPath, nameY, nullptr, 340.0);// vertical
IggyValueSetF64RS(&panelPath, nameW, nullptr, 580.0);
IggyValueSetF64RS(&panelPath, nameH, nullptr, 270.0);
}
else //720p
{
IggyValueSetF64RS(&panelPath, nameX, nullptr, 250.0);
IggyValueSetF64RS(&panelPath, nameY, nullptr, 290.0);
IggyValueSetF64RS(&panelPath, nameW, nullptr, 400.0);
IggyValueSetF64RS(&panelPath, nameH, nullptr, 230.0);
}
}
}
}
void UIScene_JoinMenu::friendSessionUpdated(bool success, void *pParam)
{
UIScene_JoinMenu *scene = static_cast<UIScene_JoinMenu *>(pParam);

View file

@ -93,6 +93,8 @@ protected:
// TODO: This should be pure virtual in this class
virtual wstring getMoviePath();
void updateServerDescription();
public:
public:
// INPUT

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -13,11 +13,19 @@
#include "../Minecraft.World/SkullTileEntity.h"
#include "../Minecraft.World/LivingEntity.h"
#include "../Minecraft.World/Facing.h"
#include "../Minecraft.Client/SimpleIcon.h"
#include "../Minecraft.World/AirTile.h"
CustomHeadLayer::CustomHeadLayer(ModelPart* headPart, LivingEntityRenderer* parentRenderer)
: headPart(headPart), parentRenderer(parentRenderer)
{
tileRenderer = new TileRenderer();
}
CustomHeadLayer::~CustomHeadLayer() {
delete tileRenderer;
}
int CustomHeadLayer::colorsOnDamage()
@ -90,12 +98,136 @@ void CustomHeadLayer::render(shared_ptr<LivingEntity> mob,
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
Minecraft* mc = Minecraft::GetInstance();
if (mc)
{
auto* iihr = mc->getItemInHandRenderer();
if (iihr)
iihr->renderItem(mob, helmet, 0, true);
// 4J - code borrowed from render method below, although not factoring in brightness as that should already be being taken into account
// by texture lighting. This is for colourising things held in 3rd person view.
if ((item != nullptr)) {
int col = Item::items[item->id]->getColor(helmet, 0);
float red = ((col >> 16) & 0xff) / 255.0f;
float g = ((col >> 8) & 0xff) / 255.0f;
float b = ((col) & 0xff) / 255.0f;
glColor4f(red, g, b, 1);
}
Minecraft* minecraft = Minecraft::GetInstance();
glPushMatrix();
Tile* tile = Tile::tiles[item->id];
if ((item->getIconType() == Icon::TYPE_TERRAIN && tile != nullptr && TileRenderer::canRender(tile->getRenderShape())) && item->id != AirTile::barrier_Id)
{
MemSect(31);
minecraft->textures->bindTexture(minecraft->textures->getTextureLocation(Icon::TYPE_TERRAIN));
MemSect(0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
tileRenderer->renderTile(Tile::tiles[item->id], helmet->getAuxValue(), SharedConstants::TEXTURE_LIGHTING ? 1.0f : mob->getBrightness(1)); // 4J - change brought forward from 1.8.2
glDisable(GL_BLEND);
}
else
{
MemSect(31);
Icon* icon = mob->getItemInHandIcon(helmet, 0);
if (icon == nullptr)
{
glPopMatrix();
MemSect(0);
return;
}
bool bIsTerrain = item->getIconType() == Icon::TYPE_TERRAIN;
minecraft->textures->bindTexture(minecraft->textures->getTextureLocation(item->getIconType()));
MemSect(0);
Tesselator* t = Tesselator::getInstance();
// Consider forcing the mipmap LOD level to use, if this is to be rendered from a larger than standard source texture.
int iconWidth = icon->getWidth();
int LOD = -1; // Default to not doing anything special with LOD forcing
if (iconWidth == 32)
{
LOD = 1; // Force LOD level 1 to achieve texture reads from 256x256 map
}
else if (iconWidth == 64)
{
LOD = 2; // Force LOD level 2 to achieve texture reads from 256x256 map
}
RenderManager.StateSetForceLOD(LOD);
// 4J Original comment
// Yes, these are backwards.
// No, I don't know why.
// 4J Stu - Make them the right way round...u coords were swapped
float u0 = icon->getU0();
float u1 = icon->getU1();
float v0 = icon->getV0();
float v1 = icon->getV1();
float xo = 0.0f;
float yo = 0.3f;
// Re position height of held item if skin is small
if (mob->getAnimOverrideBitmask() & (1 << HumanoidModel::eAnim_SmallModel))
{
if (mob->isRiding())
{
std::shared_ptr<Entity> ridingEntity = mob->riding;
if (ridingEntity != nullptr) // Safety check;
{
yo += 0.3f; // reverts the change in Boat.cpp for smaller models.
}
}
}
glEnable(GL_RESCALE_NORMAL);
glTranslatef(-xo, -yo, 0);
glScalef(1, 1, 1);
glRotatef(90, 0, 1, 0);
glTranslatef(-7.5f / 16.0f, 9 / 16.0f, 0);
glTranslatef(0, 0.03f, 0);
float dd = 1 / 16.0f;
ItemInHandRenderer::renderItem3D(t, u0, v0, u1, v1, icon->getSourceWidth(), icon->getSourceHeight(), 1 / 16.0f, false, bIsTerrain);
if (item != nullptr && helmet->isFoil())
{
glDepthFunc(GL_EQUAL);
glDisable(GL_LIGHTING);
minecraft->textures->bindTexture(&ItemInHandRenderer::ENCHANT_GLINT_LOCATION);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR, GL_ONE);
float br = 0.76f;
glColor4f(0.5f * br, 0.25f * br, 0.8f * br, 1); // MGH - for some reason this colour isn't making it through to the render, so I've added to the tesselator for the glint geom above
glMatrixMode(GL_TEXTURE);
glPushMatrix();
float ss = 1 / 8.0f;
glScalef(ss, ss, ss);
float sx = Minecraft::currentTimeMillis() % (3000) / (3000.0f) * 8;
glTranslatef(sx, 0, 0);
glRotatef(-50, 0, 0, 1);
ItemInHandRenderer::renderItem3D(t, 0, 0, 1, 1, 256, 256, 1 / 16.0f, true, bIsTerrain);
glPopMatrix();
glPushMatrix();
glScalef(ss, ss, ss);
sx = System::currentTimeMillis() % (3000 + 1873) / (3000 + 1873.0f) * 8;
glTranslatef(-sx, 0, 0);
glRotatef(10, 0, 0, 1);
ItemInHandRenderer::renderItem3D(t, 0, 0, 1, 1, 256, 256, 1 / 16.0f, true, bIsTerrain);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glDisable(GL_BLEND);
glEnable(GL_LIGHTING);
glDepthFunc(GL_LEQUAL);
}
RenderManager.StateSetForceLOD(-1);
glDisable(GL_RESCALE_NORMAL);
}
glPopMatrix();
}
}

View file

@ -4,14 +4,17 @@
class ModelPart;
class LivingEntity;
class LivingEntityRenderer;
class TileRenderer;
class CustomHeadLayer : public RenderLayer {
public:
ModelPart* headPart;
LivingEntityRenderer* parentRenderer;
TileRenderer* tileRenderer;
CustomHeadLayer(ModelPart* headPart, LivingEntityRenderer* parentRenderer);
virtual ~CustomHeadLayer() {}
virtual ~CustomHeadLayer();
virtual int colorsOnDamage() override;
virtual void render(shared_ptr<LivingEntity> mob,

View file

@ -148,6 +148,7 @@ GameRenderer::GameRenderer(Minecraft *mc)
itemInHandRenderer = nullptr;
// 4J-PB - set up the local players iteminhand renderers here - needs to be done with lighting enabled so that the render geometry gets compiled correctly
#ifndef MINECRAFT_SERVER_BUILD
glEnable(GL_LIGHTING);
mc->localitemInHandRenderers[0] = new ItemInHandRenderer(mc);//itemInHandRenderer;
mc->localitemInHandRenderers[1] = new ItemInHandRenderer(mc);
@ -170,7 +171,9 @@ GameRenderer::GameRenderer(Minecraft *mc)
for(int i=0;i<NUM_LIGHT_TEXTURES;i++)
lightPixels[i] = intArray(16*16);
#endif
#endif
#ifndef MINECRAFT_SERVER_BUILD
#ifdef MULTITHREAD_ENABLE
m_updateEvents = new C4JThread::EventArray(eUpdateEventCount, C4JThread::EventArray::e_modeAutoClear);
m_updateEvents->Set(eUpdateEventIsFinished);
@ -183,6 +186,7 @@ GameRenderer::GameRenderer(Minecraft *mc)
m_updateThread->SetProcessor(CPU_CORE_CHUNK_UPDATE);
m_updateThread->Run();
#endif
#endif
}
// 4J Stu Added to go with 1.8.2 change

View file

@ -8,6 +8,15 @@ GuiParticles::GuiParticles(Minecraft *mc)
this->mc = mc;
}
GuiParticles::~GuiParticles()
{
for (GuiParticle *gp : particles)
{
delete gp;
}
particles.clear();
}
void GuiParticles::tick()
{
for (unsigned int i = 0; i < particles.size(); i++)
@ -19,6 +28,7 @@ void GuiParticles::tick()
if (gp->removed)
{
delete gp;
particles.erase(particles.begin()+i);
i--;
}

View file

@ -13,6 +13,7 @@ private:
public:
GuiParticles(Minecraft *mc);
~GuiParticles();
void tick();
void add(GuiParticle *guiParticle);
void render(float a);

View file

@ -110,81 +110,75 @@ void ItemFrameRenderer::drawFrame(shared_ptr<ItemFrame> itemFrame)
void ItemFrameRenderer::drawItem(shared_ptr<ItemFrame> entity)
{
Minecraft *pMinecraft=Minecraft::GetInstance();
shared_ptr<ItemInstance> instance = entity->getItem();
if (instance == nullptr) return;
shared_ptr<ItemInstance> instance = entity->getItem();
if (instance == nullptr) return;
shared_ptr<ItemEntity> itemEntity = std::make_shared<ItemEntity>(entity->level, 0, 0, 0, instance);
itemEntity->getItem()->count = 1;
itemEntity->bobOffs = 0;
shared_ptr<ItemEntity> itemEntity = std::make_shared<ItemEntity>(entity->level, 0, 0, 0, instance);
itemEntity->getItem()->count = 1;
itemEntity->bobOffs = 0;
glPushMatrix();
glPushMatrix();
glTranslatef((-7.25f / 16.0f) * Direction::STEP_X[entity->dir], -0.18f, (-7.25f / 16.0f) * Direction::STEP_Z[entity->dir]);
glRotatef(180 + entity->yRot, 0, 1, 0);
glRotatef(-90 * entity->getRotation(), 0, 0, 1);
glRotatef(180.0f + entity->yRot, 0, 1, 0);
glTranslatef(0.0f, 0.0f, -0.4375f);
switch (entity->getRotation())
{
case 1:
glTranslatef(-0.16f, -0.16f, 0);
break;
case 2:
glTranslatef(0, -0.32f, 0);
break;
case 3:
glTranslatef(0.16f, -0.16f, 0);
break;
}
int rotation = entity->getRotation();
bool isMap = (itemEntity->getItem()->getItem() == Item::map);
int effectiveRotation = isMap ? 2 * (rotation % 4) : rotation;
if (itemEntity->getItem()->getItem() == Item::map)
{
entityRenderDispatcher->textures->bindTexture(&MAP_BACKGROUND_LOCATION);
Tesselator *t = Tesselator::getInstance();
glRotatef(-45.0f * effectiveRotation, 0, 0, 1);
glTranslatef(0.0f, -0.41f/2, 0.0f);
glRotatef(180, 0, 1, 0);
glRotatef(180, 0, 0, 1);
glScalef(1.0f / 128.0f, 1.0f / 128.0f, 1.0f / 128.0f);
glTranslatef(-64.0f, -87.0f, -3.0f);
glNormal3f(0, 0, -1);
t->begin();
int vo = 7;
t->vertexUV(0.0f, 128.0f, 0.0f, 0.0f, 1.0f);
t->vertexUV(128.0f, 128.0f, 0.0f, 1.0f, 1.0f);
t->vertexUV(128.0f, 0.0f, 0.0f, 1.0f, 0.0f);
t->vertexUV(0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
t->end();
if (isMap)
{
//entityRenderDispatcher->textures->bindTexture(&MAP_BACKGROUND_LOCATION);
//Tesselator *t = Tesselator::getInstance();
shared_ptr<MapItemSavedData> data = Item::map->getSavedData(itemEntity->getItem(), entity->level);
if (data != nullptr)
{
entityRenderDispatcher->itemInHandRenderer->minimap->render(nullptr, entityRenderDispatcher->textures, data, entity->entityId);
}
}
else
{
if (itemEntity->getItem()->getItem() == Item::compass)
{
CompassTexture *ct = CompassTexture::instance;
double compassRot = ct->rot;
double compassRotA = ct->rota;
ct->rot = 0;
ct->rota = 0;
ct->updateFromPosition(entity->level, entity->x, entity->z, Mth::wrapDegrees( static_cast<float>(180 + entity->dir * 90) ), false, true);
ct->rot = compassRot;
ct->rota = compassRotA;
}
glRotatef(180, 0, 1, 0);
glRotatef(180, 0, 0, 1);
glScalef(1.0f / 128.0f, 1.0f / 128.0f, 1.0f / 128.0f);
glTranslatef(-64.0f, -87.0f, -3.0f);
EntityRenderDispatcher::instance->render(itemEntity, 0, 0, 0, 0, 0, true);
//glNormal3f(0, 0, -1);
//t->begin();
//t->vertexUV(0.0f, 128.0f, 0.0f, 0.0f, 1.0f);
//t->vertexUV(128.0f, 128.0f, 0.0f, 1.0f, 1.0f);
//t->vertexUV(128.0f, 0.0f, 0.0f, 1.0f, 0.0f);
//t->vertexUV(0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
//t->end();
if (itemEntity->getItem()->getItem() == Item::compass)
{
CompassTexture *ct = CompassTexture::instance;
ct->cycleFrames();
}
}
glPopMatrix();
shared_ptr<MapItemSavedData> data = Item::map->getSavedData(itemEntity->getItem(), entity->level);
if (data != nullptr)
{
entityRenderDispatcher->itemInHandRenderer->minimap->render(
nullptr, entityRenderDispatcher->textures, data, entity->entityId);
}
}
else
{
if (itemEntity->getItem()->getItem() == Item::compass)
{
CompassTexture *ct = CompassTexture::instance;
double compassRot = ct->rot;
double compassRotA = ct->rota;
ct->rot = 0;
ct->rota = 0;
ct->updateFromPosition(entity->level, entity->x, entity->z,
Mth::wrapDegrees(static_cast<float>(180 + entity->dir * 90)), false, true);
ct->rot = compassRot;
ct->rota = compassRotA;
}
EntityRenderDispatcher::instance->render(itemEntity, 0, 0, 0, 0, 0, true);
if (itemEntity->getItem()->getItem() == Item::compass)
{
CompassTexture *ct = CompassTexture::instance;
ct->cycleFrames();
}
}
glPopMatrix();
}

View file

@ -555,7 +555,7 @@ void LivingEntityRenderer::renderName(shared_ptr<LivingEntity> mob, double x, do
bool LivingEntityRenderer::shouldShowName(shared_ptr<LivingEntity> mob)
{
return Minecraft::renderNames() && mob != entityRenderDispatcher->cameraEntity && !mob->isInvisibleTo(Minecraft::GetInstance()->player) && mob->rider.lock() == nullptr;
return Minecraft::renderNames() && mob != entityRenderDispatcher->cameraEntity && (!mob->isInvisibleTo(Minecraft::GetInstance()->player) || mob->isCustomNameVisible()) && mob->rider.lock() == nullptr;
}
void LivingEntityRenderer::renderNameTags(shared_ptr<LivingEntity> mob, double x, double y, double z, const wstring &msg, float scale, double dist)

View file

@ -10,7 +10,14 @@ public:
int id;
bool isLoaded;
int ticksSinceLastUse;
static const int UNUSED_TICKS_TO_FREE = 20;
// @CDevJoud
// changing the lifetime of the texture from 20 ticks(1 sec) to 200 ticks (10 sec)
// as it helps the texture to have longer lifetime and reducing the usage of loadTexture for every second/frame
// note that we dont remove the code that removes the textures from `tick()` as it is required in memory limited environment such as older Consoles(PS3/XBOX360)
static const int UNUSED_TICKS_TO_FREE = 200;
//default ctor for int Texture::getHeight(const wstring& url, int backup)
MemTexture() = default;
MemTexture(const wstring& _name, PBYTE pbData, DWORD dwBytes, MemTextureProcessor *processor);
~MemTexture();

View file

@ -526,9 +526,10 @@ LevelStorageSource *Minecraft::getLevelSource()
void Minecraft::setScreen(Screen *screen)
{
if (this->screen != nullptr)
Screen *oldScreen = this->screen;
if (oldScreen != nullptr)
{
this->screen->removed();
oldScreen->removed();
}
#ifdef _WINDOWS64
@ -1268,6 +1269,8 @@ void Minecraft::applyFrameMouseLook()
void Minecraft::run_middle()
{
pause = app.IsAppPaused();
static int64_t lastTime = 0;
static bool bFirstTimeIntoGame = true;
static bool bAutosaveTimerSet=false;
@ -4436,6 +4439,8 @@ void Minecraft::setLevel(MultiPlayerLevel *level, int message /*=-1*/, shared_pt
// 4J If we are setting the level to nullptr then we are exiting, so delete the levels
if( level == nullptr )
{
if (soundEngine) soundEngine->stopElytraSound();
if(levels[0]!=nullptr)
{
delete levels[0];

View file

@ -1848,7 +1848,7 @@ void MinecraftServer::run(int64_t seed, void *lpParameter)
lastTime = now;
// 4J Added ability to pause the server
if( !m_isServerPaused )
if( !m_isServerPaused && !app.IsAppPaused() )
{
bool didTick = false;
if (levels[0]->allPlayersAreSleeping())
@ -2017,7 +2017,11 @@ void MinecraftServer::run(int64_t seed, void *lpParameter)
QueryPerformanceCounter(&asAfterRules);
#endif
#ifdef MINECRAFT_SERVER_BUILD
levels[0]->saveToDisc(nullptr, true);
#else
levels[0]->saveToDisc(Minecraft::GetInstance()->progressRenderer, true);
#endif
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
QueryPerformanceCounter(&asAfterFlush);

View file

@ -266,7 +266,7 @@ private:
#endif
#endif
bool IsServerPaused() { return m_isServerPaused; }
private:
// 4J Added
@ -291,6 +291,7 @@ public:
const wstring& getSaveFolderName() const { return m_saveFolderName; }
void Suspend();
bool IsSuspending();
bool IsServerPaused() { return m_isServerPaused; }
// 4J Stu - A load of functions were all added in 1.0.1 in the ServerInterface, but I don't think we need any of them
};

View file

@ -183,7 +183,7 @@ void PlayerConnection::tick()
// Ensure server-side player tick runs even when no move packet was received this tick.
// Without this, environmental damage (drowning, fire, lava) is never applied to clients
// that don't send frequent move packets.
if (!didTick && player != nullptr)
if (!didTick && player != nullptr && !server->IsServerPaused() && !app.IsAppPaused())
{
player->doTick(false);
}
@ -1046,6 +1046,13 @@ void PlayerConnection::handleCommand(const wstring& message)
ss >> cmd;
if (cmd == L"tp" || cmd == L"teleport")
{
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_Teleport))
{
warn(L"You do not have permission to use this command.");
@ -1138,6 +1145,13 @@ if (cmd == L"tp" || cmd == L"teleport")
}
} else if (cmd == L"time")
{
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_Time))
{
warn(L"You do not have permission to use this command.");
@ -1268,15 +1282,44 @@ if (cmd == L"tp" || cmd == L"teleport")
}
else if (cmd == L"kill")
{
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_Kill))
{
warn(L"You do not have permission to use this command.");
return;
}
server->getCommandDispatcher()->performCommand(player, eGameCommand_Kill, byteArray());
wstring targetName;
ss >> targetName;
if (targetName.empty())
{
server->getCommandDispatcher()->performCommand(player, eGameCommand_Kill, byteArray());
}
else
{
ByteArrayOutputStream baos;
DataOutputStream dos(&baos);
dos.writeUTF(targetName);
byteArray data = baos.toByteArray();
server->getCommandDispatcher()->performCommand(player, eGameCommand_Kill, data);
}
}
else if (cmd == L"toggledownfall")
{
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_ToggleDownfall))
{
warn(L"You do not have permission to use this command.");
@ -1285,6 +1328,14 @@ if (cmd == L"tp" || cmd == L"teleport")
shared_ptr<GameCommandPacket> packet = ToggleDownfallCommand::preparePacket();
server->getCommandDispatcher()->performCommand(player, eGameCommand_ToggleDownfall, packet->data);
} else if (cmd == L"gamemode") {
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_GameMode))
{
warn(L"You do not have permission to use this command.");
@ -1323,6 +1374,13 @@ if (cmd == L"tp" || cmd == L"teleport")
shared_ptr<GameCommandPacket> packet = GameModeCommand::preparePacket(target, mode);
server->getCommandDispatcher()->performCommand(player, eGameCommand_GameMode, packet->data);
} else if (cmd == L"give") {
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_Give))
{
warn(L"You do not have permission to use this command.");
@ -1868,6 +1926,8 @@ void PlayerConnection::handleGameCommand(shared_ptr<GameCommandPacket> packet)
player->getName().c_str(), player->isModerator() ? 1 : 0, isHost ? 1 : 0,
static_cast<int>(packet->command));
#endif
MinecraftServer::getInstance()->getCommandDispatcher()->performCommand(player, packet->command, packet->data);
}
@ -2417,7 +2477,7 @@ void PlayerConnection::handleCustomPayload(shared_ptr<CustomPayloadPacket> custo
player->inventory->setItem(player->inventory->selected, sentItem);
}
}
else if (CustomPayloadPacket::QUICK_EQUIP_PACKET.compare(customPayloadPacket->identifier) == 0) {
/*else if (CustomPayloadPacket::QUICK_EQUIP_PACKET.compare(customPayloadPacket->identifier) == 0) {
//ByteArrayInputStream bais(customPayloadPacket->data);
//DataInputStream input(&bais);
//shared_ptr<ItemInstance> sentItem = Packet::readItem(&input);
@ -2448,7 +2508,7 @@ void PlayerConnection::handleCustomPayload(shared_ptr<CustomPayloadPacket> custo
//PlayerList* playerList = MinecraftServer::getInstance()->getPlayers();
//playerList->broadcastAll(std::make_shared<SetEquippedItemPacket>(player->entityId, slot, sentItem));
}
}*/
else if (CustomPayloadPacket::TRADER_SELECTION_PACKET.compare(customPayloadPacket->identifier) == 0)
{
ByteArrayInputStream bais(customPayloadPacket->data);

View file

@ -37,6 +37,8 @@
#include "Common/Network/Sony/NetworkPlayerSony.h"
#endif
#include "../Minecraft.World/Recipes.h"
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
#include "../Minecraft.Server/Access/Access.h"
#include "../Minecraft.Server/Common/StringUtils.h"
@ -51,6 +53,7 @@ extern bool g_Win64DedicatedServer;
static unsigned int s_playerListTickCount = 0;
static const int kIdentityResponseGraceTicks = 200; // 10 seconds at 20 TPS
#endif
#include "../Minecraft.Client/Common/UI/IUIScene_CreativeMenu.h"
// 4J - this class is fairly substantially altered as there didn't seem any point in porting code for banning, whitelisting, ops etc.
@ -300,6 +303,9 @@ bool PlayerList::placeNewPlayer(Connection *connection, shared_ptr<ServerPlayer>
app.DebugPrintf("RECONNECT: placeNewPlayer smallId=%d entityId=%d dim=%d\n",
newSmallId, player->entityId, level->dimension->id);
playerConnection->send(Recipes::getInstance()->createUpdatePacket());
playerConnection->send(IUIScene_CreativeMenu::createUpdatePacket());
playerConnection->send(std::make_shared<LoginPacket>(L"", player->entityId, level->getLevelData()->getGenerator(),
level->getSeed(),
player->gameMode->getGameModeForPlayer()->getId(),

View file

@ -23,6 +23,18 @@ Screen::Screen() // 4J added
clickedButton = nullptr;
}
Screen::~Screen()
{
delete particles;
particles = nullptr;
for (Button *button : buttons)
{
delete button;
}
buttons.clear();
}
void Screen::render(int xm, int ym, float a)
{
for (Button* button : buttons)

View file

@ -22,6 +22,7 @@ public:
GuiParticles *particles;
Screen(); // 4J added
virtual ~Screen();
virtual void render(int xm, int ym, float a);
protected:
virtual void keyPressed(wchar_t eventCharacter, int eventKey);

View file

@ -1683,14 +1683,15 @@ void ServerLevel::flagEntitiesToBeRemoved(unsigned int *flags, bool *removedFoun
}
void ServerLevel::sendParticles(const ParticleType* type, bool longDistance, double x, double y, double z, int count, double dx, double dy, double dz, double speed, arrayWithLength<int> data)
{
wchar_t buf[32];
swprintf_s(buf, L"%d", type->getId());
auto packet = make_shared<LevelParticlesPacket>(
type,
longDistance,
buf,
(float)x, (float)y, (float)z,
(float)dx, (float)dy, (float)dz,
(float)speed,
count,
data
count
);
for (auto const& p : players)

View file

@ -138,12 +138,21 @@ private:
// 4J - added for implementation of finite limit to number of item entities, tnt and falling block entities
public:
static const int MAX_HANGING_ENTITIES = 400;
static const int MAX_ITEM_ENTITIES = 200;
static const int MAX_ARROW_ENTITIES = 200;
static const int MAX_EXPERIENCEORB_ENTITIES = 50;
static const int MAX_PRIMED_TNT = 20;
static const int MAX_FALLING_TILE = 20;
static const int MAX_HANGING_ENTITIES = 800;
static const int MAX_ITEM_ENTITIES = 400;
static const int MAX_ARROW_ENTITIES = 400;
static const int MAX_EXPERIENCEORB_ENTITIES = 100;
static const int MAX_PRIMED_TNT = 40;
static const int MAX_FALLING_TILE = 40;
//static const int MAX_HANGING_ENTITIES = 400;
//static const int MAX_ITEM_ENTITIES = 200;
//static const int MAX_ARROW_ENTITIES = 200;
//static const int MAX_EXPERIENCEORB_ENTITIES = 50;
//static const int MAX_PRIMED_TNT = 20;
//static const int MAX_FALLING_TILE = 20;
int m_primedTntCount;
int m_fallingTileCount;

View file

@ -850,8 +850,10 @@ void ServerPlayer::die(DamageSource *source)
bool ServerPlayer::hurt(DamageSource *dmgSource, float dmg)
{
if (isInvulnerable()) return false;
if (gameMode == nullptr||gameMode->isCreative()) return false;
if (isInvulnerable() && dmgSource != DamageSource::outOfWorld) return false;
if (gameMode == nullptr || gameMode->isCreative()) {
if (dmgSource != DamageSource::outOfWorld) return false;
}
// 4J: Not relevant to console servers
// Allow falldamage on dedicated pvpservers -- so people cannot cheat their way out of 'fall traps'

View file

@ -1256,8 +1256,14 @@ int Textures::getHeight(const wstring& url, int backup)
if (img)
{
MemTexture* _texture = new MemTexture();
_texture->loadedImage = img;
_texture->isLoaded = true;
_texture->id = getTexture(_texture->loadedImage, C4JRender::TEXTURE_FORMAT_RxGyBzAw, MIPMAP);
int h = img->getHeight();
delete img;
//delete img; // commenting this out and inserting the loaded texture to memTextures unordered_map
this->memTextures[url] = _texture;
return h;
}

View file

@ -290,24 +290,53 @@ void TrackedEntity::tick(EntityTracker *tracker, vector<shared_ptr<Player> > *pl
wasRiding = false;
}
else
{
bool rot = abs(yRotn - yRotp) >= TOLERANCE_LEVEL || abs(xRotn - xRotp) >= TOLERANCE_LEVEL;
if (rot)
{
// 4J: Changed this to use deltas
broadcast(std::make_shared<MoveEntityPacket::Rot>(e->entityId, static_cast<byte>(yRota), static_cast<byte>(xRota)));
yRotp = yRotn;
xRotp = xRotn;
}
{
// the entity have a rider, the code didnt send position updates,
// causing desync between client and server when boat was spritning.
xp = Mth::floor(e->x * 32.0);
yp = Mth::floor(e->y * 32.0);
zp = Mth::floor(e->z * 32.0);
bool rot = abs(yRotn - yRotp) >= TOLERANCE_LEVEL || abs(xRotn - xRotp) >= TOLERANCE_LEVEL;
if (rot)
{
broadcast(std::make_shared<MoveEntityPacket::Rot>(e->entityId, static_cast<byte>(yRota), static_cast<byte>(xRota)));
yRotp = yRotn;
xRotp = xRotn;
}
sendDirtyEntityData();
int xn = Mth::floor(e->x * 32.0);
int yn = Mth::floor(e->y * 32.0);
int zn = Mth::floor(e->z * 32.0);
int xa = xn - xp;
int ya = yn - yp;
int za = zn - zp;
wasRiding = true;
}
// send only if the boat moved enough
// or 3 seconds periodically
bool pos = abs(xa) >= TOLERANCE_LEVEL || abs(ya) >= TOLERANCE_LEVEL || abs(za) >= TOLERANCE_LEVEL
|| (tickCount % (SharedConstants::TICKS_PER_SECOND * 3) == 0);
if (pos)
{
// if deltapos is too much big use teleport.
if (xa < -128 || xa >= 128 || ya < -128 || ya >= 128 || za < -128 || za >= 128)
{
broadcast(std::make_shared<TeleportEntityPacket>(e->entityId, xn, yn, zn,
static_cast<byte>(yRotn), static_cast<byte>(xRotn)));
}
else
{
// small movement, delta
broadcast(std::make_shared<MoveEntityPacket::Pos>(e->entityId,
static_cast<char>(xa), static_cast<char>(ya), static_cast<char>(za)));
}
xp = xn;
yp = yn;
zp = zn;
}
sendDirtyEntityData();
wasRiding = true;
}
int yHeadRot = Mth::floor(e->getYHeadRot() * 256 / 360);
if (abs(yHeadRot - yHeadRotp) >= TOLERANCE_LEVEL)

View file

@ -390,6 +390,20 @@ float KeyboardMouseInput::GetLookY(float sensitivity) const
return static_cast<float>(-m_mouseDeltaY) * sensitivity;
}
void KeyboardMouseInput::SetCursorIcon(LPCWSTR cursorName)
{
HCURSOR hCursor = LoadCursorW(nullptr, cursorName);
if (hCursor)
{
SetCursor(hCursor);
if (g_hWnd)
{
SetClassLongPtrW(g_hWnd, GCLP_HCURSOR, (LONG_PTR)hCursor);
}
}
}
void KeyboardMouseInput::OnChar(wchar_t c)
{
int next = (m_charBufferHead + 1) % CHAR_BUFFER_SIZE;

View file

@ -104,6 +104,8 @@ public:
float GetLookX(float sensitivity) const;
float GetLookY(float sensitivity) const;
void SetCursorIcon(LPCWSTR cursorName);
private:
bool m_keyDown[MAX_KEYS];
bool m_keyDownPrev[MAX_KEYS];

View file

@ -115,6 +115,7 @@ bool WinsockNetLayer::s_clientKeyStored = false;
bool g_Win64MultiplayerHost = false;
bool g_Win64MultiplayerJoin = false;
bool g_Win64MultiplayerQuitOnDisconnect = false;
int g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT;
char g_Win64MultiplayerIP[256] = "127.0.0.1";
bool g_Win64DedicatedServer = false;

View file

@ -227,6 +227,7 @@ public:
extern bool g_Win64MultiplayerHost;
extern bool g_Win64MultiplayerJoin;
extern bool g_Win64MultiplayerQuitOnDisconnect;
extern int g_Win64MultiplayerPort;
extern char g_Win64MultiplayerIP[256];
extern bool g_Win64DedicatedServer;

View file

@ -149,47 +149,57 @@ static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize)
dest[destSize - 1] = 0;
}
// ---------- Persistent options (options.txt next to exe) ----------
static void GetOptionsFilePath(char *out, size_t outSize)
// ---------- Persistent options (options.dat next to exe) ----------
static void GetOptionsFilePath(char *out, DWORD outSize)
{
GetModuleFileNameA(nullptr, out, static_cast<DWORD>(outSize));
char *p = strrchr(out, '\\');
if (p) *(p + 1) = '\0';
strncat_s(out, outSize, "options.txt", _TRUNCATE);
GetModuleFileNameA(nullptr, out, outSize);
char *p = strrchr(out, '\\');
if (p) *(p + 1) = '\0';
strncat_s(out, outSize, "settings.dat", _TRUNCATE);
}
static void SaveFullscreenOption(bool fullscreen)
{
char path[MAX_PATH];
GetOptionsFilePath(path, sizeof(path));
FILE *f = nullptr;
if (fopen_s(&f, path, "w") == 0 && f)
{
fprintf(f, "fullscreen=%d\n", fullscreen ? 1 : 0);
fclose(f);
}
GAME_SETTINGS settings = {};
char path[MAX_PATH] = {};
GetOptionsFilePath(path, MAX_PATH);
FILE *f = nullptr;
if (fopen_s(&f, path, "rb") == 0 && f)
{
fread(&settings, sizeof(GAME_SETTINGS), 1, f);
fclose(f);
}
if (fullscreen)
settings.uiBitmaskValues |= (1UL << 25);
else
settings.uiBitmaskValues &= ~(1UL << 25);
if (fopen_s(&f, path, "wb") == 0 && f)
{
fwrite(&settings, sizeof(GAME_SETTINGS), 1, f);
fclose(f);
}
}
static bool LoadFullscreenOption()
{
char path[MAX_PATH];
char path[MAX_PATH] = {};
GetOptionsFilePath(path, sizeof(path));
FILE *f = nullptr;
if (fopen_s(&f, path, "r") == 0 && f)
{
char line[256];
while (fgets(line, sizeof(line), f))
{
int val = 0;
if (sscanf_s(line, "fullscreen=%d", &val) == 1)
{
fclose(f);
return val != 0;
}
}
fclose(f);
}
return false;
FILE *f = nullptr;
if (fopen_s(&f, path, "rb") != 0 || !f)
return false;
GAME_SETTINGS current = {};
bool ok = (fread(&current, sizeof(GAME_SETTINGS), 1, f) == 1);
fclose(f);
if (!ok)
return false;
return (current.uiBitmaskValues & (1UL << 25)) != 0;
}
// ------------------------------------------------------------------
@ -219,6 +229,7 @@ static Win64LaunchOptions ParseLaunchOptions()
Win64LaunchOptions options = {};
options.screenMode = 0;
g_Win64MultiplayerQuitOnDisconnect = false;
g_Win64MultiplayerJoin = false;
g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT;
@ -239,6 +250,10 @@ static Win64LaunchOptions ParseLaunchOptions()
{
CopyWideArgToAnsi(argv[++i], g_Win64Username, sizeof(g_Win64Username));
}
else if (_wcsicmp(argv[i], L"-quitondisconnect") == 0)
{
g_Win64MultiplayerQuitOnDisconnect = true;
}
else if (_wcsicmp(argv[i], L"-ip") == 0 && (i + 1) < argc)
{
char ipBuf[256];
@ -819,8 +834,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
return FALSE;
}
ShowWindow(g_hWnd, (nCmdShow != SW_HIDE) ? SW_SHOWMAXIMIZED : nCmdShow);
UpdateWindow(g_hWnd);
return TRUE;
}
@ -1451,8 +1465,9 @@ void CleanupDevice()
static Minecraft* InitialiseMinecraftRuntime()
{
app.loadMediaArchive();
RenderManager.Initialise(g_pd3dDevice, g_pSwapChain);
// @CDevJoud: No need to call this method as it gets called once in `InitDevice()`
// Calling it again and it results of 20MB of memory leak!
//RenderManager.Initialise(g_pd3dDevice, g_pSwapChain);
app.loadStringTable();
ui.init(g_pd3dDevice, g_pImmediateContext, g_pRenderTargetView, g_pDepthStencilView, g_rScreenWidth, g_rScreenHeight);
@ -1690,11 +1705,12 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
CleanupDevice();
return 0;
}
// Restore fullscreen state from previous session. Route through the
// deferred exclusive fullscreen path so the main loop applies it on the
// first tick (safer than transitioning during init).
if ((LoadFullscreenOption() && !g_isFullscreen) || launchOptions.fullscreen)
bool FullScreenEnabled = LoadFullscreenOption();
if (FullScreenEnabled && !g_isFullscreen)
{
g_bPendingExclusiveFullscreen = true;
g_bPendingExclusiveFullscreenValue = true;
@ -1785,6 +1801,20 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
hr = XuiTimersRun();
}
#endif
// @CDevJoud The window should only be shown after the engine/game
// initialization has fully completed.
//
// Showing the window too early especially on low end devices,
// may cause windows to display a "Not Responding" state while
// initialization is still in progress.
//
// This creates an unprofessional first impression for the player.
// Instead, initialize all engine systems first, then display the
// window once everything is ready.
ShowWindow(g_hWnd, (nCmdShow != SW_HIDE) ? SW_SHOWMAXIMIZED : nCmdShow);
UpdateWindow(g_hWnd);
MSG msg = {0};
while( WM_QUIT != msg.message && !app.m_bShutdown)
{

View file

@ -9100,7 +9100,7 @@ All Ender Chests in a world are linked. Items placed into an Ender Chest are acc
</data>
<data name="IDS_ITEM_RABBIT_STEW">
<value>{*ICON_SHANK_01*}</value>
<value>Rabbit Stew</value>
</data>
<data name="IDS_TILE_DOUBLE_TALL_GRASS">
@ -9570,4 +9570,8 @@ All Ender Chests in a world are linked. Items placed into an Ender Chest are acc
<data name="IDS_ACHIEVEMENT_VIEW"><value>Hold {*CONTROLLER_VK_Y*} to view</value></data>
<data name="IDS_CHECKBOX_CLASSICCRAFTING"><value>Classic Crafting</value></data>
<data name="IDS_DESC_RABBIT_STEW">
<value>Restores 5{*ICON_SHANK_01*}.</value>
</data>
</root>

View file

@ -1281,10 +1281,9 @@ void __cdecl NativeSpawnParticle(int entityId, int particleId, float x, float y,
{
auto player = FindPlayer(entityId);
if (!player || !player->connection) return;
const ParticleType* type = ParticleType::byId(particleId);
if (!type) type = ParticleType::getDefault();
arrayWithLength<int> noParams = { nullptr, 0 };
player->connection->send(std::make_shared<LevelParticlesPacket>(type, false, x, y, z, offsetX, offsetY, offsetZ, speed, count, noParams));
wchar_t buf[32];
swprintf_s(buf, L"%d", particleId);
player->connection->send(std::make_shared<LevelParticlesPacket>(std::wstring(buf), x, y, z, offsetX, offsetY, offsetZ, speed, count));
}
int __cdecl NativeSetPassenger(int entityId, int passengerEntityId)

View file

@ -54,10 +54,16 @@ AABB *AABB::newPermanent(double x0, double y0, double z0, double x1, double y1,
void AABB::clearPool()
{
ThreadStorage *tls = static_cast<ThreadStorage *>(TlsGetValue(tlsIdx));
if (tls != nullptr)
{
tls->poolPointer = 0;
}
}
void AABB::resetPool()
{
clearPool();
}
AABB *AABB::newTemp(double x0, double y0, double z0, double x1, double y1, double z1)

View file

@ -54,7 +54,7 @@ AddEntityPacket::AddEntityPacket(shared_ptr<Entity> e, int type, int data, int y
void AddEntityPacket::read(DataInputStream *dis) // throws IOException TODO 4J JEV add throws statement
{
id = dis->readShort();
id = dis->readInt();
type = dis->readByte();
#ifdef _LARGE_WORLDS
x = dis->readInt();
@ -78,7 +78,7 @@ void AddEntityPacket::read(DataInputStream *dis) // throws IOException TODO 4J
void AddEntityPacket::write(DataOutputStream *dos) // throws IOException TODO 4J JEV add throws statement
{
dos->writeShort(id);
dos->writeInt(id);
dos->writeByte(type);
#ifdef _LARGE_WORLDS
dos->writeInt(x);
@ -107,5 +107,5 @@ void AddEntityPacket::handle(PacketListener *listener)
int AddEntityPacket::getEstimatedSize()
{
return 11 + data > -1 ? 6 : 0;
return (11 + data > -1 ? 6 : 0) + 2;
}

View file

@ -66,7 +66,7 @@ AddMobPacket::AddMobPacket(shared_ptr<LivingEntity> mob, int yRotp, int xRotp, i
void AddMobPacket::read(DataInputStream *dis) //throws IOException
{
id = dis->readShort();
id = dis->readInt();
type = dis->readByte() & 0xff;
#ifdef _LARGE_WORLDS
x = dis->readInt();
@ -90,7 +90,7 @@ void AddMobPacket::read(DataInputStream *dis) //throws IOException
void AddMobPacket::write(DataOutputStream *dos) //throws IOException
{
dos->writeShort(id);
dos->writeInt(id);
dos->writeByte(type & 0xff);
#ifdef _LARGE_WORLDS
dos->writeInt(x);
@ -127,7 +127,7 @@ int AddMobPacket::getEstimatedSize()
// 4J Stu - This is an incoming value which we aren't currently analysing
//size += unpack->get
}
return size;
return size + 2;
}
vector<shared_ptr<SynchedEntityData::DataItem> > *AddMobPacket::getUnpackedData()

View file

@ -16,11 +16,12 @@
#include "ParticleTypes.h"
#include "Random.h"
#include "AABB.h"
#include "../Minecraft.World/LevelChunk.h"
const Rotations ArmorStand::DEFAULT_HEAD_POSE (0.0f, 0.0f, 0.0f);
const Rotations ArmorStand::DEFAULT_BODY_POSE (0.0f, 0.0f, 0.0f);
const Rotations ArmorStand::DEFAULT_LEFT_ARM_POSE (-10.0f, 0.0f, -10.0f);
const Rotations ArmorStand::DEFAULT_RIGHT_ARM_POSE (-15.0f, 0.0f, 10.0f);
const Rotations ArmorStand::DEFAULT_LEFT_ARM_POSE (-15.0f, 0.0f, 10.0f);
const Rotations ArmorStand::DEFAULT_RIGHT_ARM_POSE (-10.0f, 0.0f, -10.0f);
const Rotations ArmorStand::DEFAULT_LEFT_LEG_POSE (-1.0f, 0.0f, -1.0f);
const Rotations ArmorStand::DEFAULT_RIGHT_LEG_POSE (1.0f, 0.0f, 1.0f);
@ -45,6 +46,10 @@ void ArmorStand::init()
for (int i = 0; i < equipmentCount; i++)
equipment[i] = nullptr;
rotateElytraX = 0.2617994f;
rotateElytraY = 0.0f;
rotateElytraZ = -0.2617994f;
headPose = DEFAULT_HEAD_POSE;
bodyPose = DEFAULT_BODY_POSE;
leftArmPose = DEFAULT_LEFT_ARM_POSE;
@ -83,7 +88,7 @@ void ArmorStand::defineSynchedData()
ArmorStand::~ArmorStand() {}
bool ArmorStand::hasPhysics() const { return (entityData->getByte(DATA_CLIENT_FLAGS) & FLAG_NO_GRAVITY) == 0; }
bool ArmorStand::isBaby() const { return (entityData->getByte(DATA_CLIENT_FLAGS) & FLAG_SMALL) != 0; }
bool ArmorStand::isSmall() const { return isBaby(); }
bool ArmorStand::isShowArms() const { return (entityData->getByte(DATA_CLIENT_FLAGS) & FLAG_SHOW_ARMS) != 0; }
@ -188,6 +193,93 @@ void ArmorStand::updateInvisibilityStatus()
setInvisible(invisible);
}
void ArmorStand::travel(float xa, float ya)
{
if (hasPhysics()) {
float friction = 0.91f;
int frictionTile = 0;
if (onGround)
{
frictionTile = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, Mth::floor(z));
friction = 0.6f * 0.91f;
if (frictionTile > 0)
{
friction = Tile::tiles[frictionTile]->friction * 0.91f;
}
}
float friction2 = (0.6f * 0.6f * 0.91f * 0.91f * 0.6f * 0.91f) / (friction * friction * friction);
float speed;
if (onGround)
{
speed = getSpeed() * friction2;
}
else
{
speed = flyingSpeed;
}
moveRelative(xa, ya, speed);
friction = 0.91f;
if (onGround)
{
friction = 0.6f * 0.91f;
if (frictionTile > 0)
{
friction = Tile::tiles[frictionTile]->friction * 0.91f;
}
}
if (onLadder())
{
float max = 0.15f;
if (xd < -max) xd = -max;
if (xd > max) xd = max;
if (zd < -max) zd = -max;
if (zd > max) zd = max;
fallDistance = 0;
if (yd < -0.15) yd = -0.15;
bool playerSneaking = isSneaking() && this->instanceof(eTYPE_PLAYER);
if (playerSneaking && yd < 0) yd = 0;
}
move(xd, yd, zd);
if (horizontalCollision && onLadder())
{
yd = 0.2;
}
if (!level->isClientSide || (level->hasChunkAt(static_cast<int>(x), 0, static_cast<int>(z)) && level->getChunkAt(static_cast<int>(x), static_cast<int>(z))->loaded))
{
yd -= 0.08;
}
else if (y > 0)
{
yd = -0.1;
}
else
{
yd = 0;
}
yd *= 0.98f;
xd *= friction;
zd *= friction;
walkAnimSpeedO = walkAnimSpeed;
double xxd = x - xo;
double zzd = z - zo;
float wst = Mth::sqrt(xxd * xxd + zzd * zzd) * 4;
if (wst > 1) wst = 1;
walkAnimSpeed += (wst - walkAnimSpeed) * 0.4f;
walkAnimPos += walkAnimSpeed;
} else {
move(xd, yd, zd);
}
}
void ArmorStand::tick()
{
@ -195,14 +287,14 @@ void ArmorStand::tick()
LivingEntity::tick();
if (onGround)
{
BlockPos pos((int)floorf(x), (int)floorf(y) - 1, (int)floorf(z));
int blockId = level->getTile(pos.getX(), pos.getY(), pos.getZ());
if (blockId == Tile::topSnow->id)
{
int meta = level->getData(pos.getX(), pos.getY(), pos.getZ());
float snowHeight = ((meta & 0x7) + 1) * 0.125f;
moveTo(x, floorf(y) + snowHeight, z, yRot, xRot);
}
BlockPos pos((int)floorf(x), (int)floorf(y) - 1, (int)floorf(z));
int blockId = level->getTile(pos.getX(), pos.getY(), pos.getZ());
if (blockId == Tile::topSnow->id)
{
int meta = level->getData(pos.getX(), pos.getY(), pos.getZ());
float snowHeight = ((meta & 0x7) + 1) * 0.125f;
moveTo(x, floorf(y) + snowHeight, z, yRot, xRot);
}
}
this->yRot = lockedRot;
this->yRotO = lockedRot;

View file

@ -56,6 +56,10 @@ private:
bool isMarkerFlag;
bool noPhysics;
float standDamage;
public:
float rotateElytraX;
float rotateElytraY;
float rotateElytraZ;
public:
long long lastHit;
@ -64,6 +68,7 @@ public:
explicit ArmorStand(Level* level);
virtual ~ArmorStand();
bool hasPhysics() const;
bool isBaby() const;
bool isSmall() const;
bool isShowArms() const;
@ -142,6 +147,8 @@ public:
void updateBoundingBox(bool markerMode);
void updateInvisibilityStatus();
virtual void travel(float xz, float ya);
virtual shared_ptr<ItemInstance> getCarriedItem() override;
virtual shared_ptr<ItemInstance> getCarried(int slot) override;
virtual shared_ptr<ItemInstance> getArmor(int pos) override;

View file

@ -8,7 +8,7 @@
const BlockPos BlockPos::ZERO = BlockPos(0, 0, 0);
// Costruttori
BlockPos::BlockPos() : Vec3i(0, 0, 0) {}
BlockPos::BlockPos(int x, int y, int z) : Vec3i(x, y, z) {}
@ -49,7 +49,7 @@ BlockPos::BlockPos(int compressed) : Vec3i(0, 0, 0) {
BlockPos::BlockPos(BlockSource& source)
: Vec3i(source.getBlockX(), source.getBlockY(), source.getBlockZ()) {}
// Metodi di confronto
bool BlockPos::equals(const BlockPos& other) const {
return x == other.x && y == other.y && z == other.z;
}
@ -88,7 +88,7 @@ BlockPos BlockPos::relative(int direction, int distance) const {
return BlockPos(x + dx, y, z + dz);
}
// Metodi direzionali
// directional methods
BlockPos BlockPos::above(int distance) const {
return BlockPos(x, y + distance, z);
}
@ -119,7 +119,7 @@ BlockPos BlockPos::multiply(int factor) const {
return BlockPos(x * factor, y * factor, z * factor);
}
// Compressione
// compression
int BlockPos::compress() const {
static const int MASK_X = (1 << BITS_X) - 1;
static const int MASK_Y = (1 << BITS_Y) - 1;

View file

@ -148,7 +148,7 @@ void Boat::lerpTo(double x, double y, double z, float yRot, float xRot, int step
{
if (doLerp)
{
lSteps = steps + 5;
lSteps = steps +5;
}
else
{
@ -188,6 +188,10 @@ void Boat::lerpMotion(double xd, double yd, double zd)
void Boat::tick()
{
Entity::tick();
if (getHurtTime() > 0) setHurtTime(getHurtTime() - 1);
if (getDamage() > 0) setDamage(getDamage() - 1);
xo = x;
@ -199,8 +203,8 @@ void Boat::tick()
double waterPercentage = 0;
for (int i = 0; i < steps; i++)
{
double y0 = bb->y0 + (bb->y1 - bb->y0) * (i + 0) / steps - 2 / 16.0f;
double y1 = bb->y0 + (bb->y1 - bb->y0) * (i + 1) / steps - 2 / 16.0f;
double y0 = bb->y0 + (bb->y1 - bb->y0) * (i + 0) / steps + 1.5f / 16.0f;
double y1 = bb->y0 + (bb->y1 - bb->y0) * (i + 1) / steps + 1.5f / 16.0f;
AABB *bb2 = AABB::newTemp(bb->x0, y0, bb->z0, bb->x1, y1, bb->z1);
if (level->containsLiquid(bb2, Material::water))
{
@ -257,18 +261,19 @@ void Boat::tick()
return;
}
// Bob in water
if (waterPercentage > 0)
// Bob in water & gravity
if (waterPercentage < 1.0)
{
double bob = waterPercentage * 2 - 1;
double bob = waterPercentage * 2.0 - 1.0;
yd += 0.04f * bob;
}
// Reimplement gravity again (??)
int tileUnder = level->getTile(Mth::floor(x), Mth::floor(y-0.15), Mth::floor(z));
if (tileUnder == 0 && !onGround)
else
{
yd -= 0.04f;
if (yd < 0.0)
{
yd /= 2.0;
}
yd += 0.007f;
}
// Rider controls
@ -281,24 +286,16 @@ void Boat::tick()
{
double riderXd = -sin(livingRider->yRot * PI / 180);
double riderZd = cos(livingRider->yRot * PI / 180);
float mult = livingRider->isSprinting() ? 2.0f : 1.0f;
double currentSpeed = sqrt(xd * xd + zd * zd);
float moveFactor = (float)forward;
if (forward < 0) moveFactor *= 0.5f; // Move slower backwards
xd += riderXd * acceleration * 0.05f * mult * moveFactor;
zd += riderZd * acceleration * 0.05f * mult * moveFactor;
xd += riderXd * acceleration * 0.05f * moveFactor;
zd += riderZd * acceleration * 0.05f * moveFactor;
}
}
double curSpeed = sqrt(xd * xd + zd * zd);
double maxSpeed = MAX_SPEED;
if (rider.lock() != nullptr && rider.lock()->instanceof(eTYPE_LIVINGENTITY))
{
shared_ptr<LivingEntity> livingRider = dynamic_pointer_cast<LivingEntity>(rider.lock());
if (livingRider->isSprinting())
{
maxSpeed *= 1.5;
}
}
if (curSpeed > maxSpeed)
{
@ -330,10 +327,12 @@ void Boat::tick()
move(xd, yd, zd);
// Break boat on high speed collision
float breakThreshold = (rider.lock() != nullptr) ? 0.35f : 0.20f;
if ((horizontalCollision && lastSpeed > 0.20))
{
if (!level->isClientSide && !removed)
{
remove();
for (int i = 0; i < 3; i++)
{
@ -343,6 +342,9 @@ void Boat::tick()
{
spawnAtLocation(Item::stick->id, 1, 0);
}
}
}
else
@ -472,10 +474,19 @@ bool Boat::interact(shared_ptr<Player> player)
if ( (rider.lock() != nullptr) && rider.lock()->instanceof(eTYPE_PLAYER) && (rider.lock() != player) ) return true;
if (!level->isClientSide)
{
bool isRiding = (rider.lock() == player);
if (isRiding)
{
player->xd = 0;
player->yd = 0;
player->zd = 0;
}
// 4J HEG - Fixed issue with player not being able to dismount boat (issue #4446)
player->ride( rider.lock() == player ? nullptr : shared_from_this() );
}
return true;
player->ride(isRiding ? nullptr : shared_from_this());
}
return true;
}
void Boat::setDamage(float damage)

View file

@ -38,14 +38,54 @@ void ClothDyeRecipes::addRecipes(Recipes *r)
}
// some dye recipes
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 2, DyePowderItem::YELLOW),
//flowers
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::YELLOW),
L"tg",
Tile::flower,L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 2, DyePowderItem::RED),
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::RED),
L"tg",
Tile::rose,L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::LIGHT_BLUE),
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::BLUE_ORCHID), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::MAGENTA),
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::ALLIUM), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::SILVER),
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::AZURE_BLUET), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::RED),
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::RED_TULIP), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::PINK),
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::PINK_TULIP), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::SILVER),
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::WHITE_TULIP), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::ORANGE),
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::ORANGE_TULIP), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 1, DyePowderItem::SILVER),
L"zg", new ItemInstance(Item::items[Tile::rose_Id], 1, Rose::OXEYE_DAISY), L'D');
// Tall flowers
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 2, DyePowderItem::YELLOW),
L"zg", new ItemInstance(Item::items[Tile::tallgrass2_Id], 1, TallGrass2::SUNFLOWER), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 2, DyePowderItem::MAGENTA),
L"zg", new ItemInstance(Item::items[Tile::tallgrass2_Id], 1, TallGrass2::LILAC), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 2, DyePowderItem::RED),
L"zg", new ItemInstance(Item::items[Tile::tallgrass2_Id], 1, TallGrass2::ROSE_BUSH), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 2, DyePowderItem::MAGENTA),
L"zg", new ItemInstance(Item::items[Tile::tallgrass2_Id], 1, TallGrass2::PEONY), L'D');
r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 3, DyePowderItem::WHITE),
L"ig",
Item::bone,L'D');
@ -114,6 +154,9 @@ void ClothDyeRecipes::addRecipes(Recipes *r)
new ItemInstance(Item::dye_powder, 1, DyePowderItem::RED),
new ItemInstance(Item::dye_powder, 1, DyePowderItem::WHITE),L'D');
for (int i = 0; i < 16; i++)
{
r->addShapedRecipy(new ItemInstance(Tile::woolCarpet, 3, i),

View file

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "net.minecraft.world.item.h"
#include "net.minecraft.world.level.h"
#include "net.minecraft.world.level.redstone.h"
@ -107,33 +107,42 @@ bool ComparatorTile::shouldTurnOn(Level *level, int x, int y, int z, int data)
int ComparatorTile::getInputSignal(Level *level, int x, int y, int z, int data)
{
int result = DiodeTile::getInputSignal(level, x, y, z, data);
int result = DiodeTile::getInputSignal(level, x, y, z, data);
int dir = getDirection(data);
int xx = x + Direction::STEP_X[dir];
int zz = z + Direction::STEP_Z[dir];
int tile = level->getTile(xx, y, zz);
int dir = getDirection(data);
int xx = x + Direction::STEP_X[dir];
int zz = z + Direction::STEP_Z[dir];
int tile = level->getTile(xx, y, zz);
if (tile > 0)
{
if (Tile::tiles[tile]->hasAnalogOutputSignal())
{
result = Tile::tiles[tile]->getAnalogOutputSignal(level, xx, y, zz, Direction::DIRECTION_OPPOSITE[dir]);
}
else if (result < Redstone::SIGNAL_MAX && Tile::isSolidBlockingTile(tile))
{
xx += Direction::STEP_X[dir];
zz += Direction::STEP_Z[dir];
tile = level->getTile(xx, y, zz);
if (tile > 0)
{
if (Tile::tiles[tile]->hasAnalogOutputSignal())
{
result = Tile::tiles[tile]->getAnalogOutputSignal(level, xx, y, zz, Direction::DIRECTION_OPPOSITE[dir]);
}
else if (result < Redstone::SIGNAL_MAX && Tile::isSolidBlockingTile(tile))
{
xx += Direction::STEP_X[dir];
zz += Direction::STEP_Z[dir];
tile = level->getTile(xx, y, zz);
if (tile > 0 && Tile::tiles[tile]->hasAnalogOutputSignal())
{
result = Tile::tiles[tile]->getAnalogOutputSignal(level, xx, y, zz, Direction::DIRECTION_OPPOSITE[dir]);
}
}
}
if (tile > 0 && Tile::tiles[tile]->hasAnalogOutputSignal())
{
result = Tile::tiles[tile]->getAnalogOutputSignal(level, xx, y, zz, Direction::DIRECTION_OPPOSITE[dir]);
}
else if (tile == 0)
{
shared_ptr<ItemFrame> frame = getItemFrame(level, xx, y, zz);
if (frame != nullptr)
{
result = frame->getAnalogOutput();
}
}
}
}
return result;
return result;
}
shared_ptr<ComparatorTileEntity> ComparatorTile::getComparator(LevelSource *level, int x, int y, int z)
@ -250,4 +259,28 @@ shared_ptr<TileEntity> ComparatorTile::newTileEntity(Level *level)
bool ComparatorTile::TestUse()
{
return true;
}
shared_ptr<ItemFrame> ComparatorTile::getItemFrame(
Level* level,
int x,
int y,
int z)
{
AABB* box = AABB::newTemp(
x,
y,
z,
x + 1,
y + 1,
z + 1
);
vector<shared_ptr<Entity>>* entities =
level->getEntitiesOfClass(typeid(ItemFrame), box);
if (entities == nullptr || entities->size() != 1)
return nullptr;
return dynamic_pointer_cast<ItemFrame>((*entities)[0]);
}

View file

@ -2,6 +2,7 @@
#include "DiodeTile.h"
#include "EntityTile.h"
#include "AABB.h"
class ComparatorTileEntity;
@ -57,4 +58,5 @@ public:
virtual bool triggerEvent(Level *level, int x, int y, int z, int b0, int b1);
virtual shared_ptr<TileEntity> newTileEntity(Level *level);
virtual bool TestUse();
shared_ptr<ItemFrame> ComparatorTile::getItemFrame(Level* level,int x,int y,int z);
};

View file

@ -26,6 +26,7 @@ void Creeper::_init()
oldSwell = 0;
maxSwell = 30;
explosionRadius = 3;
ignited = false;
}
Creeper::Creeper(Level *level) : Monster( level )
@ -190,3 +191,38 @@ void Creeper::thunderHit(const LightningBolt *lightningBolt)
Monster::thunderHit(lightningBolt);
entityData->set(DATA_IS_POWERED, static_cast<byte>(1));
}
void Creeper::Ignite()
{
setSwellDir(1);
ignited = true;
}
bool Creeper::isIgnited()
{
return ignited;
}
bool Creeper::mobInteract(shared_ptr<Player> player)
{
shared_ptr<ItemInstance> item = player->inventory->getSelected();
if (item == nullptr || item->id != Item::flintAndSteel_Id)
return Mob::mobInteract(player);
playSound(eSoundType_FIRE_NEWIGNITE, 1, random->nextFloat() * 0.4f + 0.8f);
player->swing();
if (!level->isClientSide)
{
if (!isIgnited())
{
Ignite();
item->hurtAndBreak(1, player);
return true;
}
return Mob::mobInteract(player);
}
return true;
}

View file

@ -21,6 +21,8 @@ private:
int maxSwell;
int explosionRadius;
bool ignited;
void _init();
public:
@ -34,6 +36,8 @@ public:
virtual int getMaxFallDistance();
virtual bool mobInteract(shared_ptr<Player> player);
protected:
virtual void causeFallDamage(float distance);
virtual void defineSynchedData();
@ -61,5 +65,9 @@ protected:
public:
int getSwellDir();
void setSwellDir(int dir);
void thunderHit(const LightningBolt *lightningBolt) ;
void thunderHit(const LightningBolt *lightningBolt);
public:
void Ignite();
bool isIgnited();
};

View file

@ -5,30 +5,39 @@
#include "CustomPayloadPacket.h"
// Mojang-defined custom packets
const wstring CustomPayloadPacket::CUSTOM_BOOK_PACKET = L"MC|BEdit";
const wstring CustomPayloadPacket::CUSTOM_BOOK_SIGN_PACKET = L"MC|BSign";
const wstring CustomPayloadPacket::TEXTURE_PACK_PACKET = L"MC|TPack";
const wstring CustomPayloadPacket::TRADER_LIST_PACKET = L"MC|TrList";
const wstring CustomPayloadPacket::TRADER_SELECTION_PACKET = L"MC|TrSel";
const wstring CustomPayloadPacket::SET_ADVENTURE_COMMAND_PACKET = L"MC|AdvCdm";
const wstring CustomPayloadPacket::SET_BEACON_PACKET = L"MC|Beacon";
const wstring CustomPayloadPacket::SET_ITEM_NAME_PACKET = L"MC|ItemName";
const wstring CustomPayloadPacket::CUSTOM_BOOK_PACKET = CreateVanillaPayloadKey(L"BEdit");
const wstring CustomPayloadPacket::CUSTOM_BOOK_SIGN_PACKET = CreateVanillaPayloadKey(L"BSign");
const wstring CustomPayloadPacket::TEXTURE_PACK_PACKET = CreateVanillaPayloadKey(L"TPack");
const wstring CustomPayloadPacket::TRADER_LIST_PACKET = CreateVanillaPayloadKey(L"TrList");
const wstring CustomPayloadPacket::TRADER_SELECTION_PACKET = CreateVanillaPayloadKey(L"TrSel");
const wstring CustomPayloadPacket::CIPHER_KEY_CHANNEL = L"MC|CKey";
const wstring CustomPayloadPacket::CIPHER_ACK_CHANNEL = L"MC|CAck";
const wstring CustomPayloadPacket::CIPHER_ON_CHANNEL = L"MC|COn";
// neoLegacy-defined custom packets
const wstring CustomPayloadPacket::UPDATE_RECIPE_REGISTRY = CreatePayloadKey(L"neo", L"UpdRReg");
const wstring CustomPayloadPacket::UPDATE_CREATIVE_REGISTRY = CreatePayloadKey(L"neo", L"UpdCReg");
const wstring CustomPayloadPacket::IDENTITY_TOKEN_ISSUE = L"MC|CTIssue";
const wstring CustomPayloadPacket::IDENTITY_TOKEN_CHALLENGE = L"MC|CTChallenge";
const wstring CustomPayloadPacket::IDENTITY_TOKEN_RESPONSE = L"MC|CTResponse";
//todo: figure out if we should replace the packets in the comment section with a custom payload identifier
//comment section start
const wstring CustomPayloadPacket::SET_ADVENTURE_COMMAND_PACKET = CreateVanillaPayloadKey(L"AdvCdm");
const wstring CustomPayloadPacket::SET_BEACON_PACKET = CreateVanillaPayloadKey(L"Beacon");
const wstring CustomPayloadPacket::SET_ITEM_NAME_PACKET = CreateVanillaPayloadKey(L"ItemName");
const wstring CustomPayloadPacket::FORK_HELLO_CHANNEL = L"MC|ForkHello";
const wstring CustomPayloadPacket::FORK_PLAYER_LEAVE_CHANNEL = L"MC|ForkPLeave";
const wstring CustomPayloadPacket::CIPHER_KEY_CHANNEL = CreateVanillaPayloadKey(L"CKey");
const wstring CustomPayloadPacket::CIPHER_ACK_CHANNEL = CreateVanillaPayloadKey(L"CAck");
const wstring CustomPayloadPacket::CIPHER_ON_CHANNEL = CreateVanillaPayloadKey(L"COn");
const wstring CustomPayloadPacket::QUICK_EQUIP_PACKET = L"MC|QEquip";
const wstring CustomPayloadPacket::QUICK_EQUIP_SERVER_PACKET = L"MC|QEquipServer";
const wstring CustomPayloadPacket::IDENTITY_TOKEN_ISSUE = CreateVanillaPayloadKey(L"CTIssue");
const wstring CustomPayloadPacket::IDENTITY_TOKEN_CHALLENGE = CreateVanillaPayloadKey(L"CTChallenge");
const wstring CustomPayloadPacket::IDENTITY_TOKEN_RESPONSE = CreateVanillaPayloadKey(L"CTResponse");
const wstring CustomPayloadPacket::ENCHANTMENT_LIST_PACKET = L"MC|EnchList";
const wstring CustomPayloadPacket::FORK_HELLO_CHANNEL = CreateVanillaPayloadKey(L"ForkHello");
const wstring CustomPayloadPacket::FORK_PLAYER_LEAVE_CHANNEL = CreateVanillaPayloadKey(L"ForkPLeave");
const wstring CustomPayloadPacket::ENCHANTMENT_LIST_PACKET = CreateVanillaPayloadKey(L"EnchList");
//comment section end
//removed cause its now handled on the server side
// const wstring CustomPayloadPacket::QUICK_EQUIP_PACKET = CreateVanillaPayloadKey(L"QEquip");
// const wstring CustomPayloadPacket::QUICK_EQUIP_SERVER_PACKET = CreateVanillaPayloadKey(L"QEquipServer");
CustomPayloadPacket::CustomPayloadPacket()
: length(0)

View file

@ -3,6 +3,9 @@ using namespace std;
#include "Packet.h"
#define CreatePayloadKey(identifier, action) identifier L"|" action
#define CreateVanillaPayloadKey(action) CreatePayloadKey(L"MC", action)
class CustomPayloadPacket : public Packet, public enable_shared_from_this<CustomPayloadPacket>
{
public:
@ -17,6 +20,10 @@ public:
static const wstring SET_BEACON_PACKET;
static const wstring SET_ITEM_NAME_PACKET;
// neoLegacy-defined custom packets
static const wstring UPDATE_RECIPE_REGISTRY;
static const wstring UPDATE_CREATIVE_REGISTRY;
// Security: stream cipher handshake channels
static const wstring CIPHER_KEY_CHANNEL; // server->client: carries 32-byte key (16 AES key + 16 IV)
static const wstring CIPHER_ACK_CHANNEL; // client->server: ack (empty payload)
@ -32,8 +39,8 @@ public:
static const wstring FORK_PLAYER_LEAVE_CHANNEL; // server->client: player disconnected (payload: UTF gamertag)
// Fixes for MP related crashes
static const wstring QUICK_EQUIP_PACKET;
static const wstring QUICK_EQUIP_SERVER_PACKET;
//static const wstring QUICK_EQUIP_PACKET;
//static const wstring QUICK_EQUIP_SERVER_PACKET;
static const wstring ENCHANTMENT_LIST_PACKET;

View file

@ -42,8 +42,20 @@ Icon* DirtTile::getTexture(int face, int data)
if (data < 0 || data >= DIRT_NAMES_LENGTH)
data = 0;
if (TEXTURE_NAMES[data] == L"dirt_podzol") {
return (face == Facing::UP) ? podzolTop : podzolSide;
if (TEXTURE_NAMES[data] == L"dirt_podzol")
{
switch(face)
{
case Facing::UP:
return podzolTop;
break;
case Facing::DOWN:
return Tile::dirt->getTexture(face);
break;
default:
return podzolSide;
break;
}
}
return icons[data];

View file

@ -6,13 +6,13 @@
#include "net.minecraft.world.item.h"
#include "net.minecraft.world.item.enchantment.h"
#include "EnchantmentMenu.h"
#include "../../../Minecraft.Client/ServerPlayer.h"
#include "../../../Minecraft.Client/MinecraftServer.h"
#include "../../../Minecraft.Client/PlayerList.h"
#include "../../../Minecraft.Client/MultiPlayerLocalPlayer.h"
#include "../../../Minecraft.Client/PlayerConnection.h"
#include "../../../Minecraft.World/CustomPayloadPacket.h"
#include "../../../Minecraft.Client/Minecraft.h"
#include "../Minecraft.Client/ServerPlayer.h"
#include "../Minecraft.Client/MinecraftServer.h"
#include "../Minecraft.Client/PlayerList.h"
#include "../Minecraft.Client/MultiPlayerLocalPlayer.h"
#include "../Minecraft.Client/PlayerConnection.h"
#include "../Minecraft.World/CustomPayloadPacket.h"
#include "../Minecraft.Client/Minecraft.h"
EnchantmentMenu::EnchantmentMenu(shared_ptr<Inventory> inventory, Level *level, int xt, int yt, int zt)
{

View file

@ -1170,7 +1170,13 @@ bool EnderDragon::hurt(shared_ptr<MultiEntityMobPart> MultiEntityMobPart, Damage
bool EnderDragon::hurt(DamageSource *source, float damage)
{
return false;
if (source == DamageSource::outOfWorld)
{
setSynchedAction(e_EnderdragonAction_Sitting_Scanning, true);
reallyHurt(source, getMaxHealth() + 1);
return true;
}
return false;
}
bool EnderDragon::reallyHurt(DamageSource *source, float damage)

View file

@ -0,0 +1,118 @@
#include "stdafx.h"
#include "EntityTypeMap.h"
static const unordered_map<wstring, eINSTANCEOF> s_nameToType = {
// animals
{ L"pig", eTYPE_PIG },
{ L"cow", eTYPE_COW },
{ L"sheep", eTYPE_SHEEP },
{ L"chicken", eTYPE_CHICKEN },
{ L"horse", eTYPE_HORSE },
{ L"wolf", eTYPE_WOLF },
{ L"ocelot", eTYPE_OCELOT },
{ L"rabbit", eTYPE_RABBIT },
{ L"mooshroom", eTYPE_MUSHROOMCOW },
{ L"squid", eTYPE_SQUID },
{ L"bat", eTYPE_BAT },
// neutral/passive
{ L"villager", eTYPE_VILLAGER },
{ L"snowgolem", eTYPE_SNOWMAN },
{ L"irongolem", eTYPE_VILLAGERGOLEM },
// monsters
{ L"zombie", eTYPE_ZOMBIE },
{ L"skeleton", eTYPE_SKELETON },
{ L"creeper", eTYPE_CREEPER },
{ L"spider", eTYPE_SPIDER },
{ L"cavespider", eTYPE_CAVESPIDER },
{ L"enderman", eTYPE_ENDERMAN },
{ L"silverfish", eTYPE_SILVERFISH },
{ L"blaze", eTYPE_BLAZE },
{ L"witch", eTYPE_WITCH },
{ L"ghast", eTYPE_GHAST },
{ L"slime", eTYPE_SLIME },
{ L"magmacube", eTYPE_LAVASLIME },
{ L"zombie_pigman", eTYPE_PIGZOMBIE },
{ L"witherboss", eTYPE_WITHERBOSS },
{ L"enderdragon", eTYPE_ENDERDRAGON },
{ L"giant", eTYPE_GIANT },
{ L"endermite", eTYPE_ENDERMITE },
{ L"guardian", eTYPE_GUARDIAN },
{ L"elder_guardian", eTYPE_ELDER_GUARDIAN },
// minecart
{ L"minecart", eTYPE_MINECART },
{ L"minecart_chest", eTYPE_MINECART_CHEST },
{ L"minecart_hopper", eTYPE_MINECART_HOPPER },
{ L"minecart_tnt", eTYPE_MINECART_TNT },
{ L"minecart_furnace", eTYPE_MINECART_FURNACE },
{ L"minecart_spawner", eTYPE_MINECART_SPAWNER },
// projectiles
{ L"arrow", eTYPE_ARROW },
{ L"snowball", eTYPE_SNOWBALL },
{ L"egg", eTYPE_THROWNEGG },
{ L"enderpearl", eTYPE_THROWNENDERPEARL },
{ L"potion", eTYPE_THROWNPOTION },
{ L"expbottle", eTYPE_THROWNEXPBOTTLE },
{ L"large_fireball", eTYPE_LARGE_FIREBALL },
{ L"small_fireball", eTYPE_SMALL_FIREBALL },
{ L"wither_skull", eTYPE_WITHER_SKULL },
{ L"dragon_fireball", eTYPE_DRAGON_FIREBALL },
{ L"fireworks_rocket", eTYPE_FIREWORKS_ROCKET },
{ L"eyeofender", eTYPE_EYEOFENDERSIGNAL },
// hanging
{ L"painting", eTYPE_PAINTING },
{ L"item_frame", eTYPE_ITEM_FRAME },
{ L"leash_knot", eTYPE_LEASHFENCEKNOT },
// others
{ L"item", eTYPE_ITEMENTITY },
{ L"xp_orb", eTYPE_EXPERIENCEORB },
{ L"boat", eTYPE_BOAT },
{ L"tnt", eTYPE_PRIMEDTNT },
{ L"falling_block", eTYPE_FALLINGTILE },
{ L"armor_stand", eTYPE_ARMORSTAND },
{ L"ender_crystal", eTYPE_ENDER_CRYSTAL },
{ L"lightning_bolt", eTYPE_LIGHTNINGBOLT },
};
static const unordered_map<eINSTANCEOF, wstring> s_typeToName = []()
{
unordered_map<eINSTANCEOF, wstring> m;
for (auto& pair : s_nameToType)
{
if (m.find(pair.second) == m.end())
m[pair.second] = pair.first;
}
return m;
}();
const unordered_map<wstring, eINSTANCEOF>& EntityTypeMap::getNameToTypeMap()
{
return s_nameToType;
}
const unordered_map<eINSTANCEOF, wstring>& EntityTypeMap::getTypeToNameMap()
{
return s_typeToName;
}
eINSTANCEOF EntityTypeMap::getTypeFromName(const wstring& name)
{
wstring lower = name;
transform(lower.begin(), lower.end(), lower.begin(), towlower);
auto it = s_nameToType.find(lower);
if (it != s_nameToType.end())
return it->second;
return eTYPE_NOTSET;
}
wstring EntityTypeMap::getNameFromType(eINSTANCEOF type)
{
auto it = s_typeToName.find(type);
if (it != s_typeToName.end())
return it->second;
return L"";
}
bool EntityTypeMap::isValidType(const wstring& name)
{
return getTypeFromName(name) != eTYPE_NOTSET;
}

View file

@ -0,0 +1,21 @@
#pragma once
#include "../Minecraft.World/Class.h"
#include <unordered_map>
#include <string>
using namespace std;
class EntityTypeMap
{
public:
static eINSTANCEOF getTypeFromName(const wstring& name);
static wstring getNameFromType(eINSTANCEOF type);
static bool isValidType(const wstring& name);
private:
static const unordered_map<wstring, eINSTANCEOF>& getNameToTypeMap();
static const unordered_map<eINSTANCEOF, wstring>& getTypeToNameMap();
};

View file

@ -43,4 +43,8 @@ public:
// 4J Added
static void updatePossibleRecipes(shared_ptr<CraftingContainer> craftSlots, bool *firework, bool *charge, bool *fade);
static bool isValidIngredient(shared_ptr<ItemInstance> item, bool firework, bool charge, bool fade);
virtual void writeToStream(DataOutputStream* dos) {
dos->writeByte(99);
}
};

View file

@ -121,8 +121,14 @@ void GrassTile::tick(Level *level, int x, int y, int z, Random *random)
}
}
// using isSolid() here is wrong because non full blocks like iron bars,
// fences, walls are also flagged as solid by their material
int aboveTileId = level->getTile(x, y + 1, z);
Material* above = level->getMaterial(x, y + 1, z);
if (above->isSolid() || above->isLiquid()) level->setTileAndUpdate(x, y, z, Tile::dirt_Id);
if (above->isLiquid() || Tile::lightBlock[aboveTileId] > 2)
{
level->setTileAndUpdate(x, y, z, Tile::dirt_Id);
}
}
int GrassTile::getResource(int data, Random *random, int playerBonusLevel)

View file

@ -360,7 +360,7 @@ void Item::staticCtor()
Item::diamond = ( new Item(8) ) ->setBaseItemTypeAndMaterial(eBaseItemType_treasure, eMaterial_diamond)->setIconName(L"diamond")->setDescriptionId(IDS_ITEM_DIAMOND)->setUseDescriptionId(IDS_DESC_DIAMONDS);
Item::stick = ( new Item(24) ) ->setBaseItemTypeAndMaterial(Item::eBaseItemType_stick, Item::eMaterial_wood)->setIconName(L"stick")->handEquipped()->setDescriptionId(IDS_ITEM_STICK)->setUseDescriptionId(IDS_DESC_STICK);
Item::mushroomStew = ( new BowlFoodItem(26, 6) ) ->setIconName(L"mushroomStew")->setDescriptionId(IDS_ITEM_MUSHROOM_STEW)->setUseDescriptionId(IDS_DESC_MUSHROOMSTEW);
Item::rabbitStew = ( new BowlFoodItem(157, 10) ) ->setIconName(L"rabbitStew")->setDescriptionId(IDS_ITEM_MUSHROOM_STEW)->setUseDescriptionId(IDS_DESC_MUSHROOMSTEW);
Item::rabbitStew = ( new BowlFoodItem(157, 10) ) ->setIconName(L"rabbitStew")->setDescriptionId(IDS_ITEM_RABBIT_STEW)->setUseDescriptionId(IDS_DESC_RABBIT_STEW);
Item::string = ( new TilePlanterItem(31, Tile::tripWire) ) ->setIconName(L"string")->setDescriptionId(IDS_ITEM_STRING)->setUseDescriptionId(IDS_DESC_STRING);
Item::feather = ( new Item(32) ) ->setIconName(L"feather")->setDescriptionId(IDS_ITEM_FEATHER)->setUseDescriptionId(IDS_DESC_FEATHER);

View file

@ -10,7 +10,8 @@
#include "net.minecraft.world.level.saveddata.h"
#include "com.mojang.nbt.h"
#include "ItemFrame.h"
#include "DamageSource.h"
#include "Level.h"
@ -87,29 +88,52 @@ shared_ptr<ItemInstance> ItemFrame::getItem()
return getEntityData()->getItemInstance(DATA_ITEM);
}
void ItemFrame::setItem(shared_ptr<ItemInstance> item)
void ItemFrame::setItem(shared_ptr<ItemInstance> item, bool notifyNeighbors)
{
if(item != nullptr)
{
item = item->copy();
item->count = 1;
if (item != nullptr)
{
item = item->copy();
item->count = 1;
item->setFramed(dynamic_pointer_cast<ItemFrame>(shared_from_this()));
}
getEntityData()->set(DATA_ITEM, item);
getEntityData()->markDirty(DATA_ITEM);
item->setFramed(dynamic_pointer_cast<ItemFrame>( shared_from_this() ));
}
getEntityData()->set(DATA_ITEM, item);
getEntityData()->markDirty(DATA_ITEM);
if (notifyNeighbors)
{
level->updateNeighbourForOutputSignal(xTile, yTile, zTile, Tile::comparator_off->id);
}
}
int ItemFrame::getRotation()
void ItemFrame::setItem(shared_ptr<ItemInstance> item)
{
return getEntityData()->getByte(DATA_ROTATION);
setItem(item, true);
}
void ItemFrame::setRotation(int rotation)
int ItemFrame::getRotation()
{
getEntityData()->set(DATA_ROTATION, static_cast<byte>(rotation % 4));
return getEntityData()->getByte(DATA_ROTATION);
}
void ItemFrame::setRotation(int rotation, bool notifyNeighbors)
{
getEntityData()->set(DATA_ROTATION, static_cast<byte>(rotation % 8));
if (notifyNeighbors)
{
level->updateNeighbourForOutputSignal(xTile, yTile, zTile, Tile::comparator_off->id);
}
}
void ItemFrame::setRotation(int rotation)
{
getEntityData()->set(DATA_ROTATION, static_cast<byte>(rotation % 8));
level->updateNeighbourForOutputSignal(xTile, yTile, zTile, Tile::comparator_off->id);
}
void ItemFrame::addAdditonalSaveData(CompoundTag *tag)
{
if (getItem() != nullptr)
@ -171,3 +195,54 @@ bool ItemFrame::interact(shared_ptr<Player> player)
return true;
}
bool ItemFrame::hurt(DamageSource *source, float damage)
{
if (level->isClientSide) return false;
shared_ptr<ItemInstance> item = getItem();
if (!source->isExplosion() && item != nullptr)
{
shared_ptr<Entity> sourceEntity = source->getEntity();
if (sourceEntity != nullptr && sourceEntity->instanceof(eTYPE_PLAYER))
{
shared_ptr<Player> player = dynamic_pointer_cast<Player>(sourceEntity);
if (!player->abilities.instabuild)
{
shared_ptr<ItemInstance> copy = item->copy();
removeFramedMap(copy);
spawnAtLocation(copy, 0);
}
else
{
removeFramedMap(item);
}
}
else
{
shared_ptr<ItemInstance> copy = item->copy();
removeFramedMap(copy);
spawnAtLocation(copy, 0);
}
setItem(nullptr);
return true;
}
return HangingEntity::hurt(source, damage);
}
int ItemFrame::getAnalogOutput()
{
shared_ptr<ItemInstance> item = getItem();
if (item == nullptr) return 0;
return getRotation() % 8 + 1;
}
float ItemFrame::getPickRadius()
{
return 0.0f;
}

View file

@ -38,9 +38,14 @@ private:
public:
shared_ptr<ItemInstance> getItem();
void setItem(shared_ptr<ItemInstance> item, bool notifyNeighbors);
void setItem(shared_ptr<ItemInstance> item);
int getRotation();
void setRotation(int rotation, bool notifyNeighbors);
void setRotation(int rotation);
virtual bool hurt(DamageSource *source, float damage) override;
virtual int getAnalogOutput();
virtual float getPickRadius()override;
virtual void addAdditonalSaveData(CompoundTag *tag);
virtual void readAdditionalSaveData(CompoundTag *tag);

View file

@ -220,6 +220,11 @@ void ItemInstance::setAuxValue(int value)
}
}
void ItemInstance::setRawAuxValue(int value)
{
auxValue = value;
}
int ItemInstance::getMaxDamage()
{
return Item::items[id]->getMaxDamage();

View file

@ -90,6 +90,7 @@ public:
int getDamageValue();
int getAuxValue() const;
void setAuxValue(int value);
void setRawAuxValue(int value);
int getMaxDamage();
bool hurt(int dmg, Random *random);
void hurtAndBreak(int dmg, shared_ptr<LivingEntity> owner);

View file

@ -1,26 +1,197 @@
#include "stdafx.h"
#include "stdafx.h"
#include "net.minecraft.commands.h"
#include "net.minecraft.world.entity.player.h"
#include "net.minecraft.world.damagesource.h"
#include "net.minecraft.world.level.h"
#include "BasicTypeContainers.h"
#include "KillCommand.h"
#include "EntityTypeMap.h"
static void killEntity(shared_ptr<Entity> entity)
{
if (entity->instanceof(eTYPE_LIVINGENTITY))
{
auto living = dynamic_pointer_cast<LivingEntity>(entity);
if (living != nullptr)
{
living->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
return;
}
entity->remove();
return;
}
entity->remove();
}
EGameCommand KillCommand::getId()
{
return eGameCommand_Kill;
return eGameCommand_Kill;
}
int KillCommand::getPermissionLevel()
{
return LEVEL_ALL;
return LEVEL_ALL;
}
void KillCommand::execute(shared_ptr<CommandSender> source, byteArray commandData)
{
shared_ptr<Player> player = dynamic_pointer_cast<Player>(source);
shared_ptr<Player> senderPlayer = dynamic_pointer_cast<Player>(source);
if (senderPlayer == nullptr)
return;
player->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
Level *level = senderPlayer->level;
if (level == nullptr)
return;
source->sendMessage(L"Ouch. That look like it hurt.");
//source.sendMessage(ChatMessageComponent.forTranslation("commands.kill.success"));
//nothing is the same of @s
if (commandData.length == 0 || commandData.data == nullptr)
{
senderPlayer->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
return;
}
ByteArrayInputStream bais(commandData);
DataInputStream dis(&bais);
wstring targetName = dis.readUTF();
wstring targetLower = targetName;
transform(targetLower.begin(), targetLower.end(), targetLower.begin(), towlower);
//@s
if (targetLower == L"@s")
{
senderPlayer->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
return;
}
//@a
if (targetLower == L"@a")
{
vector<shared_ptr<Player>> toKill;
for (auto& p : level->players)
if (p != nullptr && !p->removed)
toKill.push_back(p);
for (auto& p : toKill)
p->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
return;
}
//@p
if (targetLower == L"@p")
{
shared_ptr<Player> nearest = level->getNearestPlayer(
dynamic_pointer_cast<Entity>(senderPlayer), 9999.0);
if (nearest != nullptr)
{
nearest->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
source->sendMessage(L"Killed " + nearest->getName() + L".");
}
else
{
source->sendMessage(L"No player found.");
}
return;
}
//@r
if (targetLower == L"@r")
{
if (level->players.empty())
{
source->sendMessage(L"No player found.");
return;
}
int idx = rand() % (int)level->players.size();
auto& p = level->players[idx];
if (p != nullptr && !p->removed)
{
p->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
source->sendMessage(L"Killed " + p->getName() + L".");
}
return;
}
// @e
if (targetLower.size() >= 2 && targetLower.substr(0, 2) == L"@e")
{
eINSTANCEOF filterType = eTYPE_NOTSET;
bool invertFilter = false;
bool filterIsPlayer = false;
if (targetLower.size() > 3 && targetLower[2] == L'[')
{
wstring inner = targetLower.substr(3, targetLower.size() - 4);
wstring key = L"type=";
size_t pos = inner.find(key);
if (pos == wstring::npos)
{
source->sendMessage(L"Invalid selector syntax. Usage: @e[type=<entity_type>]");
return;
}
wstring typeStr = inner.substr(pos + key.size());
if (!typeStr.empty() && typeStr[0] == L'!')
{
invertFilter = true;
typeStr = typeStr.substr(1);
}
if (typeStr == L"player")
{
filterIsPlayer = true;
}
else
{
filterType = EntityTypeMap::getTypeFromName(typeStr);
if (filterType == eTYPE_NOTSET)
{
source->sendMessage(L"Unknown entity type: " + typeStr);
return;
}
}
}
vector<shared_ptr<Entity>> toKill;
for (auto& entity : level->entities)
{
if (entity == nullptr || entity->removed) continue;
bool isPlayer = entity->instanceof(eTYPE_PLAYER);
bool matchesFilter;
if (filterType == eTYPE_NOTSET && !filterIsPlayer)
matchesFilter = true;
else if (filterIsPlayer)
matchesFilter = isPlayer;
else
matchesFilter = entity->instanceof(filterType);
if (invertFilter) matchesFilter = !matchesFilter;
if (matchesFilter)
toKill.push_back(entity);
}
for (auto& entity : toKill)
if (!entity->removed)
killEntity(entity);
source->sendMessage(L"Killed " + to_wstring(toKill.size()) + L" entities.");
return;
}
// by player name
shared_ptr<Player> targetPlayer = level->getPlayerByName(targetName);
if (targetPlayer != nullptr)
{
targetPlayer->hurt(DamageSource::outOfWorld, Float::MAX_VALUE);
source->sendMessage(L"Killed " + targetName + L".");
return;
}
source->sendMessage(L"No entity was found.");
}

View file

@ -15,13 +15,13 @@ const unsigned int LeafTile2::LEAF2_NAMES[LEAF2_NAMES_SIZE] = {
};
const wstring LeafTile2::TEXTURES[2][2] = {
{ L"leaves_acacia", L"leaves_dark_oak" }, // Indice 0: Fancy
{ L"leaves_acacia_opaque", L"leaves_dark_oak_opaque" } // Indice 1: Veloce/Opaca
{ L"leaves_acacia", L"leaves_dark_oak" }, // index 0: Fancy
{ L"leaves_acacia_opaque", L"leaves_dark_oak_opaque" } // index 1: Fast
};
LeafTile2::LeafTile2(int id) : LeafTile(id)
{
// Non serve fare checkBuffer qui, ci pensa già la classe padre LeafTile!
// do nothing here
}
Icon *LeafTile2::getTexture(int face, int data)
@ -29,8 +29,8 @@ Icon *LeafTile2::getTexture(int face, int data)
int type = data & 3;
if (type >= LEAF2_NAMES_SIZE) type = 0;
// isSolidRender() in LeafTile restituisce 'true' se la grafica è su Veloce/Opaca.
// Quindi se è true usiamo l'indice 1, se è false (Trasparente) usiamo l'indice 0.
// isSolidRender() in LeafTile returns 'true' if graphics is Fast
// if true -> index is 1, else 0.
int textureSet = isSolidRender(false) ? 1 : 0;
return icons[textureSet][type];
@ -56,13 +56,14 @@ void LeafTile2::registerIcons(IconRegister *iconRegister)
int LeafTile2::getColor(int data)
{
// In inventario o in mano, l'Acacia e la Dark Oak usano il verde base
// in the inventory use the default colour for leaves
return FoliageColor::getDefaultColor();
}
int LeafTile2::getColor(LevelSource *level, int x, int y, int z, int data)
{
// Codice di blending per il colore del bioma (copiato dal tuo LeafTile.cpp)
// Codice di blending per il colore del bioma (copiato dal tuo LeafTile.cpp))
// blending biome colors copied from LeafTile.cpp
int totalRed = 0;
int totalGreen = 0;
int totalBlue = 0;
@ -71,7 +72,7 @@ int LeafTile2::getColor(LevelSource *level, int x, int y, int z, int data)
{
for (int ox = -1; ox <= 1; ox++)
{
int foliageColor = level->getBiome(x + ox, z + oz)->getFolageColor(); // Attento, nel tuo engine si chiama getFolageColor() senza la 'i'
int foliageColor = level->getBiome(x + ox, z + oz)->getFolageColor(); // they mispelled the word. getFolageColor without "i"
totalRed += (foliageColor & 0xff0000) >> 16;
totalGreen += (foliageColor & 0xff00) >> 8;
totalBlue += (foliageColor & 0xff);
@ -83,7 +84,7 @@ int LeafTile2::getColor(LevelSource *level, int x, int y, int z, int data)
void LeafTile2::playerDestroy(Level *level, shared_ptr<Player> player, int x, int y, int z, int data)
{
// Se il giocatore usa le cesoie, vogliamo droppare "leaves2" (ID 161) e non "leaves" (ID 18)
// if player is using shears, drop "leaves2" (ID 161) , instead of "leaves" (ID 18)
if (!level->isClientSide && player->getSelectedItem() != nullptr && player->getSelectedItem()->id == Item::shears->id)
{
player->awardStat(
@ -95,7 +96,7 @@ void LeafTile2::playerDestroy(Level *level, shared_ptr<Player> player, int x, in
}
else
{
// Altrimenti usa la distruzione standard di TransparentTile
// or default destroy
TransparentTile::playerDestroy(level, player, x, y, z, data);
}
}

View file

@ -13,7 +13,7 @@ public:
static const unsigned int LEAF2_NAMES[LEAF2_NAMES_SIZE];
private:
//[0] = Fancy (Trasparenti), [1] = Fast (Opache)
//index 0, fancy; index 1, fast
static const wstring TEXTURES[2][2];
Icon *icons[2][2];

View file

@ -1,127 +1,110 @@

#include "stdafx.h"
#include "stdafx.h"
#include "PacketListener.h"
#include "LevelParticlesPacket.h"
#include "../Minecraft.Client/ParticleType.h"
LevelParticlesPacket::LevelParticlesPacket()
{
this->overrideLimiter = false;
this->type = nullptr;
this->count = 0;
this->y = 0.0f;
this->paramCount = 0;
this->x = 0.0f;
this->yDist = 0.0f;
this->zDist = 0.0f;
this->z = 0.0f;
this->maxSpeed = 0.0f;
this->xDist = 0.0f;
this->params = nullptr;
this->name = L"";
this->x = 0.0f;
this->y = 0.0f;
this->z = 0.0f;
this->xDist = 0.0f;
this->yDist = 0.0f;
this->zDist = 0.0f;
this->maxSpeed = 0.0f;
this->count = 0;
}
LevelParticlesPacket::LevelParticlesPacket(const ParticleType* type, bool overrideLimiter,
float x, float y, float z,
float xDist, float yDist, float zDist,
float maxSpeed, int count,
arrayWithLength<int> data)
LevelParticlesPacket::LevelParticlesPacket(const wstring& name, float x, float y, float z, float xDist, float yDist, float zDist, float maxSpeed, int count)
{
this->type = type;
this->overrideLimiter = overrideLimiter;
this->x = x;
this->y = y;
this->z = z;
this->xDist = xDist;
this->yDist = yDist;
this->zDist = zDist;
this->maxSpeed = maxSpeed;
this->count = count;
this->paramCount = data.length;
if (data.data && data.length > 0)
{
this->params = new int[data.length];
memcpy(this->params, data.data, data.length * sizeof(int));
}
else
{
this->params = nullptr;
}
}
LevelParticlesPacket::~LevelParticlesPacket()
{
if (params)
{
delete[] params;
params = nullptr;
}
this->name = name;
this->x = x;
this->y = y;
this->z = z;
this->xDist = xDist;
this->yDist = yDist;
this->zDist = zDist;
this->maxSpeed = maxSpeed;
this->count = count;
}
void LevelParticlesPacket::read(DataInputStream* dis)
{
int particleId = dis->readInt();
const ParticleType* resolved = ParticleType::byId(particleId);
if (!resolved)
resolved = ParticleType::getDefault();
this->type = resolved;
this->overrideLimiter = dis->readBoolean();
this->x = dis->readFloat();
this->y = dis->readFloat();
this->z = dis->readFloat();
this->xDist = dis->readFloat();
this->yDist = dis->readFloat();
this->zDist = dis->readFloat();
this->maxSpeed = dis->readFloat();
this->count = dis->readInt();
int paramCount = this->type ? this->type->getParamCount() : 0;
this->paramCount = paramCount;
if (paramCount > 0)
{
this->params = new int[paramCount]();
for (int i = 0; i < paramCount; i++)
{
this->params[i] = dis->readInt();
}
}
else
{
this->params = nullptr;
}
name = readUtf(dis, 64);
x = dis->readFloat();
y = dis->readFloat();
z = dis->readFloat();
xDist = dis->readFloat();
yDist = dis->readFloat();
zDist = dis->readFloat();
maxSpeed = dis->readFloat();
count = dis->readInt();
}
void LevelParticlesPacket::write(DataOutputStream* dos)
{
dos->writeInt(this->type ? this->type->getId() : 0);
dos->writeBoolean(this->overrideLimiter);
dos->writeFloat(this->x);
dos->writeFloat(this->y);
dos->writeFloat(this->z);
dos->writeFloat(this->xDist);
dos->writeFloat(this->yDist);
dos->writeFloat(this->zDist);
dos->writeFloat(this->maxSpeed);
dos->writeInt(this->count);
writeUtf(name, dos);
dos->writeFloat(x);
dos->writeFloat(y);
dos->writeFloat(z);
dos->writeFloat(xDist);
dos->writeFloat(yDist);
dos->writeFloat(zDist);
dos->writeFloat(maxSpeed);
dos->writeInt(count);
}
int toWrite = this->type ? this->type->getParamCount() : 0;
for (int i = 0; i < toWrite; i++)
{
dos->writeInt(this->params[i]);
}
wstring LevelParticlesPacket::getName()
{
return name;
}
double LevelParticlesPacket::getX()
{
return x;
}
double LevelParticlesPacket::getY()
{
return y;
}
double LevelParticlesPacket::getZ()
{
return z;
}
float LevelParticlesPacket::getXDist()
{
return xDist;
}
float LevelParticlesPacket::getYDist()
{
return yDist;
}
float LevelParticlesPacket::getZDist()
{
return zDist;
}
float LevelParticlesPacket::getMaxSpeed()
{
return maxSpeed;
}
int LevelParticlesPacket::getCount()
{
return count;
}
void LevelParticlesPacket::handle(PacketListener* listener)
{
listener->handleParticleEvent(shared_from_this());
listener->handleParticleEvent(shared_from_this());
}
int LevelParticlesPacket::getEstimatedSize()
{
return 0x40;
return 4 * 2 + 7 * 8;
}

View file

@ -1,53 +1,39 @@
#pragma once
#include "Packet.h"
#include "../Minecraft.Client/ParticleType.h"
class LevelParticlesPacket : public Packet, public enable_shared_from_this<LevelParticlesPacket>
{
private:
const ParticleType* type;
float x;
float y;
float z;
float xDist;
float yDist;
float zDist;
float maxSpeed;
int count;
bool overrideLimiter;
int* params;
int paramCount;
wstring name;
float x;
float y;
float z;
float xDist;
float yDist;
float zDist;
float maxSpeed;
int count;
public:
LevelParticlesPacket();
LevelParticlesPacket(const ParticleType* type, bool overrideLimiter,
float x, float y, float z,
float xDist, float yDist, float zDist,
float maxSpeed, int count,
arrayWithLength<int> data);
~LevelParticlesPacket();
LevelParticlesPacket();
LevelParticlesPacket(const wstring& name, float x, float y, float z, float xDist, float yDist, float zDist, float maxSpeed, int count);
void read(DataInputStream* dis) override;
void write(DataOutputStream* dos) override;
void read(DataInputStream* dis);
void write(DataOutputStream* dos);
wstring getName();
double getX();
double getY();
double getZ();
float getXDist();
float getYDist();
float getZDist();
float getMaxSpeed();
int getCount();
void handle(PacketListener* listener);
int getEstimatedSize();
const ParticleType* getType() { return type; }
double getX() { return x; }
double getY() { return y; }
double getZ() { return z; }
double getXDist() { return xDist; }
double getYDist() { return yDist; }
double getZDist() { return zDist; }
double getMaxSpeed() { return maxSpeed; }
int getCount() { return count; }
bool isOverrideLimiter() { return overrideLimiter; }
int* getParams() { return params; }
int getParamCount() { return paramCount; }
void handle(PacketListener* listener) override;
int getEstimatedSize() override;
static shared_ptr<Packet> create() { return std::make_shared<LevelParticlesPacket>(); }
virtual int getId() override { return 63; }
public:
static shared_ptr<Packet> create() { return std::make_shared<LevelParticlesPacket>(); }
virtual int getId() { return 63; }
};

View file

@ -51,9 +51,10 @@ public:
static const int DATA_ARROW_COUNT_ID = 9;
private:
BaseAttributeMap* attributes;
CombatTracker* combatTracker;
unordered_map<int, MobEffectInstance*> activeEffects;
protected:
BaseAttributeMap* attributes;
ItemInstanceArray lastEquipment;
public:

View file

@ -63,18 +63,18 @@ void MobCategory::setMaxInstancesPerLevel(int max)
m_maxPerLevel = max;
}
int MobCategory::maxAnimalsWithBreeding() { return creature->getMaxInstancesPerLevel() + 20; }
int MobCategory::maxChickensWithBreeding() { return creature_chicken->getMaxInstancesPerLevel() + 8; }
int MobCategory::maxMushroomCowsWithBreeding() { return creature_mushroomcow->getMaxInstancesPerLevel() + 20; }
int MobCategory::maxWolvesWithBreeding() { return creature_wolf->getMaxInstancesPerLevel() + 8; }
int MobCategory::maxAnimalsWithBreeding() { return (creature->getMaxInstancesPerLevel() + 20)*2; }
int MobCategory::maxChickensWithBreeding() { return (creature_chicken->getMaxInstancesPerLevel() + 8)*2; }
int MobCategory::maxMushroomCowsWithBreeding() { return (creature_mushroomcow->getMaxInstancesPerLevel() + 20)*2; }
int MobCategory::maxWolvesWithBreeding() { return (creature_wolf->getMaxInstancesPerLevel() + 8)*2; }
int MobCategory::maxAnimalsWithSpawnEgg() { return maxAnimalsWithBreeding() + 20; }
int MobCategory::maxChickensWithSpawnEgg() { return maxChickensWithBreeding() + 10; }
int MobCategory::maxWolvesWithSpawnEgg() { return maxWolvesWithBreeding() + 10; }
int MobCategory::maxMonstersWithSpawnEgg() { return monster->getMaxInstancesPerLevel() + 20; }
int MobCategory::maxMushroomCowsWithSpawnEgg() { return maxMushroomCowsWithBreeding() + 8; }
int MobCategory::maxSquidsWithSpawnEgg() { return waterCreature->getMaxInstancesPerLevel() + 8; }
int MobCategory::maxAmbientWithSpawnEgg() { return ambient->getMaxInstancesPerLevel() + 8; }
int MobCategory::maxAnimalsWithSpawnEgg() { return (maxAnimalsWithBreeding() + 20)*2; }
int MobCategory::maxChickensWithSpawnEgg() { return (maxChickensWithBreeding() + 10)*2; }
int MobCategory::maxWolvesWithSpawnEgg() { return (maxWolvesWithBreeding() + 10)*2; }
int MobCategory::maxMonstersWithSpawnEgg() { return (monster->getMaxInstancesPerLevel() + 20)*2; }
int MobCategory::maxMushroomCowsWithSpawnEgg() { return (maxMushroomCowsWithBreeding() + 8)*2; }
int MobCategory::maxSquidsWithSpawnEgg() { return (waterCreature->getMaxInstancesPerLevel() + 8)*2; }
int MobCategory::maxAmbientWithSpawnEgg() { return (ambient->getMaxInstancesPerLevel() + 8)*2; }
Material *MobCategory::getSpawnPositionMaterial()
{

View file

@ -7,9 +7,9 @@ class MobCategory
{
public:
// 4J - putting constants for xbox spawning in one place to tidy things up a bit - all numbers are per level
static const int CONSOLE_MONSTERS_HARD_LIMIT = 50; // Max number of enemies (skeleton, zombie, creeper etc) that the mob spawner will produce
static const int CONSOLE_ANIMALS_HARD_LIMIT = 50; // Max number of animals (cows, sheep, pigs) that the mob spawner will produce
static const int CONSOLE_AMBIENT_HARD_LIMIT = 20; // Ambient mobs
static const int CONSOLE_MONSTERS_HARD_LIMIT = 100; // Max number of enemies (skeleton, zombie, creeper etc) that the mob spawner will produce
static const int CONSOLE_ANIMALS_HARD_LIMIT = 100; // Max number of animals (cows, sheep, pigs) that the mob spawner will produce
static const int CONSOLE_AMBIENT_HARD_LIMIT = 40; // Ambient mobs
static const int MAX_XBOX_CHICKENS = 8; // Max number of chickens that the mob spawner will produce
static const int MAX_XBOX_WOLVES = 8; // Max number of wolves that the mob spawner will produce
@ -20,7 +20,7 @@ public:
static const int MAX_CONSOLE_BOSS = 1; // Max number of bosses (enderdragon/wither)
// 4J Villager breeding/egg limits - villagers are not a MobCategory so these stay hardcoded
static const int MAX_VILLAGERS_WITH_BREEDING = 35;
static const int MAX_VILLAGERS_WITH_BREEDING = 70;
static const int MAX_XBOX_VILLAGERS_WITH_SPAWN_EGG = MAX_VILLAGERS_WITH_BREEDING + 15;
// Breeding headroom above the natural spawn cap. Read at call time so these

View file

@ -137,9 +137,13 @@ void MobEffect::applyEffectTick(shared_ptr<LivingEntity> mob, int amplification)
}
else if (id == poison->id)
{
if (mob->getHealth() > 1.0f)
// poison must never reduce health below 1 hp
// if the current health is between 1 and 2 hp the player is left at exactly 1 HP rather than dying.
float currentHealth = mob->getHealth();
if (currentHealth > 1.0f)
{
mob->hurt(DamageSource::magic, 1.0f);
float poisonDmg = min(1.0f, currentHealth - 1.0f);
mob->hurt(DamageSource::magic, poisonDmg);
}
}
else if (id == wither->id)

View file

@ -30,7 +30,7 @@ MoveEntityPacket::MoveEntityPacket(int id)
void MoveEntityPacket::read(DataInputStream *dis) //throws IOException
{
id = dis->readShort();
id = dis->readInt();
}
void MoveEntityPacket::write(DataOutputStream *dos) //throws IOException
@ -40,7 +40,7 @@ void MoveEntityPacket::write(DataOutputStream *dos) //throws IOException
// We shouln't be tracking an entity that doesn't have a short type of id
DEBUG_BREAK();
}
dos->writeShort(static_cast<short>(id));
dos->writeInt(static_cast<short>(id));
}
void MoveEntityPacket::handle(PacketListener *listener)
@ -50,7 +50,7 @@ void MoveEntityPacket::handle(PacketListener *listener)
int MoveEntityPacket::getEstimatedSize()
{
return 2;
return 4;
}
bool MoveEntityPacket::canBeInvalidated()
@ -101,7 +101,7 @@ void MoveEntityPacket::PosRot::write(DataOutputStream *dos) //throws IOException
int MoveEntityPacket::PosRot::getEstimatedSize()
{
return 2+5;
return 4+5;
}
MoveEntityPacket::Pos::Pos()
@ -133,7 +133,7 @@ void MoveEntityPacket::Pos::write(DataOutputStream *dos) //throws IOException
int MoveEntityPacket::Pos::getEstimatedSize()
{
return 2+3;
return 4+3;
}
MoveEntityPacket::Rot::Rot()
@ -164,5 +164,5 @@ void MoveEntityPacket::Rot::write(DataOutputStream *dos) //throws IOException
int MoveEntityPacket::Rot::getEstimatedSize()
{
return 2+2;
return 4+2;
}

View file

@ -37,7 +37,7 @@ MoveEntityPacketSmall::MoveEntityPacketSmall(int id)
void MoveEntityPacketSmall::read(DataInputStream *dis) //throws IOException
{
id = dis->readShort();
id = dis->readInt();
}
void MoveEntityPacketSmall::write(DataOutputStream *dos) //throws IOException
@ -47,7 +47,7 @@ void MoveEntityPacketSmall::write(DataOutputStream *dos) //throws IOException
// We shouln't be tracking an entity that doesn't have a short type of id
DEBUG_BREAK();
}
dos->writeShort(static_cast<short>(id));
dos->writeInt(id);
}
void MoveEntityPacketSmall::handle(PacketListener *listener)
@ -57,7 +57,7 @@ void MoveEntityPacketSmall::handle(PacketListener *listener)
int MoveEntityPacketSmall::getEstimatedSize()
{
return 2;
return 4;
}
bool MoveEntityPacketSmall::canBeInvalidated()
@ -88,13 +88,12 @@ MoveEntityPacketSmall::PosRot::PosRot(int id, char xa, char ya, char za, char yR
void MoveEntityPacketSmall::PosRot::read(DataInputStream *dis) //throws IOException
{
int idAndRot = dis->readShort();
this->id = idAndRot & 0x07ff;
this->yRot = idAndRot >> 11;
int xAndYAndZ = (int)dis->readShort();
this->xa = xAndYAndZ >> 11;
this->ya = (xAndYAndZ << 21 ) >> 26;
this->za = (xAndYAndZ << 27 ) >> 27;
this->id = dis->readInt();
this->yRot = dis->readChar();
int XandYandZ = (int)dis->readShort();
this->xa = XandYandZ >> 11;
this->ya = (XandYandZ << 21 ) >> 26;
this->za = (XandYandZ << 27 ) >> 27;
}
void MoveEntityPacketSmall::PosRot::write(DataOutputStream *dos) //throws IOException
@ -104,15 +103,15 @@ void MoveEntityPacketSmall::PosRot::write(DataOutputStream *dos) //throws IOExce
// We shouln't be tracking an entity that doesn't have a short type of id
DEBUG_BREAK();
}
short idAndRot = id | yRot << 11;
dos->writeShort(idAndRot);
short xAndYAndZ = ( xa << 11 ) | ( ( ya & 0x3f ) << 5 ) | ( za & 0x1f );
dos->writeShort(xAndYAndZ);
dos->writeInt(id);
dos->writeChar(yRot);
short XandYandZ = ( xa << 11 ) | ( ( ya & 0x3f ) << 5 ) | ( za & 0x1f );
dos->writeShort(XandYandZ);
}
int MoveEntityPacketSmall::PosRot::getEstimatedSize()
{
return 4;
return 7;
}
MoveEntityPacketSmall::Pos::Pos()
@ -128,9 +127,8 @@ MoveEntityPacketSmall::Pos::Pos(int id, char xa, char ya, char za) : MoveEntityP
void MoveEntityPacketSmall::Pos::read(DataInputStream *dis) //throws IOException
{
int idAndY = dis->readShort();
this->id = idAndY & 0x07ff;
this->ya = idAndY >> 11;
this->id = dis->readInt();
this->ya = dis->readChar();
int XandZ = (int)static_cast<signed char>(dis->readByte());
xa = XandZ >> 4;
za = ( XandZ << 28 ) >> 28;
@ -143,15 +141,15 @@ void MoveEntityPacketSmall::Pos::write(DataOutputStream *dos) //throws IOExcepti
// We shouln't be tracking an entity that doesn't have a short type of id
DEBUG_BREAK();
}
short idAndY = id | ya << 11;
dos->writeShort(idAndY);
dos->writeInt(id);
dos->writeChar(ya);
char XandZ = ( xa << 4 ) | ( za & 0x0f );
dos->writeByte(XandZ);
}
int MoveEntityPacketSmall::Pos::getEstimatedSize()
{
return 3;
return 7;
}
MoveEntityPacketSmall::Rot::Rot()
@ -169,9 +167,8 @@ MoveEntityPacketSmall::Rot::Rot(int id, char yRot, char xRot) : MoveEntityPacket
void MoveEntityPacketSmall::Rot::read(DataInputStream *dis) //throws IOException
{
int idAndRot = (int)dis->readShort();
this->id = idAndRot & 0x07ff;
this->yRot = idAndRot >> 11;
this->id = dis->readInt();
this->yRot = dis->readChar();
}
void MoveEntityPacketSmall::Rot::write(DataOutputStream *dos) //throws IOException
@ -181,11 +178,11 @@ void MoveEntityPacketSmall::Rot::write(DataOutputStream *dos) //throws IOExcepti
// We shouln't be tracking an entity that doesn't have a short type of id
DEBUG_BREAK();
}
short idAndRot = id | yRot << 11;
dos->writeShort(idAndRot);
dos->writeInt(id);
dos->writeChar(yRot);
}
int MoveEntityPacketSmall::Rot::getEstimatedSize()
{
return 2;
return 5;
}

View file

@ -35,13 +35,16 @@ Ocelot::Ocelot(Level *level) : TamableAnimal(level)
registerAttributes();
setHealth(getMaxHealth());
avoidPlayerGoal = nullptr;
reassessTameGoals();
setSize(0.6f, 0.8f);
getNavigation()->setAvoidWater(true);
goalSelector.addGoal(1, new FloatGoal(this));
goalSelector.addGoal(2, sitGoal, false);
goalSelector.addGoal(3, temptGoal = new TemptGoal(this, SNEAK_SPEED_MOD, Item::fish_raw_Id, true), false);
goalSelector.addGoal(4, new AvoidPlayerGoal(this, typeid(Player), 16, WALK_SPEED_MOD, SPRINT_SPEED_MOD));
goalSelector.addGoal(5, new FollowOwnerGoal(this, FOLLOW_SPEED_MOD, 10, 5));
goalSelector.addGoal(6, new OcelotSitOnTileGoal(this, SPRINT_SPEED_MOD));
goalSelector.addGoal(7, new LeapAtTargetGoal(this, 0.3f));
@ -60,6 +63,21 @@ void Ocelot::defineSynchedData()
entityData->define(DATA_TYPE_ID, static_cast<byte>(0));
}
void Ocelot::reassessTameGoals()
{
if (!avoidPlayerGoal)
avoidPlayerGoal = new AvoidPlayerGoal(this, typeid(Player), 16, WALK_SPEED_MOD, SPRINT_SPEED_MOD);
goalSelector.removeGoal(avoidPlayerGoal);
if (!isTame())
goalSelector.addGoal(4, avoidPlayerGoal, false);
}
void Ocelot::setTame(bool tame)
{
TamableAnimal::setTame(tame);
}
void Ocelot::serverAiMobStep()
{
if (getMoveControl()->hasWanted())
@ -199,7 +217,10 @@ bool Ocelot::mobInteract(shared_ptr<Player> player)
}
else
{
if (temptGoal->isRunning() && item != nullptr && item->id == Item::fish_raw_Id && player->distanceToSqr(shared_from_this()) < 3 * 3)
//player must be close holding raw fish
// temptGoal->isRunning() check removed
// when the player enters interaction range, which would block taming entirely
if (item != nullptr && item->id == Item::fish_raw_Id && player->distanceToSqr(shared_from_this()) < 3 * 3)
{
// 4J-PB - don't lose the fish in creative mode
if (!player->abilities.instabuild) item->count--;
@ -284,6 +305,8 @@ void Ocelot::setCatType(int type)
bool Ocelot::canSpawn()
{
//return level->random->nextInt(3) != 0; when checkSpawnObstruction is implemented
// artificially make ozelots more rare
if (level->random->nextInt(3) == 0)
{

View file

@ -1,6 +1,7 @@
#pragma once
#include "TamableAnimal.h"
#include "AvoidPlayerGoal.h"
class TemptGoal;
@ -32,6 +33,7 @@ public:
private:
TemptGoal *temptGoal;
AvoidPlayerGoal *avoidPlayerGoal;
public:
Ocelot(Level *level);
@ -41,6 +43,8 @@ protected:
public:
virtual void serverAiMobStep();
virtual void reassessTameGoals();
virtual void setTame(bool tame);
protected:
virtual bool removeWhenFarAway();
@ -78,6 +82,7 @@ public:
virtual int getCatType();
virtual void setCatType(int type);
virtual bool canSpawn();
//virtual bool checkSpawnObstruction(); TODO when blockstates will be merged.
virtual wstring getAName();
virtual MobGroupData *finalizeMobSpawn(MobGroupData *groupData, int extraData = 0); // 4J Added extraData param

View file

@ -103,7 +103,5 @@ public:
static shared_ptr<ItemInstance> readItem(DataInputStream *dis);
static void writeItem(shared_ptr<ItemInstance> item, DataOutputStream *dos);
static CompoundTag *readNbt(DataInputStream *dis);
protected:
static void writeNbt(CompoundTag *tag, DataOutputStream *dos);
};

View file

@ -29,21 +29,12 @@ DWORD PistonBaseTile::tlsIdx = TlsAlloc();
// For us, that means that if we create a piston next to another one, then one of them gets two events to createPush, the second of which fails, leaving the
// piston in a bad (simultaneously extended & not extended) state.
// 4J - ignoreUpdate is a static in java, implementing as TLS here to make thread safe
bool PistonBaseTile::ignoreUpdate()
{
return (TlsGetValue(tlsIdx) != nullptr);
}
void PistonBaseTile::ignoreUpdate(bool set)
{
TlsSetValue(tlsIdx,(LPVOID)(set?1:0));
}
//I removed the code for ignoreUpdate so the above comment no longer applies ^.^
PistonBaseTile::PistonBaseTile(int id, bool isSticky) : Tile(id, Material::piston, isSolidRender() )
{
// 4J - added initialiser
ignoreUpdate(false);
this->isSticky = isSticky;
setSoundType(SOUND_STONE);
setDestroyTime(0.5f);
@ -131,7 +122,7 @@ void PistonBaseTile::setPlacedBy(Level *level, int x, int y, int z, shared_ptr<L
{
int targetData = getNewFacing(level, x, y, z, dynamic_pointer_cast<Player>(by) );
level->setData(x, y, z, targetData, Tile::UPDATE_CLIENTS);
if (!level->isClientSide && !ignoreUpdate())
if (!level->isClientSide)
{
checkIfExtend(level, x, y, z);
}
@ -139,7 +130,7 @@ void PistonBaseTile::setPlacedBy(Level *level, int x, int y, int z, shared_ptr<L
void PistonBaseTile::neighborChanged(Level *level, int x, int y, int z, int type)
{
if (!level->isClientSide && !ignoreUpdate())
if (!level->isClientSide)
{
checkIfExtend(level, x, y, z);
}
@ -147,7 +138,7 @@ void PistonBaseTile::neighborChanged(Level *level, int x, int y, int z, int type
void PistonBaseTile::onPlace(Level *level, int x, int y, int z)
{
if (!level->isClientSide && level->getTileEntity(x, y, z) == nullptr && !ignoreUpdate())
if (!level->isClientSide && level->getTileEntity(x, y, z) == nullptr)
{
checkIfExtend(level, x, y, z);
}
@ -212,7 +203,6 @@ bool PistonBaseTile::getNeighborSignal(Level *level, int x, int y, int z, int fa
bool PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1, int facing)
{
ignoreUpdate(true);
if (!level->isClientSide)
{
@ -221,12 +211,10 @@ bool PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1,
if (extend && param1 == TRIGGER_CONTRACT)
{
level->setData(x, y, z, facing | EXTENDED_BIT, UPDATE_CLIENTS);
ignoreUpdate(false);
return false;
}
else if (!extend && param1 == TRIGGER_EXTEND)
{
ignoreUpdate(false);
return false;
}
}
@ -253,7 +241,6 @@ bool PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1,
}
if (FourKitBridge::FirePistonExtend(level->dimension->id, x, y, z, facing, pushLength))
{
ignoreUpdate(false);
return false;
}
}
@ -277,7 +264,6 @@ bool PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1,
}
else
{
ignoreUpdate(false);
return false;
}
PIXEndNamedEvent();
@ -288,7 +274,6 @@ bool PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1,
if (FourKitBridge::FirePistonRetract(level->dimension->id, x, y, z, facing))
{
level->setData(x, y, z, facing | EXTENDED_BIT, UPDATE_CLIENTS);
ignoreUpdate(false);
return false;
}
#endif
@ -353,32 +338,24 @@ bool PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1,
level->setTileAndData(x, y, z, Tile::pistonMovingPiece_Id, blockData, Tile::UPDATE_ALL);
level->setTileEntity(x, y, z, PistonMovingPiece::newMovingPieceEntity(block, blockData, facing, false, false));
ignoreUpdate(false);
level->removeTile(twoX, twoY, twoZ);
ignoreUpdate(true);
}
else if (!pistonPiece)
{
stopSharingIfServer(level, x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]); // 4J added
ignoreUpdate(false);
level->removeTile(x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]);
ignoreUpdate(true);
}
PIXEndNamedEvent();
}
else
{
stopSharingIfServer(level, x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]); // 4J added
ignoreUpdate(false);
level->removeTile(x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]);
ignoreUpdate(true);
}
level->playSound(x + 0.5, y + 0.5, z + 0.5, eSoundType_TILE_PISTON_IN, 0.5f, level->random->nextFloat() * 0.15f + 0.6f);
}
ignoreUpdate(false);
return true;
}

View file

@ -27,8 +27,7 @@ private:
static DWORD tlsIdx;
// 4J - was just a static but implemented with TLS for our version
static bool ignoreUpdate();
static void ignoreUpdate(bool set);
//code removed so the above comment no longer applies
public:
PistonBaseTile(int id, bool isSticky);
@ -68,4 +67,4 @@ private:
static void stopSharingIfServer(Level *level, int x, int y, int z); // 4J added
bool createPush(Level *level, int sx, int sy, int sz, int facing);
};
};

View file

@ -29,20 +29,14 @@ void Recipes::_init()
{
// 4J Jev: instance = new Recipes();
recipies = new RecipyList();
}
Recipes::Recipes()
{
int iCount=0;
_init();
pArmorRecipes = new ArmorRecipes;
pClothDyeRecipes = new ClothDyeRecipes;
pFoodRecipies = new FoodRecipies;
pOreRecipies = new OreRecipies;
pStructureRecipies = new StructureRecipies;
pToolRecipies = new ToolRecipies;
pWeaponRecipies = new WeaponRecipies;
pArmorRecipes = new ArmorRecipes;
pClothDyeRecipes = new ClothDyeRecipes;
pFoodRecipies = new FoodRecipies;
pOreRecipies = new OreRecipies;
pStructureRecipies = new StructureRecipies;
pToolRecipies = new ToolRecipies;
pWeaponRecipies = new WeaponRecipies;
// 4J Stu - These just don't work with our crafting menu
//recipies->push_back(new ArmorDyeRecipe());
@ -50,8 +44,10 @@ Recipes::Recipes()
//recipies->add(new MapExtendingRecipe());
//recipies->add(new FireworksRecipe());
pFireworksRecipes = new FireworksRecipe();
}
void Recipes::_compileRecipes()
{
addShapedRecipy(new ItemInstance(Tile::wood, 4, 0), //
L"sczg",
L"#", //
@ -186,7 +182,7 @@ Recipes::Recipes()
L"W#W", //
L"W#W", //
L'#', Item::stick,
L'#', Item::stick,
L'W', new ItemInstance(Tile::wood, 1, TreeTile::ACACIA_TRUNK),
L'S');
@ -195,7 +191,7 @@ Recipes::Recipes()
L"W#W", //
L"W#W", //
L'#', Item::stick,
L'#', Item::stick,
L'W', new ItemInstance(Tile::wood, 1, TreeTile::DARK_TRUNK),
L'S');
@ -475,12 +471,10 @@ Recipes::Recipes()
L'S');
pArmorRecipes->addRecipes(this);
//iCount=getRecipies()->size();
pClothDyeRecipes->addRecipes(this);
addShapedRecipy(new ItemInstance(Tile::snow, 1), //
L"sscig",
L"##", //
@ -497,7 +491,7 @@ Recipes::Recipes()
L'#', Item::prismarine_shard,
L'S');
addShapedRecipy(new ItemInstance(Tile::prismarine, 1,PrismarineTile::TYPE_BRICKS), //
addShapedRecipy(new ItemInstance(Tile::prismarine, 1, PrismarineTile::TYPE_BRICKS), //
L"ssscig",
L"###", //
L"###", //
@ -507,7 +501,7 @@ Recipes::Recipes()
L'S');
addShapedRecipy(new ItemInstance(Tile::prismarine, 1,PrismarineTile::TYPE_DARK), //
addShapedRecipy(new ItemInstance(Tile::prismarine, 1, PrismarineTile::TYPE_DARK), //
L"ssscicig",
L"###", //
L"#X#", //
@ -657,10 +651,6 @@ Recipes::Recipes()
//iCount=getRecipies()->size();
addShapedRecipy(new ItemInstance(Item::cake, 1), //
L"ssscicicicig",
L"AAA", //
@ -770,7 +760,7 @@ Recipes::Recipes()
L'#', Tile::wood,
L'V');
addShapedRecipy(new ItemInstance((Item *)Item::fishingRod, 1), //
addShapedRecipy(new ItemInstance((Item*)Item::fishingRod, 1), //
L"ssscicig",
L" #", //
L" #X", //
@ -803,7 +793,7 @@ Recipes::Recipes()
L'F');
// Moved bow and arrow in from weapons to avoid stacking on the group name display
addShapedRecipy(new ItemInstance((Item *)Item::bow, 1), //
addShapedRecipy(new ItemInstance((Item*)Item::bow, 1), //
L"ssscicig",
L" #X", //
L"# X", //
@ -850,7 +840,7 @@ Recipes::Recipes()
L'#', Tile::glass,
L'T');
// torch made of charcoal - moved to be the default due to the tutorial using it
addShapedRecipy(new ItemInstance(Tile::torch, 4), //
@ -961,12 +951,12 @@ Recipes::Recipes()
addShapelessRecipy(new ItemInstance(Item::fireball, 3), //
L"iiig",
Item::gunpowder, Item::blazePowder,Item::coal,
Item::gunpowder, Item::blazePowder, Item::coal,
L'T');
addShapelessRecipy(new ItemInstance(Item::fireball, 3), //
L"iizg",
Item::gunpowder, Item::blazePowder,new ItemInstance(Item::coal, 1, CoalItem::CHAR_COAL),
Item::gunpowder, Item::blazePowder, new ItemInstance(Item::coal, 1, CoalItem::CHAR_COAL),
L'T');
addShapedRecipy(new ItemInstance(Item::lead, 2), //
@ -1096,24 +1086,24 @@ Recipes::Recipes()
L'#', Tile::wood, L'X', Item::diamond,
'D');
addShapedRecipy(new ItemInstance(Item::leather, 1),
L"sscig",
L"##",
L"##",
L'#', Item::rabbit_hide,
L'D');
addShapedRecipy(new ItemInstance(Item::leather, 1),
L"sscig",
L"##",
L"##",
L'#', Item::rabbit_hide,
L'D');
addShapedRecipy(new ItemInstance(Item::armor_stand, 1),
L"ssscictg",
L"SSS",
L" S ",
L"SXS",
L'S', Item::stick,
L'X', Tile::stoneSlabHalf,
L"ssscictg",
L"SSS",
L" S ",
L"SXS",
L'S', Item::stick,
L'X', Tile::stoneSlabHalf,
L'D');
addShapedRecipy(new ItemInstance(Item::paper, 3), //
@ -1206,21 +1196,21 @@ Recipes::Recipes()
L'D');
// 4J - TODO - put these new 1.7.3 items in required place within recipes
addShapedRecipy(new ItemInstance(static_cast<Tile *>(Tile::pistonBase), 1), //
addShapedRecipy(new ItemInstance(static_cast<Tile*>(Tile::pistonBase), 1), //
L"sssctcicictg",
L"TTT", //
L"#X#", //
L"#R#", //
L"TTT", //
L"#X#", //
L"#R#", //
L'#', Tile::cobblestone, L'X', Item::ironIngot, L'R', Item::redStone, L'T', Tile::wood,
L'#', Tile::cobblestone, L'X', Item::ironIngot, L'R', Item::redStone, L'T', Tile::wood,
L'M');
addShapedRecipy(new ItemInstance(static_cast<Tile *>(Tile::pistonStickyBase), 1), //
addShapedRecipy(new ItemInstance(static_cast<Tile*>(Tile::pistonStickyBase), 1), //
L"sscictg",
L"S", //
L"P", //
L"S", //
L"P", //
L'S', Item::slimeBall, L'P', Tile::pistonBase,
L'S', Item::slimeBall, L'P', Tile::pistonBase,
L'M');
@ -1233,7 +1223,7 @@ Recipes::Recipes()
L'P', Item::paper, L'G', Item::gunpowder,
L'D');
addShapedRecipy(new ItemInstance(Item::fireworksCharge,1), //
addShapedRecipy(new ItemInstance(Item::fireworksCharge, 1), //
L"sscicig",
L" D ", //
L" G ", //
@ -1241,7 +1231,7 @@ Recipes::Recipes()
L'D', Item::dye_powder, L'G', Item::gunpowder,
L'D');
addShapedRecipy(new ItemInstance(Item::fireworksCharge,1), //
addShapedRecipy(new ItemInstance(Item::fireworksCharge, 1), //
L"sscicig",
L" D ", //
L" C ", //
@ -1249,37 +1239,38 @@ Recipes::Recipes()
L'D', Item::dye_powder, L'C', Item::fireworksCharge,
L'D');
// Sort so the largest recipes get checked first!
/* 4J-PB - TODO
Collections.sort(recipies, new Comparator<Recipy>()
{
public: int compare(Recipy r0, Recipy r1)
{
// shapeless recipes are put in the back of the list
if (r0 instanceof ShapelessRecipy && r1 instanceof ShapedRecipy)
{
return 1;
}
if (r1 instanceof ShapelessRecipy && r0 instanceof ShapedRecipy)
{
return -1;
}
if (r1.size() < r0.size()) return -1;
if (r1.size() > r0.size()) return 1;
return 0;
}
});
*/
// 4J-PB removed System.out.println(recipies->size() + L" recipes");
// 4J-PB - build the array of ingredients required per recipe
buildRecipeIngredientsArray();
}
void Recipes::_wipeRecipes()
{
int iCount = recipies->size();
for (int i = 0; i < iCount; i++) {
Recipy::INGREDIENTS_REQUIRED& req = m_pRecipeIngredientsRequired[i];
delete[] req.iIngIDA;
delete[] req.iIngValA;
delete[] req.iIngAuxValA;
delete[] req.uiGridA;
}
for (int i = 0; i < iCount; i++) {
delete (*recipies)[i];
}
recipies->clear();
delete[] m_pRecipeIngredientsRequired;
m_pRecipeIngredientsRequired = nullptr;
}
Recipes::Recipes()
{
_init();
_compileRecipes();
}
// 4J-PB - this function has been substantially changed due to the differences with a va_list of classes in C++ and Java
ShapedRecipy *Recipes::addShapedRecipy(ItemInstance *result, ...)
{
@ -1563,7 +1554,7 @@ void Recipes::buildRecipeIngredientsArray(void)
int iRecipeC=static_cast<int>(recipies->size());
m_pRecipeIngredientsRequired= new Recipy::INGREDIENTS_REQUIRED [iRecipeC];
m_pRecipeIngredientsRequired = new Recipy::INGREDIENTS_REQUIRED [iRecipeC];
int iCount=0;
for (auto& recipe : *recipies)
@ -1577,4 +1568,46 @@ void Recipes::buildRecipeIngredientsArray(void)
Recipy::INGREDIENTS_REQUIRED *Recipes::getRecipeIngredientsArray(void)
{
return m_pRecipeIngredientsRequired;
}
}
void Recipes::loadFromLocal()
{
this->_wipeRecipes();
this->_compileRecipes();
}
void Recipes::loadFromPacket(byteArray packetData)
{
ByteArrayInputStream bais(packetData);
DataInputStream input(&bais);
this->_wipeRecipes();
{
int iCount = input.readInt();
for (int i = 0; i < iCount; i++) {
int recipeType = input.readByte();
if (recipeType == 1) {
recipies->push_back(ShapelessRecipy::readFromStream(&input));
} else if (recipeType == 2) {
recipies->push_back(ShapedRecipy::readFromStream(&input));
}
}
}
this->buildRecipeIngredientsArray();
}
std::shared_ptr<CustomPayloadPacket> Recipes::createUpdatePacket()
{
ByteArrayOutputStream baos;
DataOutputStream dos(&baos);
int iCount = recipies->size();
dos.writeInt(iCount);
for (int i = 0; i < iCount; i++) {
(*recipies)[i]->writeToStream(&dos);
}
return std::make_shared<CustomPayloadPacket>(CustomPayloadPacket::UPDATE_RECIPE_REGISTRY, baos.toByteArray());
}

View file

@ -16,6 +16,7 @@ import net.minecraft.world.level.tile.Tile;
*/
#include "Recipy.h"
#include "../Minecraft.World/CustomPayloadPacket.h"
#pragma once
using namespace std;
@ -84,6 +85,8 @@ public:
private:
void _init(); // 4J add
void _compileRecipes();
void _wipeRecipes();
Recipes();
public:
@ -97,6 +100,11 @@ public:
shared_ptr<ItemInstance> getItemForRecipe(Recipy *r);
Recipy::INGREDIENTS_REQUIRED *getRecipeIngredientsArray();
void loadFromLocal();
void loadFromPacket(byteArray packetData);
std::shared_ptr<CustomPayloadPacket> createUpdatePacket();
private:
void buildRecipeIngredientsArray();
Recipy::INGREDIENTS_REQUIRED *m_pRecipeIngredientsRequired;

View file

@ -10,13 +10,13 @@
#define RECIPE_TYPE_2x2 0
#define RECIPE_TYPE_3x3 1
class Recipy
class Recipy
{
public:
enum _eGroupType
{
eGroupType_First=0,
eGroupType_Structure=0,
eGroupType_First = 0,
eGroupType_Structure = 0,
eGroupType_Tool,
eGroupType_Food,
eGroupType_Armour,
@ -28,28 +28,30 @@ public:
eGroupType; // to class the item produced by the recipe
// 4J-PB - we'll classing an ingredient ID with a different aux value as a different IngID AuxVal pair
typedef struct
typedef struct
{
int iIngC;
int iType; // Can be a 2x2 or a 3x3. Inventory crafting can only make a 2x2.
int *iIngIDA;
int *iIngValA;
int *iIngAuxValA;
Recipy *pRecipy;
int* iIngIDA;
int* iIngValA;
int* iIngAuxValA;
Recipy* pRecipy;
bool bCanMake[XUSER_MAX_COUNT];
unsigned int *uiGridA; // hold the layout of the recipe (id | auxval<<24)
unsigned int* uiGridA; // hold the layout of the recipe (id | auxval<<24)
unsigned short usBitmaskMissingGridIngredients[XUSER_MAX_COUNT]; // each bit set means we don't have that grid ingredient
}
INGREDIENTS_REQUIRED;
~Recipy() {}
virtual bool matches(shared_ptr<CraftingContainer> craftSlots, Level *level) = 0;
virtual ~Recipy() = default;
virtual bool matches(shared_ptr<CraftingContainer> craftSlots, Level* level) = 0;
virtual shared_ptr<ItemInstance> assemble(shared_ptr<CraftingContainer> craftSlots) = 0;
virtual int size() = 0;
virtual const ItemInstance *getResultItem() = 0;
virtual const int getGroup() = 0;
virtual const ItemInstance* getResultItem() = 0;
virtual const int getGroup() = 0;
// 4J-PB
virtual bool reqs(int iRecipe) = 0;
virtual void reqs(INGREDIENTS_REQUIRED *pIngReq) = 0;
virtual void reqs(INGREDIENTS_REQUIRED* pIngReq) = 0;
virtual void writeToStream(DataOutputStream* dos) = 0;
};

View file

@ -58,7 +58,7 @@ void RespawnPacket::read(DataInputStream *dis) //throws IOException
mapSeed = dis->readLong();
difficulty = dis->readByte();
m_newSeaLevel = dis->readBoolean();
m_newEntityId = dis->readShort();
m_newEntityId = dis->readInt();
#ifdef _LARGE_WORLDS
m_xzSize = dis->readShort();
m_hellScale = dis->read();
@ -83,7 +83,7 @@ void RespawnPacket::write(DataOutputStream *dos) //throws IOException
dos->writeLong(mapSeed);
dos->writeByte(difficulty);
dos->writeBoolean(m_newSeaLevel);
dos->writeShort(m_newEntityId);
dos->writeInt(m_newEntityId);
#ifdef _LARGE_WORLDS
dos->writeShort(m_xzSize);
dos->write(m_hellScale);
@ -97,5 +97,5 @@ int RespawnPacket::getEstimatedSize()
{
length = static_cast<int>(m_pLevelType->getGeneratorName().length());
}
return 13+length;
return 13+length+2;
}

View file

@ -49,9 +49,9 @@ SetEntityMotionPacket::SetEntityMotionPacket(int id, double xd, double yd, doubl
void SetEntityMotionPacket::read(DataInputStream *dis) //throws IOException
{
short idAndFlag = dis->readShort();
id = idAndFlag & 0x07ff;
if( idAndFlag & 0x0800 )
useBytes = dis->readBoolean();
id = dis->readInt();
if(useBytes)
{
xa = static_cast<int>(dis->readByte());
ya = static_cast<int>(dis->readByte());
@ -62,29 +62,28 @@ void SetEntityMotionPacket::read(DataInputStream *dis) //throws IOException
xa *= 16;
ya *= 16;
za *= 16;
useBytes = true;
}
else
{
xa = dis->readShort();
ya = dis->readShort();
za = dis->readShort();
useBytes = false;
}
}
void SetEntityMotionPacket::write(DataOutputStream *dos) //throws IOException
{
dos->writeBoolean(useBytes);
if( useBytes )
{
dos->writeShort(id | 0x800);
dos->writeInt(id);
dos->writeByte(xa/16);
dos->writeByte(ya/16);
dos->writeByte(za/16);
}
else
{
dos->writeShort(id);
dos->writeInt(id);
dos->writeShort(xa);
dos->writeShort(ya);
dos->writeShort(za);
@ -98,7 +97,7 @@ void SetEntityMotionPacket::handle(PacketListener *listener)
int SetEntityMotionPacket::getEstimatedSize()
{
return useBytes ? 5 : 8;
return useBytes ? 8 : 11;
}
bool SetEntityMotionPacket::canBeInvalidated()

Some files were not shown because too many files have changed in this diff Show more