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 - type: input
id: itsrevela id: itsrevela
attributes: 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. description: If this was a "no idea" or similar, it will be rejected.
validations: validations:
required: true 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 name: Nightly Release
on: on:
push: push:
branches: branches:
- experimental - main
workflow_dispatch: workflow_dispatch:
permissions: permissions:

2
BUMP
View file

@ -1 +1 @@
1.0.2b 1.0.8b

View file

@ -235,10 +235,14 @@ if(TARGET Minecraft.Server)
endif() endif()
set(_item_map_inputs 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/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 #neo: added ItemNameMap generation
add_custom_command( add_custom_command(
OUTPUT "${CMAKE_BINARY_DIR}/generated/ItemNameMap.h" OUTPUT "${CMAKE_BINARY_DIR}/generated/ItemNameMap.h"
@ -262,6 +266,32 @@ if(PLATFORM_NAME STREQUAL "Windows64")
add_dependencies(Minecraft.Server GenerateItemNameMap) add_dependencies(Minecraft.Server GenerateItemNameMap)
endif() 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 target_include_directories(Minecraft.Client PRIVATE
"${CMAKE_CURRENT_BINARY_DIR}/generated" "${CMAKE_CURRENT_BINARY_DIR}/generated"
) )

View file

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

View file

@ -16,6 +16,7 @@
#include "PlayerRenderer.h" #include "PlayerRenderer.h"
#include "../Minecraft.World/SkullItem.h" #include "../Minecraft.World/SkullItem.h"
#include "../Minecraft.World/SkullTileEntity.h" #include "../Minecraft.World/SkullTileEntity.h"
#include "../Minecraft.World/ElytraItem.h"
static const float DEG_TO_RAD = 3.14159265f / 180.0f; 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, double x, double y, double z,
float rot, float a) 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); 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, void ArmorStandRenderer::renderModel(shared_ptr<LivingEntity> mob,
float wp, float ws, float bob, float wp, float ws, float bob,
float headRotMinusBodyRot, float headRotMinusBodyRot,
@ -165,7 +179,109 @@ void ArmorStandRenderer::renderModel(shared_ptr<LivingEntity> mob,
void ArmorStandRenderer::additionalRendering(shared_ptr<LivingEntity> mob, float a) 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 headRotMinusBodyRot,
float headRotx, float scale) override; float headRotx, float scale) override;
virtual int prepareArmor(shared_ptr<LivingEntity> mob, int layer, float a) 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; virtual void additionalRendering(shared_ptr<LivingEntity> mob, float a) override;
}; };

View file

@ -61,6 +61,8 @@
#include "Windows64/Network/WinsockNetLayer.h" #include "Windows64/Network/WinsockNetLayer.h"
#endif #endif
#include "../Minecraft.World/Recipes.h"
#ifdef _DURANGO #ifdef _DURANGO
#include "../Minecraft.World/DurangoStats.h" #include "../Minecraft.World/DurangoStats.h"
@ -137,6 +139,9 @@ ClientConnection::ClientConnection(Minecraft *minecraft, Socket *socket, int iUs
maxPlayers = 20; maxPlayers = 20;
m_isForkServer = false; m_isForkServer = false;
m_recivedRecipeRegistyUpdate = false;
m_recivedCreativeRegistyUpdate = false;
this->minecraft = minecraft; this->minecraft = minecraft;
if( iUserIndex < 0 ) if( iUserIndex < 0 )
@ -246,6 +251,14 @@ void ClientConnection::handleLogin(shared_ptr<LoginPacket> packet)
{ {
if (done) return; if (done) return;
if (!m_recivedRecipeRegistyUpdate) {
Recipes::getInstance()->loadFromLocal();
}
if (!m_recivedCreativeRegistyUpdate) {
IUIScene_CreativeMenu::loadFromLocal();
}
PlayerUID OnlineXuid; PlayerUID OnlineXuid;
ProfileManager.GetXUID(m_userIndex,&OnlineXuid,true); // online xuid ProfileManager.GetXUID(m_userIndex,&OnlineXuid,true); // online xuid
MOJANG_DATA *pMojangData = nullptr; 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() Connection *ClientConnection::getConnection()
@ -4300,22 +4323,19 @@ void ClientConnection::handleSetPlayerTeamPacket(shared_ptr<SetPlayerTeamPacket>
void ClientConnection::handleParticleEvent(shared_ptr<LevelParticlesPacket> packet) void ClientConnection::handleParticleEvent(shared_ptr<LevelParticlesPacket> packet)
{ {
const ParticleType* type = packet->getType(); ePARTICLE_TYPE particleId = (ePARTICLE_TYPE)Integer::parseInt(packet->getName());
if (type == nullptr) return;
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++) level->addParticle(particleId, packet->getX() + xVarience, packet->getY() + yVarience, packet->getZ() + zVarience, xa, ya, za);
{ }
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);
}
} }
void ClientConnection::handleUpdateAttributes(shared_ptr<UpdateAttributesPacket> packet) void ClientConnection::handleUpdateAttributes(shared_ptr<UpdateAttributesPacket> packet)

View file

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

View file

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

View file

@ -1,3 +1,4 @@
#include "IUIScene_CreativeMenu.h"
#include "stdafx.h" #include "stdafx.h"
#include "IUIScene_CreativeMenu.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 ITEM_AUX(id, aux) list->push_back( shared_ptr<ItemInstance>(new ItemInstance(id, 1, aux)) );
#define DEF(index) list = &categoryGroups[index]; #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() void IUIScene_CreativeMenu::staticCtor()
{ {
vector< shared_ptr<ItemInstance> > *list; 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)) ITEM_AUX(Item::potion_Id,MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_LEVEL2EXTENDED, MASK_JUMPBOOST))
// end of tu31 potions // 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 };
// Top Row specs[eCreativeInventoryTab_BuildingBlocks] = new TabSpec(L"Structures", IDS_GROUPNAME_BUILDING_BLOCKS, 1, blocksGroup);
ECreative_Inventory_Groups blocksGroup[] = {eCreativeInventory_BuildingBlocks};
specs[eCreativeInventoryTab_BuildingBlocks] = new TabSpec(L"Structures", IDS_GROUPNAME_BUILDING_BLOCKS, 1, blocksGroup);
#ifndef _CONTENT_PACKAGE #ifndef _CONTENT_PACKAGE
ECreative_Inventory_Groups decorationsGroup[] = {eCreativeInventory_Decoration}; ECreative_Inventory_Groups decorationsGroup[] = { eCreativeInventory_Decoration };
ECreative_Inventory_Groups debugDecorationsGroup[] = {eCreativeInventory_ArtToolsDecorations}; ECreative_Inventory_Groups debugDecorationsGroup[] = { eCreativeInventory_ArtToolsDecorations };
specs[eCreativeInventoryTab_Decorations] = new TabSpec(L"Decoration", IDS_GROUPNAME_DECORATIONS, 1, decorationsGroup, 0, nullptr, 1, debugDecorationsGroup); specs[eCreativeInventoryTab_Decorations] = new TabSpec(L"Decoration", IDS_GROUPNAME_DECORATIONS, 1, decorationsGroup, 0, nullptr, 1, debugDecorationsGroup);
#else #else
ECreative_Inventory_Groups decorationsGroup[] = {eCreativeInventory_Decoration}; ECreative_Inventory_Groups decorationsGroup[] = { eCreativeInventory_Decoration };
specs[eCreativeInventoryTab_Decorations] = new TabSpec(L"Decoration", IDS_GROUPNAME_DECORATIONS, 1, decorationsGroup); specs[eCreativeInventoryTab_Decorations] = new TabSpec(L"Decoration", IDS_GROUPNAME_DECORATIONS, 1, decorationsGroup);
#endif #endif
ECreative_Inventory_Groups redAndTranGroup[] = {eCreativeInventory_Transport, eCreativeInventory_Redstone}; ECreative_Inventory_Groups redAndTranGroup[] = { eCreativeInventory_Transport, eCreativeInventory_Redstone };
specs[eCreativeInventoryTab_RedstoneAndTransport] = new TabSpec(L"RedstoneAndTransport", IDS_GROUPNAME_REDSTONE_AND_TRANSPORT, 2, redAndTranGroup); specs[eCreativeInventoryTab_RedstoneAndTransport] = new TabSpec(L"RedstoneAndTransport", IDS_GROUPNAME_REDSTONE_AND_TRANSPORT, 2, redAndTranGroup);
ECreative_Inventory_Groups materialsGroup[] = {eCreativeInventory_Materials}; ECreative_Inventory_Groups materialsGroup[] = { eCreativeInventory_Materials };
specs[eCreativeInventoryTab_Materials] = new TabSpec(L"Materials", IDS_GROUPNAME_MATERIALS, 1, materialsGroup); specs[eCreativeInventoryTab_Materials] = new TabSpec(L"Materials", IDS_GROUPNAME_MATERIALS, 1, materialsGroup);
ECreative_Inventory_Groups foodGroup[] = {eCreativeInventory_Food}; ECreative_Inventory_Groups foodGroup[] = { eCreativeInventory_Food };
specs[eCreativeInventoryTab_Food] = new TabSpec(L"Food", IDS_GROUPNAME_FOOD, 1, foodGroup); specs[eCreativeInventoryTab_Food] = new TabSpec(L"Food", IDS_GROUPNAME_FOOD, 1, foodGroup);
ECreative_Inventory_Groups toolsGroup[] = {eCreativeInventory_ToolsArmourWeapons}; ECreative_Inventory_Groups toolsGroup[] = { eCreativeInventory_ToolsArmourWeapons };
specs[eCreativeInventoryTab_ToolsWeaponsArmor] = new TabSpec(L"Tools", IDS_GROUPNAME_TOOLS_WEAPONS_ARMOR, 1, toolsGroup); 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 // 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 // In 480p there's not enough room for the LT button, so use text instead
//if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) //if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen())
{ {
specs[eCreativeInventoryTab_Brewing] = new TabSpec(L"Brewing", IDS_GROUPNAME_POTIONS_480, 5, brewingGroup); 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() IUIScene_CreativeMenu::IUIScene_CreativeMenu()

View file

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

View file

@ -5,6 +5,7 @@
#include "UIScene.h" #include "UIScene.h"
#include "UIControl_Slider.h" #include "UIControl_Slider.h"
#include "UIControl_TexturePackList.h" #include "UIControl_TexturePackList.h"
#include "UIControl_CheckBox.h"
#include "UIControl_AchievementsList.h" #include "UIControl_AchievementsList.h"
#include "UIScene_AchievementsMenu.h" #include "UIScene_AchievementsMenu.h"
#include "../../../Minecraft.World/StringHelpers.h" #include "../../../Minecraft.World/StringHelpers.h"
@ -836,6 +837,7 @@ void UIController::tickInput()
{ {
#ifdef _WINDOWS64 #ifdef _WINDOWS64
m_mouseClickConsumedByScene = false; m_mouseClickConsumedByScene = false;
UIControl* currHitCtrl = NULL;
if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
{ {
UIScene *pScene = nullptr; UIScene *pScene = nullptr;
@ -1010,6 +1012,7 @@ void UIController::tickInput()
hitControlId = -1; hitControlId = -1;
hitArea = INT_MAX; hitArea = INT_MAX;
hitCtrl = NULL; hitCtrl = NULL;
hitCtrl = ctrl;
break; // ButtonList takes priority break; // ButtonList takes priority
} }
if (type == UIControl::eAchievementList) if (type == UIControl::eAchievementList)
@ -1022,6 +1025,7 @@ void UIController::tickInput()
hitControlId = -1; hitControlId = -1;
hitArea = INT_MAX; hitArea = INT_MAX;
hitCtrl = NULL; hitCtrl = NULL;
hitCtrl = ctrl;
break; break;
} }
if (type == UIControl::eTexturePackList) 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() void UIController::handleInput()
{ {
// For each user, loop over each key type and send messages based on the state // 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); SetMenuDisplayed(menuDisplayedPad,true);
bool success = m_groups[static_cast<int>(group)]->NavigateToScene(iPad, scene, initData, layer); bool success = m_groups[static_cast<int>(group)]->NavigateToScene(iPad, scene, initData, layer);
if(success && group == eUIGroup_Fullscreen) setFullscreenMenuDisplayed(true); if(success && group == eUIGroup_Fullscreen) setFullscreenMenuDisplayed(true);
UpdateCursorIcon(nullptr);
LeaveCriticalSection(&m_navigationLock); LeaveCriticalSection(&m_navigationLock);
timer.PrintElapsedTime(L"Navigate to scene"); 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); 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); if(!m_groups[static_cast<int>(eUIGroup_Fullscreen)]->GetMenuDisplayed()) SetMenuDisplayed(XUSER_INDEX_ANY,false);
} }
UpdateCursorIcon(nullptr);
return navComplete; return navComplete;
} }

View file

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

View file

@ -2,6 +2,12 @@
#include "UI.h" #include "UI.h"
#include "UIScene_Intro.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) 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 #elif defined _XBOX_ONE
ui.NavigateToScene(0,eUIScene_MainMenu); 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 #else
ui.NavigateToScene(0,eUIScene_SaveMessage); ui.NavigateToScene(0,eUIScene_SaveMessage);
#endif #endif
@ -169,6 +251,82 @@ void UIScene_Intro::handleAnimationEnd()
{ {
m_bAnimationEnded = true; 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 #else
ui.NavigateToScene(0,eUIScene_SaveMessage); ui.NavigateToScene(0,eUIScene_SaveMessage);
#endif #endif

View file

@ -6,7 +6,7 @@
#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" #include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
#include "..\..\..\Minecraft.World\net.minecraft.stats.h" #include "..\..\..\Minecraft.World\net.minecraft.stats.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.effect.h" #include "..\..\..\Minecraft.World\net.minecraft.world.effect.h"
#include "..\..\MultiplayerLocalPlayer.h" #include "..\..\MultiPlayerLocalPlayer.h"
#include "..\..\Minecraft.h" #include "..\..\Minecraft.h"
#include "..\..\Options.h" #include "..\..\Options.h"
#include "..\..\EntityRenderDispatcher.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); IggyValueSetBooleanRS(&path, visibleName, nullptr, false);
} }
} }
updateServerDescription();
} }
} }
} }
@ -129,46 +131,46 @@ void UIScene_JoinMenu::updateTooltips()
void UIScene_JoinMenu::tick() void UIScene_JoinMenu::tick()
{ {
if( !m_friendInfoRequestIssued ) if (!m_friendInfoRequestIssued)
{ {
ui.NavigateToScene(m_iPad, eUIScene_Timer); ui.NavigateToScene(m_iPad, eUIScene_Timer);
g_NetworkManager.GetFullFriendSessionInfo(m_selectedSession, &friendSessionUpdated, this); g_NetworkManager.GetFullFriendSessionInfo(m_selectedSession, &friendSessionUpdated, this);
m_friendInfoRequestIssued = true; m_friendInfoRequestIssued = true;
} }
if( m_friendInfoUpdatedOK ) if (m_friendInfoUpdatedOK)
{ {
m_friendInfoUpdatedOK = false; 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.init(eControl_GamePlayers);
m_buttonListPlayers.setYPos( m_buttonListPlayers.getYPos() + 300 ); m_buttonListPlayers.setYPos(m_buttonListPlayers.getYPos() + 300);
#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__ #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 #ifndef _CONTENT_PACKAGE
if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards))) if (app.DebugSettingsOn() && (app.GetGameSettingsDebugMask() & (1L << eDebugSetting_DebugLeaderboards)))
{ {
m_buttonListPlayers.addItem(L"WWWWWWWWWWWWWWWW"); m_buttonListPlayers.addItem(L"WWWWWWWWWWWWWWWW");
} }
else else
#endif #endif
{ {
string playerName(m_selectedSession->data.players[i].getOnlineID()); 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) // 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]; char suffix[5];
sprintf(suffix, " (%d)", m_selectedSession->data.players[i].getQuadrant() + 1); sprintf(suffix, " (%d)", m_selectedSession->data.players[i].getQuadrant() + 1);
playerName.append(suffix); playerName.append(suffix);
} }
#endif #endif
m_buttonListPlayers.addItem(playerName); m_buttonListPlayers.addItem(playerName);
} }
} }
@ -179,9 +181,9 @@ void UIScene_JoinMenu::tick()
} }
} }
#elif defined(_DURANGO) #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]); 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)); m_labelLabels[eLabel_FireOn].init(app.GetString(IDS_LABEL_FIRE_SPREADS));
unsigned int uiGameHostSettings = m_selectedSession->data.m_uiGameHostSettings; unsigned int uiGameHostSettings = m_selectedSession->data.m_uiGameHostSettings;
switch(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_Difficulty)) switch (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_Difficulty))
{ {
case Difficulty::EASY: 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; break;
case Difficulty::NORMAL: 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; break;
case Difficulty::HARD: 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; break;
case Difficulty::PEACEFUL: case Difficulty::PEACEFUL:
default: default:
m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL) ); m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL));
break; break;
} }
int option = app.GetGameHostOption(uiGameHostSettings,eGameHostOption_GameType); int option = app.GetGameHostOption(uiGameHostSettings, eGameHostOption_GameType);
if(option == GameType::CREATIVE->getId()) 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 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) ); 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) ); 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) ); 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) ); 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) ); 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) ); 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) ); 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) ); 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) ); 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) ); 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) ); 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) ); 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) ); 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) ); else m_labelValues[eLabel_FireOn].init(app.GetString(IDS_OFF));
m_bIgnoreInput = false; m_bIgnoreInput = false;
// Alert the app the we want to be informed of ethernet connections // 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); 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.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_Difficulty].init(app.GetString(IDS_LABEL_DIFFICULTY));
m_labelLabels[eLabel_GameType].init(app.GetString(IDS_LABEL_GAME_TYPE)); 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_labelLabels[eLabel_FireOn].init(app.GetString(IDS_LABEL_FIRE_SPREADS));
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL)); m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL));
m_labelValues[eLabel_GameType].init( app.GetString(IDS_CREATIVE) ); m_labelValues[eLabel_GameType].init(app.GetString(IDS_CREATIVE));
m_labelValues[eLabel_GamertagsOn].init( app.GetString(IDS_OFF) ); m_labelValues[eLabel_GamertagsOn].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_Structures].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_LevelType].init(app.GetString(IDS_LEVELTYPE_NORMAL));
m_labelValues[eLabel_PVP].init( app.GetString(IDS_OFF) ); m_labelValues[eLabel_PVP].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_Trust].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_TNTOn].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_FireOn].init( app.GetString(IDS_OFF) ); m_labelValues[eLabel_FireOn].init(app.GetString(IDS_OFF));
m_friendInfoUpdatedERROR = false; m_friendInfoUpdatedERROR = false;
@ -310,9 +312,9 @@ void UIScene_JoinMenu::tick()
UINT uiIDA[1]; UINT uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK; uiIDA[0] = IDS_CONFIRM_OK;
#ifdef _XBOX_ONE #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 #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 #endif
} }
@ -323,84 +325,7 @@ void UIScene_JoinMenu::tick()
{ {
IggyPlayerTickRS(s_movieServerDesc); IggyPlayerTickRS(s_movieServerDesc);
IggyValuePath *root = IggyPlayerRootPath(s_movieServerDesc); updateServerDescription();
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);
}
}
}
} }
} }
#endif #endif
@ -408,6 +333,88 @@ void UIScene_JoinMenu::tick()
UIScene::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) void UIScene_JoinMenu::friendSessionUpdated(bool success, void *pParam)
{ {
UIScene_JoinMenu *scene = static_cast<UIScene_JoinMenu *>(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 // TODO: This should be pure virtual in this class
virtual wstring getMoviePath(); virtual wstring getMoviePath();
void updateServerDescription();
public: public:
public: public:
// INPUT // 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/SkullTileEntity.h"
#include "../Minecraft.World/LivingEntity.h" #include "../Minecraft.World/LivingEntity.h"
#include "../Minecraft.World/Facing.h" #include "../Minecraft.World/Facing.h"
#include "../Minecraft.Client/SimpleIcon.h"
#include "../Minecraft.World/AirTile.h"
CustomHeadLayer::CustomHeadLayer(ModelPart* headPart, LivingEntityRenderer* parentRenderer) CustomHeadLayer::CustomHeadLayer(ModelPart* headPart, LivingEntityRenderer* parentRenderer)
: headPart(headPart), parentRenderer(parentRenderer) : headPart(headPart), parentRenderer(parentRenderer)
{ {
tileRenderer = new TileRenderer();
}
CustomHeadLayer::~CustomHeadLayer() {
delete tileRenderer;
} }
int CustomHeadLayer::colorsOnDamage() int CustomHeadLayer::colorsOnDamage()
@ -90,12 +98,136 @@ void CustomHeadLayer::render(shared_ptr<LivingEntity> mob,
glRotatef(90.0f, 0.0f, 1.0f, 0.0f); glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
Minecraft* mc = Minecraft::GetInstance();
if (mc)
{ {
auto* iihr = mc->getItemInHandRenderer(); // 4J - code borrowed from render method below, although not factoring in brightness as that should already be being taken into account
if (iihr) // by texture lighting. This is for colourising things held in 3rd person view.
iihr->renderItem(mob, helmet, 0, true); 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 ModelPart;
class LivingEntity; class LivingEntity;
class LivingEntityRenderer; class LivingEntityRenderer;
class TileRenderer;
class CustomHeadLayer : public RenderLayer { class CustomHeadLayer : public RenderLayer {
public: public:
ModelPart* headPart; ModelPart* headPart;
LivingEntityRenderer* parentRenderer; LivingEntityRenderer* parentRenderer;
TileRenderer* tileRenderer;
CustomHeadLayer(ModelPart* headPart, LivingEntityRenderer* parentRenderer); CustomHeadLayer(ModelPart* headPart, LivingEntityRenderer* parentRenderer);
virtual ~CustomHeadLayer() {} virtual ~CustomHeadLayer();
virtual int colorsOnDamage() override; virtual int colorsOnDamage() override;
virtual void render(shared_ptr<LivingEntity> mob, virtual void render(shared_ptr<LivingEntity> mob,

View file

@ -148,6 +148,7 @@ GameRenderer::GameRenderer(Minecraft *mc)
itemInHandRenderer = nullptr; 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 // 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); glEnable(GL_LIGHTING);
mc->localitemInHandRenderers[0] = new ItemInHandRenderer(mc);//itemInHandRenderer; mc->localitemInHandRenderers[0] = new ItemInHandRenderer(mc);//itemInHandRenderer;
mc->localitemInHandRenderers[1] = new ItemInHandRenderer(mc); mc->localitemInHandRenderers[1] = new ItemInHandRenderer(mc);
@ -170,7 +171,9 @@ GameRenderer::GameRenderer(Minecraft *mc)
for(int i=0;i<NUM_LIGHT_TEXTURES;i++) for(int i=0;i<NUM_LIGHT_TEXTURES;i++)
lightPixels[i] = intArray(16*16); lightPixels[i] = intArray(16*16);
#endif #endif
#endif
#ifndef MINECRAFT_SERVER_BUILD
#ifdef MULTITHREAD_ENABLE #ifdef MULTITHREAD_ENABLE
m_updateEvents = new C4JThread::EventArray(eUpdateEventCount, C4JThread::EventArray::e_modeAutoClear); m_updateEvents = new C4JThread::EventArray(eUpdateEventCount, C4JThread::EventArray::e_modeAutoClear);
m_updateEvents->Set(eUpdateEventIsFinished); m_updateEvents->Set(eUpdateEventIsFinished);
@ -183,6 +186,7 @@ GameRenderer::GameRenderer(Minecraft *mc)
m_updateThread->SetProcessor(CPU_CORE_CHUNK_UPDATE); m_updateThread->SetProcessor(CPU_CORE_CHUNK_UPDATE);
m_updateThread->Run(); m_updateThread->Run();
#endif #endif
#endif
} }
// 4J Stu Added to go with 1.8.2 change // 4J Stu Added to go with 1.8.2 change

View file

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

View file

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

View file

@ -110,81 +110,75 @@ void ItemFrameRenderer::drawFrame(shared_ptr<ItemFrame> itemFrame)
void ItemFrameRenderer::drawItem(shared_ptr<ItemFrame> entity) void ItemFrameRenderer::drawItem(shared_ptr<ItemFrame> entity)
{ {
Minecraft *pMinecraft=Minecraft::GetInstance();
shared_ptr<ItemInstance> instance = entity->getItem(); shared_ptr<ItemInstance> instance = entity->getItem();
if (instance == nullptr) return; if (instance == nullptr) return;
shared_ptr<ItemEntity> itemEntity = std::make_shared<ItemEntity>(entity->level, 0, 0, 0, instance); shared_ptr<ItemEntity> itemEntity = std::make_shared<ItemEntity>(entity->level, 0, 0, 0, instance);
itemEntity->getItem()->count = 1; itemEntity->getItem()->count = 1;
itemEntity->bobOffs = 0; 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.0f + entity->yRot, 0, 1, 0);
glRotatef(180 + entity->yRot, 0, 1, 0); glTranslatef(0.0f, 0.0f, -0.4375f);
glRotatef(-90 * entity->getRotation(), 0, 0, 1);
switch (entity->getRotation()) int rotation = entity->getRotation();
{ bool isMap = (itemEntity->getItem()->getItem() == Item::map);
case 1: int effectiveRotation = isMap ? 2 * (rotation % 4) : rotation;
glTranslatef(-0.16f, -0.16f, 0);
break;
case 2:
glTranslatef(0, -0.32f, 0);
break;
case 3:
glTranslatef(0.16f, -0.16f, 0);
break;
}
if (itemEntity->getItem()->getItem() == Item::map) glRotatef(-45.0f * effectiveRotation, 0, 0, 1);
{ glTranslatef(0.0f, -0.41f/2, 0.0f);
entityRenderDispatcher->textures->bindTexture(&MAP_BACKGROUND_LOCATION);
Tesselator *t = Tesselator::getInstance();
glRotatef(180, 0, 1, 0); if (isMap)
glRotatef(180, 0, 0, 1); {
glScalef(1.0f / 128.0f, 1.0f / 128.0f, 1.0f / 128.0f); //entityRenderDispatcher->textures->bindTexture(&MAP_BACKGROUND_LOCATION);
glTranslatef(-64.0f, -87.0f, -3.0f); //Tesselator *t = Tesselator::getInstance();
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();
shared_ptr<MapItemSavedData> data = Item::map->getSavedData(itemEntity->getItem(), entity->level); glRotatef(180, 0, 1, 0);
if (data != nullptr) glRotatef(180, 0, 0, 1);
{ glScalef(1.0f / 128.0f, 1.0f / 128.0f, 1.0f / 128.0f);
entityRenderDispatcher->itemInHandRenderer->minimap->render(nullptr, entityRenderDispatcher->textures, data, entity->entityId); glTranslatef(-64.0f, -87.0f, -3.0f);
}
}
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); //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) shared_ptr<MapItemSavedData> data = Item::map->getSavedData(itemEntity->getItem(), entity->level);
{ if (data != nullptr)
CompassTexture *ct = CompassTexture::instance; {
ct->cycleFrames(); entityRenderDispatcher->itemInHandRenderer->minimap->render(
} nullptr, entityRenderDispatcher->textures, data, entity->entityId);
} }
}
glPopMatrix(); 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) 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) 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; int id;
bool isLoaded; bool isLoaded;
int ticksSinceLastUse; 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(const wstring& _name, PBYTE pbData, DWORD dwBytes, MemTextureProcessor *processor);
~MemTexture(); ~MemTexture();

View file

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

View file

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

View file

@ -266,7 +266,7 @@ private:
#endif #endif
#endif #endif
bool IsServerPaused() { return m_isServerPaused; }
private: private:
// 4J Added // 4J Added
@ -291,6 +291,7 @@ public:
const wstring& getSaveFolderName() const { return m_saveFolderName; } const wstring& getSaveFolderName() const { return m_saveFolderName; }
void Suspend(); void Suspend();
bool IsSuspending(); 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 // 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. // 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 // Without this, environmental damage (drowning, fire, lava) is never applied to clients
// that don't send frequent move packets. // that don't send frequent move packets.
if (!didTick && player != nullptr) if (!didTick && player != nullptr && !server->IsServerPaused() && !app.IsAppPaused())
{ {
player->doTick(false); player->doTick(false);
} }
@ -1046,6 +1046,13 @@ void PlayerConnection::handleCommand(const wstring& message)
ss >> cmd; ss >> cmd;
if (cmd == L"tp" || cmd == L"teleport") 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)) if (!player->hasPermission(eGameCommand_Teleport))
{ {
warn(L"You do not have permission to use this command."); 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") } 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)) if (!player->hasPermission(eGameCommand_Time))
{ {
warn(L"You do not have permission to use this command."); 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") 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)) if (!player->hasPermission(eGameCommand_Kill))
{ {
warn(L"You do not have permission to use this command."); warn(L"You do not have permission to use this command.");
return; 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") 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)) if (!player->hasPermission(eGameCommand_ToggleDownfall))
{ {
warn(L"You do not have permission to use this command."); 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(); shared_ptr<GameCommandPacket> packet = ToggleDownfallCommand::preparePacket();
server->getCommandDispatcher()->performCommand(player, eGameCommand_ToggleDownfall, packet->data); server->getCommandDispatcher()->performCommand(player, eGameCommand_ToggleDownfall, packet->data);
} else if (cmd == L"gamemode") { } 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)) if (!player->hasPermission(eGameCommand_GameMode))
{ {
warn(L"You do not have permission to use this command."); 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); shared_ptr<GameCommandPacket> packet = GameModeCommand::preparePacket(target, mode);
server->getCommandDispatcher()->performCommand(player, eGameCommand_GameMode, packet->data); server->getCommandDispatcher()->performCommand(player, eGameCommand_GameMode, packet->data);
} else if (cmd == L"give") { } 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)) if (!player->hasPermission(eGameCommand_Give))
{ {
warn(L"You do not have permission to use this command."); 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, player->getName().c_str(), player->isModerator() ? 1 : 0, isHost ? 1 : 0,
static_cast<int>(packet->command)); static_cast<int>(packet->command));
#endif #endif
MinecraftServer::getInstance()->getCommandDispatcher()->performCommand(player, packet->command, packet->data); 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); 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); //ByteArrayInputStream bais(customPayloadPacket->data);
//DataInputStream input(&bais); //DataInputStream input(&bais);
//shared_ptr<ItemInstance> sentItem = Packet::readItem(&input); //shared_ptr<ItemInstance> sentItem = Packet::readItem(&input);
@ -2448,7 +2508,7 @@ void PlayerConnection::handleCustomPayload(shared_ptr<CustomPayloadPacket> custo
//PlayerList* playerList = MinecraftServer::getInstance()->getPlayers(); //PlayerList* playerList = MinecraftServer::getInstance()->getPlayers();
//playerList->broadcastAll(std::make_shared<SetEquippedItemPacket>(player->entityId, slot, sentItem)); //playerList->broadcastAll(std::make_shared<SetEquippedItemPacket>(player->entityId, slot, sentItem));
} }*/
else if (CustomPayloadPacket::TRADER_SELECTION_PACKET.compare(customPayloadPacket->identifier) == 0) else if (CustomPayloadPacket::TRADER_SELECTION_PACKET.compare(customPayloadPacket->identifier) == 0)
{ {
ByteArrayInputStream bais(customPayloadPacket->data); ByteArrayInputStream bais(customPayloadPacket->data);

View file

@ -37,6 +37,8 @@
#include "Common/Network/Sony/NetworkPlayerSony.h" #include "Common/Network/Sony/NetworkPlayerSony.h"
#endif #endif
#include "../Minecraft.World/Recipes.h"
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD) #if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
#include "../Minecraft.Server/Access/Access.h" #include "../Minecraft.Server/Access/Access.h"
#include "../Minecraft.Server/Common/StringUtils.h" #include "../Minecraft.Server/Common/StringUtils.h"
@ -51,6 +53,7 @@ extern bool g_Win64DedicatedServer;
static unsigned int s_playerListTickCount = 0; static unsigned int s_playerListTickCount = 0;
static const int kIdentityResponseGraceTicks = 200; // 10 seconds at 20 TPS static const int kIdentityResponseGraceTicks = 200; // 10 seconds at 20 TPS
#endif #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. // 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", app.DebugPrintf("RECONNECT: placeNewPlayer smallId=%d entityId=%d dim=%d\n",
newSmallId, player->entityId, level->dimension->id); 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(), playerConnection->send(std::make_shared<LoginPacket>(L"", player->entityId, level->getLevelData()->getGenerator(),
level->getSeed(), level->getSeed(),
player->gameMode->getGameModeForPlayer()->getId(), player->gameMode->getGameModeForPlayer()->getId(),

View file

@ -23,6 +23,18 @@ Screen::Screen() // 4J added
clickedButton = nullptr; 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) void Screen::render(int xm, int ym, float a)
{ {
for (Button* button : buttons) for (Button* button : buttons)

View file

@ -22,6 +22,7 @@ public:
GuiParticles *particles; GuiParticles *particles;
Screen(); // 4J added Screen(); // 4J added
virtual ~Screen();
virtual void render(int xm, int ym, float a); virtual void render(int xm, int ym, float a);
protected: protected:
virtual void keyPressed(wchar_t eventCharacter, int eventKey); 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) 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>( auto packet = make_shared<LevelParticlesPacket>(
type, buf,
longDistance,
(float)x, (float)y, (float)z, (float)x, (float)y, (float)z,
(float)dx, (float)dy, (float)dz, (float)dx, (float)dy, (float)dz,
(float)speed, (float)speed,
count, count
data
); );
for (auto const& p : players) 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 // 4J - added for implementation of finite limit to number of item entities, tnt and falling block entities
public: public:
static const int MAX_HANGING_ENTITIES = 400; static const int MAX_HANGING_ENTITIES = 800;
static const int MAX_ITEM_ENTITIES = 200; static const int MAX_ITEM_ENTITIES = 400;
static const int MAX_ARROW_ENTITIES = 200; static const int MAX_ARROW_ENTITIES = 400;
static const int MAX_EXPERIENCEORB_ENTITIES = 50; static const int MAX_EXPERIENCEORB_ENTITIES = 100;
static const int MAX_PRIMED_TNT = 20; static const int MAX_PRIMED_TNT = 40;
static const int MAX_FALLING_TILE = 20; 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_primedTntCount;
int m_fallingTileCount; int m_fallingTileCount;

View file

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

View file

@ -290,24 +290,53 @@ void TrackedEntity::tick(EntityTracker *tracker, vector<shared_ptr<Player> > *pl
wasRiding = false; wasRiding = false;
} }
else else
{ {
bool rot = abs(yRotn - yRotp) >= TOLERANCE_LEVEL || abs(xRotn - xRotp) >= TOLERANCE_LEVEL; // the entity have a rider, the code didnt send position updates,
if (rot) // causing desync between client and server when boat was spritning.
{
// 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;
}
xp = Mth::floor(e->x * 32.0); bool rot = abs(yRotn - yRotp) >= TOLERANCE_LEVEL || abs(xRotn - xRotp) >= TOLERANCE_LEVEL;
yp = Mth::floor(e->y * 32.0); if (rot)
zp = Mth::floor(e->z * 32.0); {
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); int yHeadRot = Mth::floor(e->getYHeadRot() * 256 / 360);
if (abs(yHeadRot - yHeadRotp) >= TOLERANCE_LEVEL) 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; 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) void KeyboardMouseInput::OnChar(wchar_t c)
{ {
int next = (m_charBufferHead + 1) % CHAR_BUFFER_SIZE; int next = (m_charBufferHead + 1) % CHAR_BUFFER_SIZE;

View file

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

View file

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

View file

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

View file

@ -149,47 +149,57 @@ static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize)
dest[destSize - 1] = 0; dest[destSize - 1] = 0;
} }
// ---------- Persistent options (options.txt next to exe) ---------- // ---------- Persistent options (options.dat next to exe) ----------
static void GetOptionsFilePath(char *out, size_t outSize) static void GetOptionsFilePath(char *out, DWORD outSize)
{ {
GetModuleFileNameA(nullptr, out, static_cast<DWORD>(outSize)); GetModuleFileNameA(nullptr, out, outSize);
char *p = strrchr(out, '\\'); char *p = strrchr(out, '\\');
if (p) *(p + 1) = '\0'; if (p) *(p + 1) = '\0';
strncat_s(out, outSize, "options.txt", _TRUNCATE); strncat_s(out, outSize, "settings.dat", _TRUNCATE);
} }
static void SaveFullscreenOption(bool fullscreen) static void SaveFullscreenOption(bool fullscreen)
{ {
char path[MAX_PATH]; GAME_SETTINGS settings = {};
GetOptionsFilePath(path, sizeof(path));
FILE *f = nullptr; char path[MAX_PATH] = {};
if (fopen_s(&f, path, "w") == 0 && f) GetOptionsFilePath(path, MAX_PATH);
{ FILE *f = nullptr;
fprintf(f, "fullscreen=%d\n", fullscreen ? 1 : 0); if (fopen_s(&f, path, "rb") == 0 && f)
fclose(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() static bool LoadFullscreenOption()
{ {
char path[MAX_PATH]; char path[MAX_PATH] = {};
GetOptionsFilePath(path, sizeof(path)); GetOptionsFilePath(path, sizeof(path));
FILE *f = nullptr;
if (fopen_s(&f, path, "r") == 0 && f) FILE *f = nullptr;
{ if (fopen_s(&f, path, "rb") != 0 || !f)
char line[256]; return false;
while (fgets(line, sizeof(line), f))
{ GAME_SETTINGS current = {};
int val = 0; bool ok = (fread(&current, sizeof(GAME_SETTINGS), 1, f) == 1);
if (sscanf_s(line, "fullscreen=%d", &val) == 1) fclose(f);
{
fclose(f); if (!ok)
return val != 0; return false;
}
} return (current.uiBitmaskValues & (1UL << 25)) != 0;
fclose(f);
}
return false;
} }
// ------------------------------------------------------------------ // ------------------------------------------------------------------
@ -219,6 +229,7 @@ static Win64LaunchOptions ParseLaunchOptions()
Win64LaunchOptions options = {}; Win64LaunchOptions options = {};
options.screenMode = 0; options.screenMode = 0;
g_Win64MultiplayerQuitOnDisconnect = false;
g_Win64MultiplayerJoin = false; g_Win64MultiplayerJoin = false;
g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT; g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT;
@ -239,6 +250,10 @@ static Win64LaunchOptions ParseLaunchOptions()
{ {
CopyWideArgToAnsi(argv[++i], g_Win64Username, sizeof(g_Win64Username)); 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) else if (_wcsicmp(argv[i], L"-ip") == 0 && (i + 1) < argc)
{ {
char ipBuf[256]; char ipBuf[256];
@ -819,8 +834,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
return FALSE; return FALSE;
} }
ShowWindow(g_hWnd, (nCmdShow != SW_HIDE) ? SW_SHOWMAXIMIZED : nCmdShow);
UpdateWindow(g_hWnd);
return TRUE; return TRUE;
} }
@ -1451,8 +1465,9 @@ void CleanupDevice()
static Minecraft* InitialiseMinecraftRuntime() static Minecraft* InitialiseMinecraftRuntime()
{ {
app.loadMediaArchive(); app.loadMediaArchive();
// @CDevJoud: No need to call this method as it gets called once in `InitDevice()`
RenderManager.Initialise(g_pd3dDevice, g_pSwapChain); // Calling it again and it results of 20MB of memory leak!
//RenderManager.Initialise(g_pd3dDevice, g_pSwapChain);
app.loadStringTable(); app.loadStringTable();
ui.init(g_pd3dDevice, g_pImmediateContext, g_pRenderTargetView, g_pDepthStencilView, g_rScreenWidth, g_rScreenHeight); 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(); CleanupDevice();
return 0; return 0;
} }
// Restore fullscreen state from previous session. Route through the // Restore fullscreen state from previous session. Route through the
// deferred exclusive fullscreen path so the main loop applies it on the // deferred exclusive fullscreen path so the main loop applies it on the
// first tick (safer than transitioning during init). // first tick (safer than transitioning during init).
if ((LoadFullscreenOption() && !g_isFullscreen) || launchOptions.fullscreen)
bool FullScreenEnabled = LoadFullscreenOption();
if (FullScreenEnabled && !g_isFullscreen)
{ {
g_bPendingExclusiveFullscreen = true; g_bPendingExclusiveFullscreen = true;
g_bPendingExclusiveFullscreenValue = true; g_bPendingExclusiveFullscreenValue = true;
@ -1785,6 +1801,20 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
hr = XuiTimersRun(); hr = XuiTimersRun();
} }
#endif #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}; MSG msg = {0};
while( WM_QUIT != msg.message && !app.m_bShutdown) 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>
<data name="IDS_ITEM_RABBIT_STEW"> <data name="IDS_ITEM_RABBIT_STEW">
<value>{*ICON_SHANK_01*}</value> <value>Rabbit Stew</value>
</data> </data>
<data name="IDS_TILE_DOUBLE_TALL_GRASS"> <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_ACHIEVEMENT_VIEW"><value>Hold {*CONTROLLER_VK_Y*} to view</value></data>
<data name="IDS_CHECKBOX_CLASSICCRAFTING"><value>Classic Crafting</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> </root>

View file

@ -1281,10 +1281,9 @@ void __cdecl NativeSpawnParticle(int entityId, int particleId, float x, float y,
{ {
auto player = FindPlayer(entityId); auto player = FindPlayer(entityId);
if (!player || !player->connection) return; if (!player || !player->connection) return;
const ParticleType* type = ParticleType::byId(particleId); wchar_t buf[32];
if (!type) type = ParticleType::getDefault(); swprintf_s(buf, L"%d", particleId);
arrayWithLength<int> noParams = { nullptr, 0 }; player->connection->send(std::make_shared<LevelParticlesPacket>(std::wstring(buf), x, y, z, offsetX, offsetY, offsetZ, speed, count));
player->connection->send(std::make_shared<LevelParticlesPacket>(type, false, x, y, z, offsetX, offsetY, offsetZ, speed, count, noParams));
} }
int __cdecl NativeSetPassenger(int entityId, int passengerEntityId) 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() void AABB::clearPool()
{ {
ThreadStorage *tls = static_cast<ThreadStorage *>(TlsGetValue(tlsIdx));
if (tls != nullptr)
{
tls->poolPointer = 0;
}
} }
void AABB::resetPool() void AABB::resetPool()
{ {
clearPool();
} }
AABB *AABB::newTemp(double x0, double y0, double z0, double x1, double y1, double z1) 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 void AddEntityPacket::read(DataInputStream *dis) // throws IOException TODO 4J JEV add throws statement
{ {
id = dis->readShort(); id = dis->readInt();
type = dis->readByte(); type = dis->readByte();
#ifdef _LARGE_WORLDS #ifdef _LARGE_WORLDS
x = dis->readInt(); 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 void AddEntityPacket::write(DataOutputStream *dos) // throws IOException TODO 4J JEV add throws statement
{ {
dos->writeShort(id); dos->writeInt(id);
dos->writeByte(type); dos->writeByte(type);
#ifdef _LARGE_WORLDS #ifdef _LARGE_WORLDS
dos->writeInt(x); dos->writeInt(x);
@ -107,5 +107,5 @@ void AddEntityPacket::handle(PacketListener *listener)
int AddEntityPacket::getEstimatedSize() 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 void AddMobPacket::read(DataInputStream *dis) //throws IOException
{ {
id = dis->readShort(); id = dis->readInt();
type = dis->readByte() & 0xff; type = dis->readByte() & 0xff;
#ifdef _LARGE_WORLDS #ifdef _LARGE_WORLDS
x = dis->readInt(); x = dis->readInt();
@ -90,7 +90,7 @@ void AddMobPacket::read(DataInputStream *dis) //throws IOException
void AddMobPacket::write(DataOutputStream *dos) //throws IOException void AddMobPacket::write(DataOutputStream *dos) //throws IOException
{ {
dos->writeShort(id); dos->writeInt(id);
dos->writeByte(type & 0xff); dos->writeByte(type & 0xff);
#ifdef _LARGE_WORLDS #ifdef _LARGE_WORLDS
dos->writeInt(x); dos->writeInt(x);
@ -127,7 +127,7 @@ int AddMobPacket::getEstimatedSize()
// 4J Stu - This is an incoming value which we aren't currently analysing // 4J Stu - This is an incoming value which we aren't currently analysing
//size += unpack->get //size += unpack->get
} }
return size; return size + 2;
} }
vector<shared_ptr<SynchedEntityData::DataItem> > *AddMobPacket::getUnpackedData() vector<shared_ptr<SynchedEntityData::DataItem> > *AddMobPacket::getUnpackedData()

View file

@ -16,11 +16,12 @@
#include "ParticleTypes.h" #include "ParticleTypes.h"
#include "Random.h" #include "Random.h"
#include "AABB.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_HEAD_POSE (0.0f, 0.0f, 0.0f);
const Rotations ArmorStand::DEFAULT_BODY_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_LEFT_ARM_POSE (-15.0f, 0.0f, 10.0f);
const Rotations ArmorStand::DEFAULT_RIGHT_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_LEFT_LEG_POSE (-1.0f, 0.0f, -1.0f);
const Rotations ArmorStand::DEFAULT_RIGHT_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++) for (int i = 0; i < equipmentCount; i++)
equipment[i] = nullptr; equipment[i] = nullptr;
rotateElytraX = 0.2617994f;
rotateElytraY = 0.0f;
rotateElytraZ = -0.2617994f;
headPose = DEFAULT_HEAD_POSE; headPose = DEFAULT_HEAD_POSE;
bodyPose = DEFAULT_BODY_POSE; bodyPose = DEFAULT_BODY_POSE;
leftArmPose = DEFAULT_LEFT_ARM_POSE; leftArmPose = DEFAULT_LEFT_ARM_POSE;
@ -83,7 +88,7 @@ void ArmorStand::defineSynchedData()
ArmorStand::~ArmorStand() {} 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::isBaby() const { return (entityData->getByte(DATA_CLIENT_FLAGS) & FLAG_SMALL) != 0; }
bool ArmorStand::isSmall() const { return isBaby(); } bool ArmorStand::isSmall() const { return isBaby(); }
bool ArmorStand::isShowArms() const { return (entityData->getByte(DATA_CLIENT_FLAGS) & FLAG_SHOW_ARMS) != 0; } bool ArmorStand::isShowArms() const { return (entityData->getByte(DATA_CLIENT_FLAGS) & FLAG_SHOW_ARMS) != 0; }
@ -188,6 +193,93 @@ void ArmorStand::updateInvisibilityStatus()
setInvisible(invisible); 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() void ArmorStand::tick()
{ {
@ -195,14 +287,14 @@ void ArmorStand::tick()
LivingEntity::tick(); LivingEntity::tick();
if (onGround) if (onGround)
{ {
BlockPos pos((int)floorf(x), (int)floorf(y) - 1, (int)floorf(z)); BlockPos pos((int)floorf(x), (int)floorf(y) - 1, (int)floorf(z));
int blockId = level->getTile(pos.getX(), pos.getY(), pos.getZ()); int blockId = level->getTile(pos.getX(), pos.getY(), pos.getZ());
if (blockId == Tile::topSnow->id) if (blockId == Tile::topSnow->id)
{ {
int meta = level->getData(pos.getX(), pos.getY(), pos.getZ()); int meta = level->getData(pos.getX(), pos.getY(), pos.getZ());
float snowHeight = ((meta & 0x7) + 1) * 0.125f; float snowHeight = ((meta & 0x7) + 1) * 0.125f;
moveTo(x, floorf(y) + snowHeight, z, yRot, xRot); moveTo(x, floorf(y) + snowHeight, z, yRot, xRot);
} }
} }
this->yRot = lockedRot; this->yRot = lockedRot;
this->yRotO = lockedRot; this->yRotO = lockedRot;

View file

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

View file

@ -8,7 +8,7 @@
const BlockPos BlockPos::ZERO = BlockPos(0, 0, 0); const BlockPos BlockPos::ZERO = BlockPos(0, 0, 0);
// Costruttori
BlockPos::BlockPos() : Vec3i(0, 0, 0) {} BlockPos::BlockPos() : Vec3i(0, 0, 0) {}
BlockPos::BlockPos(int x, int y, int z) : Vec3i(x, y, z) {} 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) BlockPos::BlockPos(BlockSource& source)
: Vec3i(source.getBlockX(), source.getBlockY(), source.getBlockZ()) {} : Vec3i(source.getBlockX(), source.getBlockY(), source.getBlockZ()) {}
// Metodi di confronto
bool BlockPos::equals(const BlockPos& other) const { bool BlockPos::equals(const BlockPos& other) const {
return x == other.x && y == other.y && z == other.z; 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); return BlockPos(x + dx, y, z + dz);
} }
// Metodi direzionali // directional methods
BlockPos BlockPos::above(int distance) const { BlockPos BlockPos::above(int distance) const {
return BlockPos(x, y + distance, z); return BlockPos(x, y + distance, z);
} }
@ -119,7 +119,7 @@ BlockPos BlockPos::multiply(int factor) const {
return BlockPos(x * factor, y * factor, z * factor); return BlockPos(x * factor, y * factor, z * factor);
} }
// Compressione // compression
int BlockPos::compress() const { int BlockPos::compress() const {
static const int MASK_X = (1 << BITS_X) - 1; static const int MASK_X = (1 << BITS_X) - 1;
static const int MASK_Y = (1 << BITS_Y) - 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) if (doLerp)
{ {
lSteps = steps + 5; lSteps = steps +5;
} }
else else
{ {
@ -188,6 +188,10 @@ void Boat::lerpMotion(double xd, double yd, double zd)
void Boat::tick() void Boat::tick()
{ {
Entity::tick(); Entity::tick();
if (getHurtTime() > 0) setHurtTime(getHurtTime() - 1); if (getHurtTime() > 0) setHurtTime(getHurtTime() - 1);
if (getDamage() > 0) setDamage(getDamage() - 1); if (getDamage() > 0) setDamage(getDamage() - 1);
xo = x; xo = x;
@ -199,8 +203,8 @@ void Boat::tick()
double waterPercentage = 0; double waterPercentage = 0;
for (int i = 0; i < steps; i++) for (int i = 0; i < steps; i++)
{ {
double y0 = bb->y0 + (bb->y1 - bb->y0) * (i + 0) / 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 - 2 / 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); AABB *bb2 = AABB::newTemp(bb->x0, y0, bb->z0, bb->x1, y1, bb->z1);
if (level->containsLiquid(bb2, Material::water)) if (level->containsLiquid(bb2, Material::water))
{ {
@ -257,18 +261,19 @@ void Boat::tick()
return; return;
} }
// Bob in water // Bob in water & gravity
if (waterPercentage > 0) if (waterPercentage < 1.0)
{ {
double bob = waterPercentage * 2 - 1; double bob = waterPercentage * 2.0 - 1.0;
yd += 0.04f * bob; yd += 0.04f * bob;
} }
else
// Reimplement gravity again (??)
int tileUnder = level->getTile(Mth::floor(x), Mth::floor(y-0.15), Mth::floor(z));
if (tileUnder == 0 && !onGround)
{ {
yd -= 0.04f; if (yd < 0.0)
{
yd /= 2.0;
}
yd += 0.007f;
} }
// Rider controls // Rider controls
@ -281,24 +286,16 @@ void Boat::tick()
{ {
double riderXd = -sin(livingRider->yRot * PI / 180); double riderXd = -sin(livingRider->yRot * PI / 180);
double riderZd = cos(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; float moveFactor = (float)forward;
if (forward < 0) moveFactor *= 0.5f; // Move slower backwards if (forward < 0) moveFactor *= 0.5f; // Move slower backwards
xd += riderXd * acceleration * 0.05f * mult * moveFactor; xd += riderXd * acceleration * 0.05f * moveFactor;
zd += riderZd * acceleration * 0.05f * mult * moveFactor; zd += riderZd * acceleration * 0.05f * moveFactor;
} }
} }
double curSpeed = sqrt(xd * xd + zd * zd); double curSpeed = sqrt(xd * xd + zd * zd);
double maxSpeed = MAX_SPEED; 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) if (curSpeed > maxSpeed)
{ {
@ -330,10 +327,12 @@ void Boat::tick()
move(xd, yd, zd); move(xd, yd, zd);
// Break boat on high speed collision // Break boat on high speed collision
float breakThreshold = (rider.lock() != nullptr) ? 0.35f : 0.20f;
if ((horizontalCollision && lastSpeed > 0.20)) if ((horizontalCollision && lastSpeed > 0.20))
{ {
if (!level->isClientSide && !removed) if (!level->isClientSide && !removed)
{ {
remove(); remove();
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
@ -343,6 +342,9 @@ void Boat::tick()
{ {
spawnAtLocation(Item::stick->id, 1, 0); spawnAtLocation(Item::stick->id, 1, 0);
} }
} }
} }
else 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 ( (rider.lock() != nullptr) && rider.lock()->instanceof(eTYPE_PLAYER) && (rider.lock() != player) ) return true;
if (!level->isClientSide) 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) // 4J HEG - Fixed issue with player not being able to dismount boat (issue #4446)
player->ride( rider.lock() == player ? nullptr : shared_from_this() ); player->ride(isRiding ? nullptr : shared_from_this());
} }
return true; return true;
} }
void Boat::setDamage(float damage) void Boat::setDamage(float damage)

View file

@ -38,14 +38,54 @@ void ClothDyeRecipes::addRecipes(Recipes *r)
} }
// some dye recipes // 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", L"tg",
Tile::flower,L'D'); 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", L"tg",
Tile::rose,L'D'); 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), r->addShapelessRecipy(new ItemInstance(Item::dye_powder, 3, DyePowderItem::WHITE),
L"ig", L"ig",
Item::bone,L'D'); 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::RED),
new ItemInstance(Item::dye_powder, 1, DyePowderItem::WHITE),L'D'); new ItemInstance(Item::dye_powder, 1, DyePowderItem::WHITE),L'D');
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
r->addShapedRecipy(new ItemInstance(Tile::woolCarpet, 3, 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.item.h"
#include "net.minecraft.world.level.h" #include "net.minecraft.world.level.h"
#include "net.minecraft.world.level.redstone.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 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 dir = getDirection(data);
int xx = x + Direction::STEP_X[dir]; int xx = x + Direction::STEP_X[dir];
int zz = z + Direction::STEP_Z[dir]; int zz = z + Direction::STEP_Z[dir];
int tile = level->getTile(xx, y, zz); int tile = level->getTile(xx, y, zz);
if (tile > 0) if (tile > 0)
{ {
if (Tile::tiles[tile]->hasAnalogOutputSignal()) if (Tile::tiles[tile]->hasAnalogOutputSignal())
{ {
result = Tile::tiles[tile]->getAnalogOutputSignal(level, xx, y, zz, Direction::DIRECTION_OPPOSITE[dir]); result = Tile::tiles[tile]->getAnalogOutputSignal(level, xx, y, zz, Direction::DIRECTION_OPPOSITE[dir]);
} }
else if (result < Redstone::SIGNAL_MAX && Tile::isSolidBlockingTile(tile)) else if (result < Redstone::SIGNAL_MAX && Tile::isSolidBlockingTile(tile))
{ {
xx += Direction::STEP_X[dir]; xx += Direction::STEP_X[dir];
zz += Direction::STEP_Z[dir]; zz += Direction::STEP_Z[dir];
tile = level->getTile(xx, y, zz); tile = level->getTile(xx, y, zz);
if (tile > 0 && Tile::tiles[tile]->hasAnalogOutputSignal()) if (tile > 0 && Tile::tiles[tile]->hasAnalogOutputSignal())
{ {
result = Tile::tiles[tile]->getAnalogOutputSignal(level, xx, y, zz, Direction::DIRECTION_OPPOSITE[dir]); 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) 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() bool ComparatorTile::TestUse()
{ {
return true; 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 "DiodeTile.h"
#include "EntityTile.h" #include "EntityTile.h"
#include "AABB.h"
class ComparatorTileEntity; class ComparatorTileEntity;
@ -57,4 +58,5 @@ public:
virtual bool triggerEvent(Level *level, int x, int y, int z, int b0, int b1); virtual bool triggerEvent(Level *level, int x, int y, int z, int b0, int b1);
virtual shared_ptr<TileEntity> newTileEntity(Level *level); virtual shared_ptr<TileEntity> newTileEntity(Level *level);
virtual bool TestUse(); 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; oldSwell = 0;
maxSwell = 30; maxSwell = 30;
explosionRadius = 3; explosionRadius = 3;
ignited = false;
} }
Creeper::Creeper(Level *level) : Monster( level ) Creeper::Creeper(Level *level) : Monster( level )
@ -190,3 +191,38 @@ void Creeper::thunderHit(const LightningBolt *lightningBolt)
Monster::thunderHit(lightningBolt); Monster::thunderHit(lightningBolt);
entityData->set(DATA_IS_POWERED, static_cast<byte>(1)); 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 maxSwell;
int explosionRadius; int explosionRadius;
bool ignited;
void _init(); void _init();
public: public:
@ -34,6 +36,8 @@ public:
virtual int getMaxFallDistance(); virtual int getMaxFallDistance();
virtual bool mobInteract(shared_ptr<Player> player);
protected: protected:
virtual void causeFallDamage(float distance); virtual void causeFallDamage(float distance);
virtual void defineSynchedData(); virtual void defineSynchedData();
@ -61,5 +65,9 @@ protected:
public: public:
int getSwellDir(); int getSwellDir();
void setSwellDir(int dir); 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" #include "CustomPayloadPacket.h"
// Mojang-defined custom packets // Mojang-defined custom packets
const wstring CustomPayloadPacket::CUSTOM_BOOK_PACKET = L"MC|BEdit"; const wstring CustomPayloadPacket::CUSTOM_BOOK_PACKET = CreateVanillaPayloadKey(L"BEdit");
const wstring CustomPayloadPacket::CUSTOM_BOOK_SIGN_PACKET = L"MC|BSign"; const wstring CustomPayloadPacket::CUSTOM_BOOK_SIGN_PACKET = CreateVanillaPayloadKey(L"BSign");
const wstring CustomPayloadPacket::TEXTURE_PACK_PACKET = L"MC|TPack"; const wstring CustomPayloadPacket::TEXTURE_PACK_PACKET = CreateVanillaPayloadKey(L"TPack");
const wstring CustomPayloadPacket::TRADER_LIST_PACKET = L"MC|TrList"; const wstring CustomPayloadPacket::TRADER_LIST_PACKET = CreateVanillaPayloadKey(L"TrList");
const wstring CustomPayloadPacket::TRADER_SELECTION_PACKET = L"MC|TrSel"; const wstring CustomPayloadPacket::TRADER_SELECTION_PACKET = CreateVanillaPayloadKey(L"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::CIPHER_KEY_CHANNEL = L"MC|CKey"; // neoLegacy-defined custom packets
const wstring CustomPayloadPacket::CIPHER_ACK_CHANNEL = L"MC|CAck"; const wstring CustomPayloadPacket::UPDATE_RECIPE_REGISTRY = CreatePayloadKey(L"neo", L"UpdRReg");
const wstring CustomPayloadPacket::CIPHER_ON_CHANNEL = L"MC|COn"; const wstring CustomPayloadPacket::UPDATE_CREATIVE_REGISTRY = CreatePayloadKey(L"neo", L"UpdCReg");
const wstring CustomPayloadPacket::IDENTITY_TOKEN_ISSUE = L"MC|CTIssue"; //todo: figure out if we should replace the packets in the comment section with a custom payload identifier
const wstring CustomPayloadPacket::IDENTITY_TOKEN_CHALLENGE = L"MC|CTChallenge"; //comment section start
const wstring CustomPayloadPacket::IDENTITY_TOKEN_RESPONSE = L"MC|CTResponse"; 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::CIPHER_KEY_CHANNEL = CreateVanillaPayloadKey(L"CKey");
const wstring CustomPayloadPacket::FORK_PLAYER_LEAVE_CHANNEL = L"MC|ForkPLeave"; 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::IDENTITY_TOKEN_ISSUE = CreateVanillaPayloadKey(L"CTIssue");
const wstring CustomPayloadPacket::QUICK_EQUIP_SERVER_PACKET = L"MC|QEquipServer"; 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() CustomPayloadPacket::CustomPayloadPacket()
: length(0) : length(0)

View file

@ -3,6 +3,9 @@ using namespace std;
#include "Packet.h" #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> class CustomPayloadPacket : public Packet, public enable_shared_from_this<CustomPayloadPacket>
{ {
public: public:
@ -17,6 +20,10 @@ public:
static const wstring SET_BEACON_PACKET; static const wstring SET_BEACON_PACKET;
static const wstring SET_ITEM_NAME_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 // 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_KEY_CHANNEL; // server->client: carries 32-byte key (16 AES key + 16 IV)
static const wstring CIPHER_ACK_CHANNEL; // client->server: ack (empty payload) 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) static const wstring FORK_PLAYER_LEAVE_CHANNEL; // server->client: player disconnected (payload: UTF gamertag)
// Fixes for MP related crashes // Fixes for MP related crashes
static const wstring QUICK_EQUIP_PACKET; //static const wstring QUICK_EQUIP_PACKET;
static const wstring QUICK_EQUIP_SERVER_PACKET; //static const wstring QUICK_EQUIP_SERVER_PACKET;
static const wstring ENCHANTMENT_LIST_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) if (data < 0 || data >= DIRT_NAMES_LENGTH)
data = 0; data = 0;
if (TEXTURE_NAMES[data] == L"dirt_podzol") { if (TEXTURE_NAMES[data] == L"dirt_podzol")
return (face == Facing::UP) ? podzolTop : podzolSide; {
switch(face)
{
case Facing::UP:
return podzolTop;
break;
case Facing::DOWN:
return Tile::dirt->getTexture(face);
break;
default:
return podzolSide;
break;
}
} }
return icons[data]; return icons[data];

View file

@ -6,13 +6,13 @@
#include "net.minecraft.world.item.h" #include "net.minecraft.world.item.h"
#include "net.minecraft.world.item.enchantment.h" #include "net.minecraft.world.item.enchantment.h"
#include "EnchantmentMenu.h" #include "EnchantmentMenu.h"
#include "../../../Minecraft.Client/ServerPlayer.h" #include "../Minecraft.Client/ServerPlayer.h"
#include "../../../Minecraft.Client/MinecraftServer.h" #include "../Minecraft.Client/MinecraftServer.h"
#include "../../../Minecraft.Client/PlayerList.h" #include "../Minecraft.Client/PlayerList.h"
#include "../../../Minecraft.Client/MultiPlayerLocalPlayer.h" #include "../Minecraft.Client/MultiPlayerLocalPlayer.h"
#include "../../../Minecraft.Client/PlayerConnection.h" #include "../Minecraft.Client/PlayerConnection.h"
#include "../../../Minecraft.World/CustomPayloadPacket.h" #include "../Minecraft.World/CustomPayloadPacket.h"
#include "../../../Minecraft.Client/Minecraft.h" #include "../Minecraft.Client/Minecraft.h"
EnchantmentMenu::EnchantmentMenu(shared_ptr<Inventory> inventory, Level *level, int xt, int yt, int zt) 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) 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) 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 // 4J Added
static void updatePossibleRecipes(shared_ptr<CraftingContainer> craftSlots, bool *firework, bool *charge, bool *fade); 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); 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); 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) 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::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::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::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::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); 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 "net.minecraft.world.level.saveddata.h"
#include "com.mojang.nbt.h" #include "com.mojang.nbt.h"
#include "ItemFrame.h" #include "ItemFrame.h"
#include "DamageSource.h"
#include "Level.h"
@ -87,29 +88,52 @@ shared_ptr<ItemInstance> ItemFrame::getItem()
return getEntityData()->getItemInstance(DATA_ITEM); return getEntityData()->getItemInstance(DATA_ITEM);
} }
void ItemFrame::setItem(shared_ptr<ItemInstance> item) void ItemFrame::setItem(shared_ptr<ItemInstance> item, bool notifyNeighbors)
{ {
if(item != nullptr) if (item != nullptr)
{ {
item = item->copy(); item = item->copy();
item->count = 1; 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() )); if (notifyNeighbors)
} {
getEntityData()->set(DATA_ITEM, item); level->updateNeighbourForOutputSignal(xTile, yTile, zTile, Tile::comparator_off->id);
getEntityData()->markDirty(DATA_ITEM); }
} }
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) void ItemFrame::addAdditonalSaveData(CompoundTag *tag)
{ {
if (getItem() != nullptr) if (getItem() != nullptr)
@ -171,3 +195,54 @@ bool ItemFrame::interact(shared_ptr<Player> player)
return true; 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: public:
shared_ptr<ItemInstance> getItem(); shared_ptr<ItemInstance> getItem();
void setItem(shared_ptr<ItemInstance> item, bool notifyNeighbors);
void setItem(shared_ptr<ItemInstance> item); void setItem(shared_ptr<ItemInstance> item);
int getRotation(); int getRotation();
void setRotation(int rotation, bool notifyNeighbors);
void setRotation(int rotation); 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 addAdditonalSaveData(CompoundTag *tag);
virtual void readAdditionalSaveData(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() int ItemInstance::getMaxDamage()
{ {
return Item::items[id]->getMaxDamage(); return Item::items[id]->getMaxDamage();

View file

@ -90,6 +90,7 @@ public:
int getDamageValue(); int getDamageValue();
int getAuxValue() const; int getAuxValue() const;
void setAuxValue(int value); void setAuxValue(int value);
void setRawAuxValue(int value);
int getMaxDamage(); int getMaxDamage();
bool hurt(int dmg, Random *random); bool hurt(int dmg, Random *random);
void hurtAndBreak(int dmg, shared_ptr<LivingEntity> owner); 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.commands.h"
#include "net.minecraft.world.entity.player.h" #include "net.minecraft.world.entity.player.h"
#include "net.minecraft.world.damagesource.h" #include "net.minecraft.world.damagesource.h"
#include "net.minecraft.world.level.h"
#include "BasicTypeContainers.h" #include "BasicTypeContainers.h"
#include "KillCommand.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() EGameCommand KillCommand::getId()
{ {
return eGameCommand_Kill; return eGameCommand_Kill;
} }
int KillCommand::getPermissionLevel() int KillCommand::getPermissionLevel()
{ {
return LEVEL_ALL; return LEVEL_ALL;
} }
void KillCommand::execute(shared_ptr<CommandSender> source, byteArray commandData) 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] = { const wstring LeafTile2::TEXTURES[2][2] = {
{ L"leaves_acacia", L"leaves_dark_oak" }, // Indice 0: Fancy { L"leaves_acacia", L"leaves_dark_oak" }, // index 0: Fancy
{ L"leaves_acacia_opaque", L"leaves_dark_oak_opaque" } // Indice 1: Veloce/Opaca { L"leaves_acacia_opaque", L"leaves_dark_oak_opaque" } // index 1: Fast
}; };
LeafTile2::LeafTile2(int id) : LeafTile(id) 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) Icon *LeafTile2::getTexture(int face, int data)
@ -29,8 +29,8 @@ Icon *LeafTile2::getTexture(int face, int data)
int type = data & 3; int type = data & 3;
if (type >= LEAF2_NAMES_SIZE) type = 0; if (type >= LEAF2_NAMES_SIZE) type = 0;
// isSolidRender() in LeafTile restituisce 'true' se la grafica è su Veloce/Opaca. // isSolidRender() in LeafTile returns 'true' if graphics is Fast
// Quindi se è true usiamo l'indice 1, se è false (Trasparente) usiamo l'indice 0. // if true -> index is 1, else 0.
int textureSet = isSolidRender(false) ? 1 : 0; int textureSet = isSolidRender(false) ? 1 : 0;
return icons[textureSet][type]; return icons[textureSet][type];
@ -56,13 +56,14 @@ void LeafTile2::registerIcons(IconRegister *iconRegister)
int LeafTile2::getColor(int data) 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(); return FoliageColor::getDefaultColor();
} }
int LeafTile2::getColor(LevelSource *level, int x, int y, int z, int data) 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 totalRed = 0;
int totalGreen = 0; int totalGreen = 0;
int totalBlue = 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++) 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; totalRed += (foliageColor & 0xff0000) >> 16;
totalGreen += (foliageColor & 0xff00) >> 8; totalGreen += (foliageColor & 0xff00) >> 8;
totalBlue += (foliageColor & 0xff); 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) 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) if (!level->isClientSide && player->getSelectedItem() != nullptr && player->getSelectedItem()->id == Item::shears->id)
{ {
player->awardStat( player->awardStat(
@ -95,7 +96,7 @@ void LeafTile2::playerDestroy(Level *level, shared_ptr<Player> player, int x, in
} }
else else
{ {
// Altrimenti usa la distruzione standard di TransparentTile // or default destroy
TransparentTile::playerDestroy(level, player, x, y, z, data); TransparentTile::playerDestroy(level, player, x, y, z, data);
} }
} }

View file

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

View file

@ -1,127 +1,110 @@
 #include "stdafx.h"
#include "stdafx.h"
#include "PacketListener.h" #include "PacketListener.h"
#include "LevelParticlesPacket.h" #include "LevelParticlesPacket.h"
#include "../Minecraft.Client/ParticleType.h"
LevelParticlesPacket::LevelParticlesPacket() LevelParticlesPacket::LevelParticlesPacket()
{ {
this->name = L"";
this->overrideLimiter = false; this->x = 0.0f;
this->type = nullptr; this->y = 0.0f;
this->count = 0; this->z = 0.0f;
this->y = 0.0f; this->xDist = 0.0f;
this->paramCount = 0; this->yDist = 0.0f;
this->x = 0.0f; this->zDist = 0.0f;
this->yDist = 0.0f; this->maxSpeed = 0.0f;
this->zDist = 0.0f; this->count = 0;
this->z = 0.0f;
this->maxSpeed = 0.0f;
this->xDist = 0.0f;
this->params = nullptr;
} }
LevelParticlesPacket::LevelParticlesPacket(const ParticleType* type, bool overrideLimiter, LevelParticlesPacket::LevelParticlesPacket(const wstring& name, float x, float y, float z, float xDist, float yDist, float zDist, float maxSpeed, int count)
float x, float y, float z,
float xDist, float yDist, float zDist,
float maxSpeed, int count,
arrayWithLength<int> data)
{ {
this->type = type; this->name = name;
this->overrideLimiter = overrideLimiter; this->x = x;
this->x = x; this->y = y;
this->y = y; this->z = z;
this->z = z; this->xDist = xDist;
this->xDist = xDist; this->yDist = yDist;
this->yDist = yDist; this->zDist = zDist;
this->zDist = zDist; this->maxSpeed = maxSpeed;
this->maxSpeed = maxSpeed; this->count = count;
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;
}
} }
void LevelParticlesPacket::read(DataInputStream* dis) void LevelParticlesPacket::read(DataInputStream* dis)
{ {
int particleId = dis->readInt(); name = readUtf(dis, 64);
const ParticleType* resolved = ParticleType::byId(particleId); x = dis->readFloat();
if (!resolved) y = dis->readFloat();
resolved = ParticleType::getDefault(); z = dis->readFloat();
this->type = resolved; xDist = dis->readFloat();
yDist = dis->readFloat();
this->overrideLimiter = dis->readBoolean(); zDist = dis->readFloat();
maxSpeed = dis->readFloat();
this->x = dis->readFloat(); count = dis->readInt();
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;
}
} }
void LevelParticlesPacket::write(DataOutputStream* dos) void LevelParticlesPacket::write(DataOutputStream* dos)
{ {
dos->writeInt(this->type ? this->type->getId() : 0); writeUtf(name, dos);
dos->writeBoolean(this->overrideLimiter); dos->writeFloat(x);
dos->writeFloat(this->x); dos->writeFloat(y);
dos->writeFloat(this->y); dos->writeFloat(z);
dos->writeFloat(this->z); dos->writeFloat(xDist);
dos->writeFloat(this->xDist); dos->writeFloat(yDist);
dos->writeFloat(this->yDist); dos->writeFloat(zDist);
dos->writeFloat(this->zDist); dos->writeFloat(maxSpeed);
dos->writeFloat(this->maxSpeed); dos->writeInt(count);
dos->writeInt(this->count); }
int toWrite = this->type ? this->type->getParamCount() : 0; wstring LevelParticlesPacket::getName()
for (int i = 0; i < toWrite; i++) {
{ return name;
dos->writeInt(this->params[i]); }
}
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) void LevelParticlesPacket::handle(PacketListener* listener)
{ {
listener->handleParticleEvent(shared_from_this()); listener->handleParticleEvent(shared_from_this());
} }
int LevelParticlesPacket::getEstimatedSize() int LevelParticlesPacket::getEstimatedSize()
{ {
return 0x40; return 4 * 2 + 7 * 8;
} }

View file

@ -1,53 +1,39 @@
#pragma once #pragma once
#include "Packet.h" #include "Packet.h"
#include "../Minecraft.Client/ParticleType.h"
class LevelParticlesPacket : public Packet, public enable_shared_from_this<LevelParticlesPacket> class LevelParticlesPacket : public Packet, public enable_shared_from_this<LevelParticlesPacket>
{ {
private: private:
wstring name;
const ParticleType* type; float x;
float x; float y;
float y; float z;
float z; float xDist;
float xDist; float yDist;
float yDist; float zDist;
float zDist; float maxSpeed;
float maxSpeed; int count;
int count;
bool overrideLimiter;
int* params;
int paramCount;
public: public:
LevelParticlesPacket(); LevelParticlesPacket();
LevelParticlesPacket(const ParticleType* type, bool overrideLimiter, LevelParticlesPacket(const wstring& name, float x, float y, float z, float xDist, float yDist, float zDist, float maxSpeed, int count);
float x, float y, float z,
float xDist, float yDist, float zDist,
float maxSpeed, int count,
arrayWithLength<int> data);
~LevelParticlesPacket();
void read(DataInputStream* dis) override; void read(DataInputStream* dis);
void write(DataOutputStream* dos) override; 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; } public:
double getX() { return x; } static shared_ptr<Packet> create() { return std::make_shared<LevelParticlesPacket>(); }
double getY() { return y; } virtual int getId() { return 63; }
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; }
}; };

View file

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

View file

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

View file

@ -7,9 +7,9 @@ class MobCategory
{ {
public: public:
// 4J - putting constants for xbox spawning in one place to tidy things up a bit - all numbers are per level // 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_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 = 50; // Max number of animals (cows, sheep, pigs) 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 = 20; // Ambient mobs 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_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 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) 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 // 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; 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 // 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) 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) else if (id == wither->id)

View file

@ -30,7 +30,7 @@ MoveEntityPacket::MoveEntityPacket(int id)
void MoveEntityPacket::read(DataInputStream *dis) //throws IOException void MoveEntityPacket::read(DataInputStream *dis) //throws IOException
{ {
id = dis->readShort(); id = dis->readInt();
} }
void MoveEntityPacket::write(DataOutputStream *dos) //throws IOException 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 // We shouln't be tracking an entity that doesn't have a short type of id
DEBUG_BREAK(); DEBUG_BREAK();
} }
dos->writeShort(static_cast<short>(id)); dos->writeInt(static_cast<short>(id));
} }
void MoveEntityPacket::handle(PacketListener *listener) void MoveEntityPacket::handle(PacketListener *listener)
@ -50,7 +50,7 @@ void MoveEntityPacket::handle(PacketListener *listener)
int MoveEntityPacket::getEstimatedSize() int MoveEntityPacket::getEstimatedSize()
{ {
return 2; return 4;
} }
bool MoveEntityPacket::canBeInvalidated() bool MoveEntityPacket::canBeInvalidated()
@ -101,7 +101,7 @@ void MoveEntityPacket::PosRot::write(DataOutputStream *dos) //throws IOException
int MoveEntityPacket::PosRot::getEstimatedSize() int MoveEntityPacket::PosRot::getEstimatedSize()
{ {
return 2+5; return 4+5;
} }
MoveEntityPacket::Pos::Pos() MoveEntityPacket::Pos::Pos()
@ -133,7 +133,7 @@ void MoveEntityPacket::Pos::write(DataOutputStream *dos) //throws IOException
int MoveEntityPacket::Pos::getEstimatedSize() int MoveEntityPacket::Pos::getEstimatedSize()
{ {
return 2+3; return 4+3;
} }
MoveEntityPacket::Rot::Rot() MoveEntityPacket::Rot::Rot()
@ -164,5 +164,5 @@ void MoveEntityPacket::Rot::write(DataOutputStream *dos) //throws IOException
int MoveEntityPacket::Rot::getEstimatedSize() 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 void MoveEntityPacketSmall::read(DataInputStream *dis) //throws IOException
{ {
id = dis->readShort(); id = dis->readInt();
} }
void MoveEntityPacketSmall::write(DataOutputStream *dos) //throws IOException 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 // We shouln't be tracking an entity that doesn't have a short type of id
DEBUG_BREAK(); DEBUG_BREAK();
} }
dos->writeShort(static_cast<short>(id)); dos->writeInt(id);
} }
void MoveEntityPacketSmall::handle(PacketListener *listener) void MoveEntityPacketSmall::handle(PacketListener *listener)
@ -57,7 +57,7 @@ void MoveEntityPacketSmall::handle(PacketListener *listener)
int MoveEntityPacketSmall::getEstimatedSize() int MoveEntityPacketSmall::getEstimatedSize()
{ {
return 2; return 4;
} }
bool MoveEntityPacketSmall::canBeInvalidated() 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 void MoveEntityPacketSmall::PosRot::read(DataInputStream *dis) //throws IOException
{ {
int idAndRot = dis->readShort(); this->id = dis->readInt();
this->id = idAndRot & 0x07ff; this->yRot = dis->readChar();
this->yRot = idAndRot >> 11; int XandYandZ = (int)dis->readShort();
int xAndYAndZ = (int)dis->readShort(); this->xa = XandYandZ >> 11;
this->xa = xAndYAndZ >> 11; this->ya = (XandYandZ << 21 ) >> 26;
this->ya = (xAndYAndZ << 21 ) >> 26; this->za = (XandYandZ << 27 ) >> 27;
this->za = (xAndYAndZ << 27 ) >> 27;
} }
void MoveEntityPacketSmall::PosRot::write(DataOutputStream *dos) //throws IOException 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 // We shouln't be tracking an entity that doesn't have a short type of id
DEBUG_BREAK(); DEBUG_BREAK();
} }
short idAndRot = id | yRot << 11; dos->writeInt(id);
dos->writeShort(idAndRot); dos->writeChar(yRot);
short xAndYAndZ = ( xa << 11 ) | ( ( ya & 0x3f ) << 5 ) | ( za & 0x1f ); short XandYandZ = ( xa << 11 ) | ( ( ya & 0x3f ) << 5 ) | ( za & 0x1f );
dos->writeShort(xAndYAndZ); dos->writeShort(XandYandZ);
} }
int MoveEntityPacketSmall::PosRot::getEstimatedSize() int MoveEntityPacketSmall::PosRot::getEstimatedSize()
{ {
return 4; return 7;
} }
MoveEntityPacketSmall::Pos::Pos() 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 void MoveEntityPacketSmall::Pos::read(DataInputStream *dis) //throws IOException
{ {
int idAndY = dis->readShort(); this->id = dis->readInt();
this->id = idAndY & 0x07ff; this->ya = dis->readChar();
this->ya = idAndY >> 11;
int XandZ = (int)static_cast<signed char>(dis->readByte()); int XandZ = (int)static_cast<signed char>(dis->readByte());
xa = XandZ >> 4; xa = XandZ >> 4;
za = ( XandZ << 28 ) >> 28; 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 // We shouln't be tracking an entity that doesn't have a short type of id
DEBUG_BREAK(); DEBUG_BREAK();
} }
short idAndY = id | ya << 11; dos->writeInt(id);
dos->writeShort(idAndY); dos->writeChar(ya);
char XandZ = ( xa << 4 ) | ( za & 0x0f ); char XandZ = ( xa << 4 ) | ( za & 0x0f );
dos->writeByte(XandZ); dos->writeByte(XandZ);
} }
int MoveEntityPacketSmall::Pos::getEstimatedSize() int MoveEntityPacketSmall::Pos::getEstimatedSize()
{ {
return 3; return 7;
} }
MoveEntityPacketSmall::Rot::Rot() 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 void MoveEntityPacketSmall::Rot::read(DataInputStream *dis) //throws IOException
{ {
int idAndRot = (int)dis->readShort(); this->id = dis->readInt();
this->id = idAndRot & 0x07ff; this->yRot = dis->readChar();
this->yRot = idAndRot >> 11;
} }
void MoveEntityPacketSmall::Rot::write(DataOutputStream *dos) //throws IOException 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 // We shouln't be tracking an entity that doesn't have a short type of id
DEBUG_BREAK(); DEBUG_BREAK();
} }
short idAndRot = id | yRot << 11; dos->writeInt(id);
dos->writeShort(idAndRot); dos->writeChar(yRot);
} }
int MoveEntityPacketSmall::Rot::getEstimatedSize() int MoveEntityPacketSmall::Rot::getEstimatedSize()
{ {
return 2; return 5;
} }

View file

@ -35,13 +35,16 @@ Ocelot::Ocelot(Level *level) : TamableAnimal(level)
registerAttributes(); registerAttributes();
setHealth(getMaxHealth()); setHealth(getMaxHealth());
avoidPlayerGoal = nullptr;
reassessTameGoals();
setSize(0.6f, 0.8f); setSize(0.6f, 0.8f);
getNavigation()->setAvoidWater(true); getNavigation()->setAvoidWater(true);
goalSelector.addGoal(1, new FloatGoal(this)); goalSelector.addGoal(1, new FloatGoal(this));
goalSelector.addGoal(2, sitGoal, false); goalSelector.addGoal(2, sitGoal, false);
goalSelector.addGoal(3, temptGoal = new TemptGoal(this, SNEAK_SPEED_MOD, Item::fish_raw_Id, true), 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(5, new FollowOwnerGoal(this, FOLLOW_SPEED_MOD, 10, 5));
goalSelector.addGoal(6, new OcelotSitOnTileGoal(this, SPRINT_SPEED_MOD)); goalSelector.addGoal(6, new OcelotSitOnTileGoal(this, SPRINT_SPEED_MOD));
goalSelector.addGoal(7, new LeapAtTargetGoal(this, 0.3f)); goalSelector.addGoal(7, new LeapAtTargetGoal(this, 0.3f));
@ -60,6 +63,21 @@ void Ocelot::defineSynchedData()
entityData->define(DATA_TYPE_ID, static_cast<byte>(0)); 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() void Ocelot::serverAiMobStep()
{ {
if (getMoveControl()->hasWanted()) if (getMoveControl()->hasWanted())
@ -199,7 +217,10 @@ bool Ocelot::mobInteract(shared_ptr<Player> player)
} }
else 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 // 4J-PB - don't lose the fish in creative mode
if (!player->abilities.instabuild) item->count--; if (!player->abilities.instabuild) item->count--;
@ -284,6 +305,8 @@ void Ocelot::setCatType(int type)
bool Ocelot::canSpawn() bool Ocelot::canSpawn()
{ {
//return level->random->nextInt(3) != 0; when checkSpawnObstruction is implemented
// artificially make ozelots more rare // artificially make ozelots more rare
if (level->random->nextInt(3) == 0) if (level->random->nextInt(3) == 0)
{ {

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "TamableAnimal.h" #include "TamableAnimal.h"
#include "AvoidPlayerGoal.h"
class TemptGoal; class TemptGoal;
@ -32,6 +33,7 @@ public:
private: private:
TemptGoal *temptGoal; TemptGoal *temptGoal;
AvoidPlayerGoal *avoidPlayerGoal;
public: public:
Ocelot(Level *level); Ocelot(Level *level);
@ -41,6 +43,8 @@ protected:
public: public:
virtual void serverAiMobStep(); virtual void serverAiMobStep();
virtual void reassessTameGoals();
virtual void setTame(bool tame);
protected: protected:
virtual bool removeWhenFarAway(); virtual bool removeWhenFarAway();
@ -78,6 +82,7 @@ public:
virtual int getCatType(); virtual int getCatType();
virtual void setCatType(int type); virtual void setCatType(int type);
virtual bool canSpawn(); virtual bool canSpawn();
//virtual bool checkSpawnObstruction(); TODO when blockstates will be merged.
virtual wstring getAName(); virtual wstring getAName();
virtual MobGroupData *finalizeMobSpawn(MobGroupData *groupData, int extraData = 0); // 4J Added extraData param 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 shared_ptr<ItemInstance> readItem(DataInputStream *dis);
static void writeItem(shared_ptr<ItemInstance> item, DataOutputStream *dos); static void writeItem(shared_ptr<ItemInstance> item, DataOutputStream *dos);
static CompoundTag *readNbt(DataInputStream *dis); static CompoundTag *readNbt(DataInputStream *dis);
protected:
static void writeNbt(CompoundTag *tag, DataOutputStream *dos); 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 // 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. // piston in a bad (simultaneously extended & not extended) state.
// 4J - ignoreUpdate is a static in java, implementing as TLS here to make thread safe // 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) //I removed the code for ignoreUpdate so the above comment no longer applies ^.^
{
TlsSetValue(tlsIdx,(LPVOID)(set?1:0));
}
PistonBaseTile::PistonBaseTile(int id, bool isSticky) : Tile(id, Material::piston, isSolidRender() ) PistonBaseTile::PistonBaseTile(int id, bool isSticky) : Tile(id, Material::piston, isSolidRender() )
{ {
// 4J - added initialiser // 4J - added initialiser
ignoreUpdate(false);
this->isSticky = isSticky; this->isSticky = isSticky;
setSoundType(SOUND_STONE); setSoundType(SOUND_STONE);
setDestroyTime(0.5f); 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) ); int targetData = getNewFacing(level, x, y, z, dynamic_pointer_cast<Player>(by) );
level->setData(x, y, z, targetData, Tile::UPDATE_CLIENTS); level->setData(x, y, z, targetData, Tile::UPDATE_CLIENTS);
if (!level->isClientSide && !ignoreUpdate()) if (!level->isClientSide)
{ {
checkIfExtend(level, x, y, z); 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) 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); 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) 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); 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) bool PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1, int facing)
{ {
ignoreUpdate(true);
if (!level->isClientSide) 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) if (extend && param1 == TRIGGER_CONTRACT)
{ {
level->setData(x, y, z, facing | EXTENDED_BIT, UPDATE_CLIENTS); level->setData(x, y, z, facing | EXTENDED_BIT, UPDATE_CLIENTS);
ignoreUpdate(false);
return false; return false;
} }
else if (!extend && param1 == TRIGGER_EXTEND) else if (!extend && param1 == TRIGGER_EXTEND)
{ {
ignoreUpdate(false);
return 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)) if (FourKitBridge::FirePistonExtend(level->dimension->id, x, y, z, facing, pushLength))
{ {
ignoreUpdate(false);
return false; return false;
} }
} }
@ -277,7 +264,6 @@ bool PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1,
} }
else else
{ {
ignoreUpdate(false);
return false; return false;
} }
PIXEndNamedEvent(); 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)) if (FourKitBridge::FirePistonRetract(level->dimension->id, x, y, z, facing))
{ {
level->setData(x, y, z, facing | EXTENDED_BIT, UPDATE_CLIENTS); level->setData(x, y, z, facing | EXTENDED_BIT, UPDATE_CLIENTS);
ignoreUpdate(false);
return false; return false;
} }
#endif #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->setTileAndData(x, y, z, Tile::pistonMovingPiece_Id, blockData, Tile::UPDATE_ALL);
level->setTileEntity(x, y, z, PistonMovingPiece::newMovingPieceEntity(block, blockData, facing, false, false)); level->setTileEntity(x, y, z, PistonMovingPiece::newMovingPieceEntity(block, blockData, facing, false, false));
ignoreUpdate(false);
level->removeTile(twoX, twoY, twoZ); level->removeTile(twoX, twoY, twoZ);
ignoreUpdate(true);
} }
else if (!pistonPiece) else if (!pistonPiece)
{ {
stopSharingIfServer(level, x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]); // 4J added 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]); level->removeTile(x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]);
ignoreUpdate(true);
} }
PIXEndNamedEvent(); PIXEndNamedEvent();
} }
else else
{ {
stopSharingIfServer(level, x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]); // 4J added 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]); 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); 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; return true;
} }

View file

@ -27,8 +27,7 @@ private:
static DWORD tlsIdx; static DWORD tlsIdx;
// 4J - was just a static but implemented with TLS for our version // 4J - was just a static but implemented with TLS for our version
static bool ignoreUpdate(); //code removed so the above comment no longer applies
static void ignoreUpdate(bool set);
public: public:
PistonBaseTile(int id, bool isSticky); PistonBaseTile(int id, bool isSticky);
@ -68,4 +67,4 @@ private:
static void stopSharingIfServer(Level *level, int x, int y, int z); // 4J added 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); 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(); // 4J Jev: instance = new Recipes();
recipies = new RecipyList(); recipies = new RecipyList();
}
Recipes::Recipes() pArmorRecipes = new ArmorRecipes;
{ pClothDyeRecipes = new ClothDyeRecipes;
int iCount=0; pFoodRecipies = new FoodRecipies;
_init(); pOreRecipies = new OreRecipies;
pStructureRecipies = new StructureRecipies;
pArmorRecipes = new ArmorRecipes; pToolRecipies = new ToolRecipies;
pClothDyeRecipes = new ClothDyeRecipes; pWeaponRecipies = new WeaponRecipies;
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 // 4J Stu - These just don't work with our crafting menu
//recipies->push_back(new ArmorDyeRecipe()); //recipies->push_back(new ArmorDyeRecipe());
@ -50,8 +44,10 @@ Recipes::Recipes()
//recipies->add(new MapExtendingRecipe()); //recipies->add(new MapExtendingRecipe());
//recipies->add(new FireworksRecipe()); //recipies->add(new FireworksRecipe());
pFireworksRecipes = new FireworksRecipe(); pFireworksRecipes = new FireworksRecipe();
}
void Recipes::_compileRecipes()
{
addShapedRecipy(new ItemInstance(Tile::wood, 4, 0), // addShapedRecipy(new ItemInstance(Tile::wood, 4, 0), //
L"sczg", L"sczg",
L"#", // L"#", //
@ -186,7 +182,7 @@ Recipes::Recipes()
L"W#W", // L"W#W", //
L"W#W", // L"W#W", //
L'#', Item::stick, L'#', Item::stick,
L'W', new ItemInstance(Tile::wood, 1, TreeTile::ACACIA_TRUNK), L'W', new ItemInstance(Tile::wood, 1, TreeTile::ACACIA_TRUNK),
L'S'); L'S');
@ -195,7 +191,7 @@ Recipes::Recipes()
L"W#W", // L"W#W", //
L"W#W", // L"W#W", //
L'#', Item::stick, L'#', Item::stick,
L'W', new ItemInstance(Tile::wood, 1, TreeTile::DARK_TRUNK), L'W', new ItemInstance(Tile::wood, 1, TreeTile::DARK_TRUNK),
L'S'); L'S');
@ -475,12 +471,10 @@ Recipes::Recipes()
L'S'); L'S');
pArmorRecipes->addRecipes(this); pArmorRecipes->addRecipes(this);
//iCount=getRecipies()->size();
pClothDyeRecipes->addRecipes(this); pClothDyeRecipes->addRecipes(this);
addShapedRecipy(new ItemInstance(Tile::snow, 1), // addShapedRecipy(new ItemInstance(Tile::snow, 1), //
L"sscig", L"sscig",
L"##", // L"##", //
@ -497,7 +491,7 @@ Recipes::Recipes()
L'#', Item::prismarine_shard, L'#', Item::prismarine_shard,
L'S'); L'S');
addShapedRecipy(new ItemInstance(Tile::prismarine, 1,PrismarineTile::TYPE_BRICKS), // addShapedRecipy(new ItemInstance(Tile::prismarine, 1, PrismarineTile::TYPE_BRICKS), //
L"ssscig", L"ssscig",
L"###", // L"###", //
L"###", // L"###", //
@ -507,7 +501,7 @@ Recipes::Recipes()
L'S'); L'S');
addShapedRecipy(new ItemInstance(Tile::prismarine, 1,PrismarineTile::TYPE_DARK), // addShapedRecipy(new ItemInstance(Tile::prismarine, 1, PrismarineTile::TYPE_DARK), //
L"ssscicig", L"ssscicig",
L"###", // L"###", //
L"#X#", // L"#X#", //
@ -657,10 +651,6 @@ Recipes::Recipes()
//iCount=getRecipies()->size();
addShapedRecipy(new ItemInstance(Item::cake, 1), // addShapedRecipy(new ItemInstance(Item::cake, 1), //
L"ssscicicicig", L"ssscicicicig",
L"AAA", // L"AAA", //
@ -770,7 +760,7 @@ Recipes::Recipes()
L'#', Tile::wood, L'#', Tile::wood,
L'V'); L'V');
addShapedRecipy(new ItemInstance((Item *)Item::fishingRod, 1), // addShapedRecipy(new ItemInstance((Item*)Item::fishingRod, 1), //
L"ssscicig", L"ssscicig",
L" #", // L" #", //
L" #X", // L" #X", //
@ -803,7 +793,7 @@ Recipes::Recipes()
L'F'); L'F');
// Moved bow and arrow in from weapons to avoid stacking on the group name display // 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"ssscicig",
L" #X", // L" #X", //
L"# X", // L"# X", //
@ -850,7 +840,7 @@ Recipes::Recipes()
L'#', Tile::glass, L'#', Tile::glass,
L'T'); L'T');
// torch made of charcoal - moved to be the default due to the tutorial using it // torch made of charcoal - moved to be the default due to the tutorial using it
addShapedRecipy(new ItemInstance(Tile::torch, 4), // addShapedRecipy(new ItemInstance(Tile::torch, 4), //
@ -961,12 +951,12 @@ Recipes::Recipes()
addShapelessRecipy(new ItemInstance(Item::fireball, 3), // addShapelessRecipy(new ItemInstance(Item::fireball, 3), //
L"iiig", L"iiig",
Item::gunpowder, Item::blazePowder,Item::coal, Item::gunpowder, Item::blazePowder, Item::coal,
L'T'); L'T');
addShapelessRecipy(new ItemInstance(Item::fireball, 3), // addShapelessRecipy(new ItemInstance(Item::fireball, 3), //
L"iizg", 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'); L'T');
addShapedRecipy(new ItemInstance(Item::lead, 2), // addShapedRecipy(new ItemInstance(Item::lead, 2), //
@ -1096,24 +1086,24 @@ Recipes::Recipes()
L'#', Tile::wood, L'X', Item::diamond, L'#', Tile::wood, L'X', Item::diamond,
'D'); 'D');
addShapedRecipy(new ItemInstance(Item::leather, 1),
L"sscig",
L"##",
L"##",
L'#', Item::rabbit_hide, addShapedRecipy(new ItemInstance(Item::leather, 1),
L'D'); L"sscig",
L"##",
L"##",
L'#', Item::rabbit_hide,
L'D');
addShapedRecipy(new ItemInstance(Item::armor_stand, 1), addShapedRecipy(new ItemInstance(Item::armor_stand, 1),
L"ssscictg", L"ssscictg",
L"SSS", L"SSS",
L" S ", L" S ",
L"SXS", L"SXS",
L'S', Item::stick, L'S', Item::stick,
L'X', Tile::stoneSlabHalf, L'X', Tile::stoneSlabHalf,
L'D'); L'D');
addShapedRecipy(new ItemInstance(Item::paper, 3), // addShapedRecipy(new ItemInstance(Item::paper, 3), //
@ -1206,21 +1196,21 @@ Recipes::Recipes()
L'D'); L'D');
// 4J - TODO - put these new 1.7.3 items in required place within recipes // 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"sssctcicictg",
L"TTT", // L"TTT", //
L"#X#", // L"#X#", //
L"#R#", // 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'); L'M');
addShapedRecipy(new ItemInstance(static_cast<Tile *>(Tile::pistonStickyBase), 1), // addShapedRecipy(new ItemInstance(static_cast<Tile*>(Tile::pistonStickyBase), 1), //
L"sscictg", L"sscictg",
L"S", // L"S", //
L"P", // L"P", //
L'S', Item::slimeBall, L'P', Tile::pistonBase, L'S', Item::slimeBall, L'P', Tile::pistonBase,
L'M'); L'M');
@ -1233,7 +1223,7 @@ Recipes::Recipes()
L'P', Item::paper, L'G', Item::gunpowder, L'P', Item::paper, L'G', Item::gunpowder,
L'D'); L'D');
addShapedRecipy(new ItemInstance(Item::fireworksCharge,1), // addShapedRecipy(new ItemInstance(Item::fireworksCharge, 1), //
L"sscicig", L"sscicig",
L" D ", // L" D ", //
L" G ", // L" G ", //
@ -1241,7 +1231,7 @@ Recipes::Recipes()
L'D', Item::dye_powder, L'G', Item::gunpowder, L'D', Item::dye_powder, L'G', Item::gunpowder,
L'D'); L'D');
addShapedRecipy(new ItemInstance(Item::fireworksCharge,1), // addShapedRecipy(new ItemInstance(Item::fireworksCharge, 1), //
L"sscicig", L"sscicig",
L" D ", // L" D ", //
L" C ", // L" C ", //
@ -1249,37 +1239,38 @@ Recipes::Recipes()
L'D', Item::dye_powder, L'C', Item::fireworksCharge, L'D', Item::dye_powder, L'C', Item::fireworksCharge,
L'D'); 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(); 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 // 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, ...) ShapedRecipy *Recipes::addShapedRecipy(ItemInstance *result, ...)
{ {
@ -1563,7 +1554,7 @@ void Recipes::buildRecipeIngredientsArray(void)
int iRecipeC=static_cast<int>(recipies->size()); int iRecipeC=static_cast<int>(recipies->size());
m_pRecipeIngredientsRequired= new Recipy::INGREDIENTS_REQUIRED [iRecipeC]; m_pRecipeIngredientsRequired = new Recipy::INGREDIENTS_REQUIRED [iRecipeC];
int iCount=0; int iCount=0;
for (auto& recipe : *recipies) for (auto& recipe : *recipies)
@ -1577,4 +1568,46 @@ void Recipes::buildRecipeIngredientsArray(void)
Recipy::INGREDIENTS_REQUIRED *Recipes::getRecipeIngredientsArray(void) Recipy::INGREDIENTS_REQUIRED *Recipes::getRecipeIngredientsArray(void)
{ {
return m_pRecipeIngredientsRequired; 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 "Recipy.h"
#include "../Minecraft.World/CustomPayloadPacket.h"
#pragma once #pragma once
using namespace std; using namespace std;
@ -84,6 +85,8 @@ public:
private: private:
void _init(); // 4J add void _init(); // 4J add
void _compileRecipes();
void _wipeRecipes();
Recipes(); Recipes();
public: public:
@ -97,6 +100,11 @@ public:
shared_ptr<ItemInstance> getItemForRecipe(Recipy *r); shared_ptr<ItemInstance> getItemForRecipe(Recipy *r);
Recipy::INGREDIENTS_REQUIRED *getRecipeIngredientsArray(); Recipy::INGREDIENTS_REQUIRED *getRecipeIngredientsArray();
void loadFromLocal();
void loadFromPacket(byteArray packetData);
std::shared_ptr<CustomPayloadPacket> createUpdatePacket();
private: private:
void buildRecipeIngredientsArray(); void buildRecipeIngredientsArray();
Recipy::INGREDIENTS_REQUIRED *m_pRecipeIngredientsRequired; Recipy::INGREDIENTS_REQUIRED *m_pRecipeIngredientsRequired;

View file

@ -10,13 +10,13 @@
#define RECIPE_TYPE_2x2 0 #define RECIPE_TYPE_2x2 0
#define RECIPE_TYPE_3x3 1 #define RECIPE_TYPE_3x3 1
class Recipy class Recipy
{ {
public: public:
enum _eGroupType enum _eGroupType
{ {
eGroupType_First=0, eGroupType_First = 0,
eGroupType_Structure=0, eGroupType_Structure = 0,
eGroupType_Tool, eGroupType_Tool,
eGroupType_Food, eGroupType_Food,
eGroupType_Armour, eGroupType_Armour,
@ -28,28 +28,30 @@ public:
eGroupType; // to class the item produced by the recipe 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 // 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 iIngC;
int iType; // Can be a 2x2 or a 3x3. Inventory crafting can only make a 2x2. int iType; // Can be a 2x2 or a 3x3. Inventory crafting can only make a 2x2.
int *iIngIDA; int* iIngIDA;
int *iIngValA; int* iIngValA;
int *iIngAuxValA; int* iIngAuxValA;
Recipy *pRecipy; Recipy* pRecipy;
bool bCanMake[XUSER_MAX_COUNT]; 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 unsigned short usBitmaskMissingGridIngredients[XUSER_MAX_COUNT]; // each bit set means we don't have that grid ingredient
} }
INGREDIENTS_REQUIRED; INGREDIENTS_REQUIRED;
~Recipy() {} virtual ~Recipy() = default;
virtual bool matches(shared_ptr<CraftingContainer> craftSlots, Level *level) = 0; virtual bool matches(shared_ptr<CraftingContainer> craftSlots, Level* level) = 0;
virtual shared_ptr<ItemInstance> assemble(shared_ptr<CraftingContainer> craftSlots) = 0; virtual shared_ptr<ItemInstance> assemble(shared_ptr<CraftingContainer> craftSlots) = 0;
virtual int size() = 0; virtual int size() = 0;
virtual const ItemInstance *getResultItem() = 0; virtual const ItemInstance* getResultItem() = 0;
virtual const int getGroup() = 0; virtual const int getGroup() = 0;
// 4J-PB // 4J-PB
virtual bool reqs(int iRecipe) = 0; 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(); mapSeed = dis->readLong();
difficulty = dis->readByte(); difficulty = dis->readByte();
m_newSeaLevel = dis->readBoolean(); m_newSeaLevel = dis->readBoolean();
m_newEntityId = dis->readShort(); m_newEntityId = dis->readInt();
#ifdef _LARGE_WORLDS #ifdef _LARGE_WORLDS
m_xzSize = dis->readShort(); m_xzSize = dis->readShort();
m_hellScale = dis->read(); m_hellScale = dis->read();
@ -83,7 +83,7 @@ void RespawnPacket::write(DataOutputStream *dos) //throws IOException
dos->writeLong(mapSeed); dos->writeLong(mapSeed);
dos->writeByte(difficulty); dos->writeByte(difficulty);
dos->writeBoolean(m_newSeaLevel); dos->writeBoolean(m_newSeaLevel);
dos->writeShort(m_newEntityId); dos->writeInt(m_newEntityId);
#ifdef _LARGE_WORLDS #ifdef _LARGE_WORLDS
dos->writeShort(m_xzSize); dos->writeShort(m_xzSize);
dos->write(m_hellScale); dos->write(m_hellScale);
@ -97,5 +97,5 @@ int RespawnPacket::getEstimatedSize()
{ {
length = static_cast<int>(m_pLevelType->getGeneratorName().length()); 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 void SetEntityMotionPacket::read(DataInputStream *dis) //throws IOException
{ {
short idAndFlag = dis->readShort(); useBytes = dis->readBoolean();
id = idAndFlag & 0x07ff; id = dis->readInt();
if( idAndFlag & 0x0800 ) if(useBytes)
{ {
xa = static_cast<int>(dis->readByte()); xa = static_cast<int>(dis->readByte());
ya = static_cast<int>(dis->readByte()); ya = static_cast<int>(dis->readByte());
@ -62,29 +62,28 @@ void SetEntityMotionPacket::read(DataInputStream *dis) //throws IOException
xa *= 16; xa *= 16;
ya *= 16; ya *= 16;
za *= 16; za *= 16;
useBytes = true;
} }
else else
{ {
xa = dis->readShort(); xa = dis->readShort();
ya = dis->readShort(); ya = dis->readShort();
za = dis->readShort(); za = dis->readShort();
useBytes = false;
} }
} }
void SetEntityMotionPacket::write(DataOutputStream *dos) //throws IOException void SetEntityMotionPacket::write(DataOutputStream *dos) //throws IOException
{ {
dos->writeBoolean(useBytes);
if( useBytes ) if( useBytes )
{ {
dos->writeShort(id | 0x800); dos->writeInt(id);
dos->writeByte(xa/16); dos->writeByte(xa/16);
dos->writeByte(ya/16); dos->writeByte(ya/16);
dos->writeByte(za/16); dos->writeByte(za/16);
} }
else else
{ {
dos->writeShort(id); dos->writeInt(id);
dos->writeShort(xa); dos->writeShort(xa);
dos->writeShort(ya); dos->writeShort(ya);
dos->writeShort(za); dos->writeShort(za);
@ -98,7 +97,7 @@ void SetEntityMotionPacket::handle(PacketListener *listener)
int SetEntityMotionPacket::getEstimatedSize() int SetEntityMotionPacket::getEstimatedSize()
{ {
return useBytes ? 5 : 8; return useBytes ? 8 : 11;
} }
bool SetEntityMotionPacket::canBeInvalidated() bool SetEntityMotionPacket::canBeInvalidated()

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