Compare commits

...

132 commits
Stable ... main

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
pieeebot 60189f6ab6 chore: build v1.0.2 2026-05-13 13:41:16 +03:00
pieeebot 55ce17bc76 chore(TU31): change XXX Wood to XXX Planks for accuracy. 2026-05-12 17:58:36 +03:00
pieeebot 9932f765cd chore(TU31): update stringsGeneric.xml to use XXX Planks instead of XXX Wood Planks 2026-05-12 17:38:57 +03:00
pieeebot 7a02a28874 Merge branch 'main' of https://github.com/neoStudiosLCE/neoLegacy 2026-05-12 17:35:56 +03:00
pieeebot d6c1ef7ab9 fix: crash when switching gamemodes using /gamemode 2026-05-12 17:35:52 +03:00
/home/neo 3902b814c3
ci: trigger 2026-05-12 15:15:10 +03:00
rockefort 7fb07ec8d4
feat(TU31): LoadCreateJoin improvements (#65)
Feat: JoinMenu have description (for now isn't working because i'm waiting for the fourkit code rewriting)
2026-05-12 14:23:36 +03:00
piebot 7850eff035 chore(TU31): Update skinHDWin.swf to be more accurate.
most noticeable change is the credits background.
2026-05-09 14:39:57 +03:00
/home/neo 8cab7f8048
chore: trigger ci 2026-05-05 19:55:56 +03:00
piebot 3ed6e32d76
chore: delete misplaced roadmap [no ci] 2026-05-05 19:36:16 +03:00
piebot a634ef4d59
chore: update progress [no ci] 2026-05-05 19:35:53 +03:00
piebot 2ff9a3d6ed
chore: update roadmap [no ci] 2026-05-05 19:35:10 +03:00
/home/neo 12bacaf31f
bump 2026-05-04 20:51:08 +03:00
/home/neo 9099593837
fix 2026-05-04 20:50:55 +03:00
/home/neo 81de00ab25
docs: NOTES.md 2026-05-04 20:50:19 +03:00
/home/neo 8f76cbb70d
docs: NOTES.md 2026-05-04 20:48:18 +03:00
/home/neo a1921a871f
ci: release notes support 2026-05-04 20:43:47 +03:00
/home/neo 69fdfafe31
Merge experimental into main 2026-05-04 15:15:03 +03:00
github-actions 3adf82e578 Merge remote-tracking branch 'origin/main' into experimental 2026-05-03 18:23:26 +00:00
/home/neo 0c944cb713
template: fix 2026-05-03 21:22:31 +03:00
/home/neo bef1a91903
fix bug report template 2026-05-03 21:21:54 +03:00
github-actions f2027b0108 Merge remote-tracking branch 'origin/main' into experimental 2026-05-03 18:21:49 +00:00
/home/neo 58d005fb02
templates: better bug report template 2026-05-03 21:20:37 +03:00
DrPerkyLegit 118894b805 forgot these files 2026-05-03 20:52:27 +03:00
DrPerkyLegit f7e0f8f381 remove creation of DX11 renderer 2026-05-03 20:52:26 +03:00
github-actions 572fbcb0b6 Merge remote-tracking branch 'origin/main' into experimental 2026-05-03 16:58:37 +00:00
/home/neo d2810bfee3
ci: fix server title 2026-05-03 19:57:16 +03:00
github-actions dcc7a33859 Merge remote-tracking branch 'origin/main' into experimental 2026-05-03 16:15:17 +00:00
/home/neo 6a8f28b645
bump 2026-05-03 19:13:58 +03:00
github-actions 73757cbf8b Merge remote-tracking branch 'origin/main' into experimental 2026-05-03 16:02:26 +00:00
/home/neo 052bb11bcd
ci: add "prerelease" to nightly 2026-05-03 19:01:08 +03:00
github-actions 1ef400c404 Merge remote-tracking branch 'origin/main' into experimental 2026-05-03 16:01:00 +00:00
/home/neo 32eb37a5e8
ci: versioning 2026-05-03 18:59:45 +03:00
github-actions 6ebbdc59f9 Merge remote-tracking branch 'origin/main' into experimental 2026-05-03 15:01:11 +00:00
neoapps-dev 89a64882ef fix(PlayerConnection): /tp fix
fix(PlayerConnection): pointer

fix(PlayerConnection): bytearray

fix(PlayerConnection): bytearray

fix(PlayerConnection): bytearray

fix(TeleportCommand): crash on coords

fix(TeleportCommand): crash on coords

fix: sunflower randomly spawning
2026-05-03 17:59:26 +03:00
neoapps-dev 083ccbd4e9 feat(PlayerConnection): better implementation of /tp and /time
feat(PlayerConnection): better implementation of /time

fix(PlayerConnection): /tp

fix(PlayerConnection): /tp

fix(PlayerConnection): /time

fix(PlayerConnection): /time

fix(PlayerConnection): /time

fix(PlayerConnection): /time

fix(PlayerConnection): /tp

fix(PlayerConnection): /tp
2026-05-03 15:43:25 +03:00
neoapps-dev d1cf63433f feat(ItemNameMap): support for wstring 2026-05-03 12:42:25 +03:00
neoapps-dev 3c9b607288 fix: include path 2026-05-03 12:36:12 +03:00
neoapps-dev 107fa9944a feat: ItemNameMap
fix: ItemNameMap regex

fix(cmake): custom target

fix(cmake): regex again, add support for Tile.h

fix(cmake): deps

fix(cmake): windows oh man

fix(cmake): windows, again
2026-05-03 12:34:09 +03:00
github-actions ee9fcd4b1f Merge remote-tracking branch 'origin/main' into experimental 2026-05-03 08:30:51 +00:00
/home/neo 985c213b27
feat: change title to Minecraft: neoLegacy (#56) 2026-05-02 22:02:56 +03:00
github-actions 7332304b20 Merge remote-tracking branch 'origin/main' into experimental 2026-05-02 19:00:44 +00:00
/home/neo abacd76024
feat(Minecraft.Client): client-side commands (#52) 2026-05-02 18:58:37 +03:00
github-actions a2f8569670 Merge remote-tracking branch 'origin/main' into experimental 2026-05-01 17:33:58 +00:00
github-actions e58800c22d Merge remote-tracking branch 'origin/main' into experimental 2026-05-01 17:19:28 +00:00
github-actions dcd084f1d5 Merge remote-tracking branch 'origin/main' into experimental 2026-05-01 17:03:50 +00:00
github-actions 5a83735d68 Merge remote-tracking branch 'origin/main' into experimental 2026-05-01 16:45:56 +00:00
github-actions 00118361a7 Merge remote-tracking branch 'origin/main' into experimental 2026-05-01 16:23:17 +00:00
/home/neo 556dce4eea
Merge pull request #47 from pieeebot/exp/achievements 2026-05-01 15:11:58 +03:00
github-actions 15164dc4c8 Merge remote-tracking branch 'origin/main' into exp/achievements 2026-05-01 12:08:53 +00:00
SevenToaster509 269f8d0335 feat: classic crafting
credits: comicgab
2026-05-01 10:27:56 +01:00
159 changed files with 4199 additions and 1250 deletions

View file

@ -62,7 +62,8 @@ body:
- type: input
id: itsrevela
attributes:
label: Is this reproducable in itsRevela/LCE-Revelations? (https://github.com/itsRevela/LCE-Revelations)
label: Is this reproducable in itsRevela/LCE-Revelations? (https://git.revela.dev/itsRevela/LCE-Revelations)
description: If this was a "no idea" or similar, it will be rejected.
validations:
required: true
@ -76,6 +77,39 @@ body:
validations:
required: true
- type: checkboxes
id: screenres
attributes:
label: Screen Resolution(s)
options:
- label: 1080p
- label: 720p
- label: 480p
validations:
required: true
- type: checkboxes
id: operatingsys
attributes:
label: Operating System(s)
options:
- label: Windows 11
- label: Windows 10
- label: Windows 8.1 (not very supported)
- label: Debian(-based)
- label: Arch(-based)
- label: Gentoo(-based)
validations:
required: true
- type: input
id: launcher
attributes:
label: Launcher
placeholder: e.g. Emerald Launcher
validations:
required: true
- type: textarea
id: additional
attributes:

BIN
.github/banner.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 656 KiB

After

Width:  |  Height:  |  Size: 673 KiB

BIN
.github/roadmap.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 198 KiB

View file

@ -1,9 +1,8 @@
name: Nightly Release
on:
push:
branches:
- experimental
- main
workflow_dispatch:
permissions:
@ -255,7 +254,7 @@ jobs:
- \`neoLegacyServerWindows64-FourKit.zip\`: server with the FourKit plugin host, bundled .NET 10 runtime, and an empty \`plugins/\` folder ready for plugin authors to drop DLLs into.
Pick the flavour you want and extract it to a folder where you'd like to keep the server runtime." \
--latest=false
--latest=false --prerelease=true
release-client:
name: Release Client
@ -333,7 +332,7 @@ jobs:
run: |
gh release create Nightly artifacts/* \
--title "Client: ${{ steps.sha.outputs.short }}" \
--notes-file notes.md
--notes-file notes.md --prerelease=true
cleanup:
needs: [release-client, release-server]

View file

@ -2,8 +2,9 @@ name: Stable Release
on:
push:
branches:
- main
paths:
- 'BUMP' #neo: this is a file. edit it. contains version number
#neo: DO NOT ADD NOTES.md HERE.
workflow_dispatch:
permissions:
@ -221,33 +222,21 @@ jobs:
artifacts/neoLegacyServerWindows64.zip
artifacts/neoLegacyServerWindows64-FourKit.zip
- name: Get short SHA
id: sha
run: echo "short=$(echo '${{ github.sha }}' | cut -c1-7)" >> "$GITHUB_OUTPUT"
- name: Delete old release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release delete Stable-Dedicated-Server --yes || true
- name: Delete old tag
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh api repos/${{ github.repository }}/git/refs/tags/Stable-Dedicated-Server --method DELETE || true
- name: Create tag
run: |
VERSION=v$(cat BUMP)
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -f Stable-Dedicated-Server -m "Stable server release ${{ steps.sha.outputs.short }}"
git push origin Stable-Dedicated-Server --force
git tag -f $VERSION-Dedicated-Server -m "$VERSION server"
git push origin $VERSION-Dedicated-Server --force
- name: Create release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create Stable-Dedicated-Server artifacts/* \
--title "Server: ${{ steps.sha.outputs.short }}" \
VERSION=v$(cat BUMP)
gh release create $VERSION-Dedicated-Server artifacts/* \
--title "$VERSION Server" \
--notes "Dedicated Server runtime for Windows64.
Two flavours are attached:
@ -278,62 +267,22 @@ jobs:
subject-path: |
artifacts/neoLegacyWindows64.zip
- name: Get short SHA
id: sha
run: echo "short=$(echo '${{ github.sha }}' | cut -c1-7)" >> "$GITHUB_OUTPUT"
- name: Delete old release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release delete Stable --yes || true
- name: Delete old tag
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh api repos/${{ github.repository }}/git/refs/tags/Stable --method DELETE || true
- name: Create tag
run: |
VERSION=v$(cat BUMP)
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -f Stable -m "Stable release ${{ steps.sha.outputs.short }}"
git push origin Stable --force
- name: Write release notes
run: |
cat > notes.md <<'NOTES'
# Instructions:
**Newcomers:**
- If this is your first time, download `neoLegacyWindows64.zip` and extract it wherever you would like to keep it.
- I would recommend to set your username prior to launch (create a file called `username.txt`, put your desired username into the file, and save).
- To play, simply run `Minecraft.Client.exe`.
**Steam Deck & Linux:**
- Y'all know the drill. Download the `neoLegacyWindows64.zip`, extract it, add the `Minecraft.Client.exe` as a "Non-Steam Game" within the Steam library, turn on compatibility mode with Proton Experimental, and then run it!
# Multiplayer instructions:
LAN games are natively supported, and any LAN games will appear automatically on the right. However, if you'd like to play with your friends online (and if you don't want to require them to setup a vpn, and/or if you don't want to port forward), I would recommend the following setup. Please keep in mind, you do NOT need to do this to enjoy the game. This is just how I have it setup for me so my friends can join without any hassle:
Prerequisites:
- Premium playit.gg account, costs about $3 USD per month. This is for setting up the tunnel.
- playit.gg agent installed on host PC.
How-to:
- Ensure your playit.gg agent is connected to your playit.gg account
- On the playit.gg website, setup a new tunnel (choose TCP). Ensure the configurable settings are set to the below values, assuming your agent is installed on the same computer as your online neoLegacyMinecraft game is hosted from.
- Configurable settings:
- Local IP: `127.0.0.1`
- Local Port: `25565`
- Proxy Protocol: `None`
- After creating your tunnel, navigate to the "Tunnels" main page. You'll see the IP address and port for your tunnel. This is what your friends will input when adding your server in order to join your online game!
git tag -f $VERSION -m "Stable release $VERSION"
git push origin $VERSION --force
- name: Create release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create Stable artifacts/* \
--title "Client: ${{ steps.sha.outputs.short }}" \
--notes-file notes.md
VERSION=v$(cat BUMP)
gh release create $VERSION artifacts/* \
--title "$VERSION" \
--notes-file NOTES.md
cleanup:
needs: [release-client, release-server]

1
BUMP Normal file
View file

@ -0,0 +1 @@
1.0.8b

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -108,6 +108,7 @@ enum EGameHostOptionWorldSize
#define GAMESETTING_VSYNC 0x01000000
#define GAMESETTING_EXCLUSIVEFULLSCREEN 0x02000000
#define GAMESETTING_CLASSICCRAFTING 0x04000000
#define GAMESETTING_HIDESAVESIZEBAR 0x08000000
// defines for languages

View file

@ -184,6 +184,8 @@ enum eGameSetting
//TU25
eGameSetting_ClassicCrafting,
// if enabled hides the save size bar in loadcreatejoinmenu (load tab)
eGameSetting_HideSaveSizeBar,
};
@ -971,4 +973,4 @@ enum eMCLang
eMCLang_hans,
eMCLang_hant,
};
};

View file

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "../../Minecraft.World/net.minecraft.world.entity.item.h"
#include "../../Minecraft.World/net.minecraft.world.entity.player.h"
#include "../../Minecraft.World/net.minecraft.world.level.tile.entity.h"
@ -27,6 +27,9 @@
#include "../GameMode.h"
#include "../Xbox/Social/SocialManager.h"
#include "Tutorial/TutorialMode.h"
#ifdef _WINDOWS64
#include "../Windows64/Network/WinsockNetLayer.h" // HUCKLE - added for quit on disconnect
#endif
#if defined _XBOX || defined _WINDOWS64
#include "../Xbox/XML/ATGXmlParser.h"
#include "../Xbox/XML/xmlFilesCallback.h"
@ -450,7 +453,7 @@ void CMinecraftApp::SetAction(int iPad, eXuiAction action, LPVOID param)
bool CMinecraftApp::IsAppPaused()
{
#if defined(_XBOX_ONE) || defined(__ORBIS__)
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
bool paused = m_bIsAppPaused;
EnterCriticalSection(&m_saveNotificationCriticalSection);
if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 )
@ -946,7 +949,9 @@ void CMinecraftApp::InitGameSettings()
memset(pProfileSettings,0,sizeof(C_4JProfile::PROFILESETTINGS));
SetDefaultOptions(pProfileSettings,i);
Win64_LoadSettings(GameSettingsA[i]);
#ifndef MINECRAFT_SERVER_BUILD
ApplyGameSettingsChanged(i);
#endif
#elif defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__
C4JStorage::PROFILESETTINGS *pProfileSettings=StorageManager.GetDashboardProfileSettings(i);
// 4J-PB - don't cause an options write to happen here
@ -1502,6 +1507,7 @@ void CMinecraftApp::ApplyGameSettingsChanged(int iPad)
//TU25
ActionGameSettings(iPad, eGameSetting_ClassicCrafting);
ActionGameSettings(iPad, eGameSetting_HideSaveSizeBar);
}
void CMinecraftApp::ActionGameSettings(int iPad,eGameSetting eVal)
@ -1755,6 +1761,9 @@ void CMinecraftApp::ActionGameSettings(int iPad,eGameSetting eVal)
case eGameSetting_ClassicCrafting:
//nothing to do here
break;
case eGameSetting_HideSaveSizeBar:
//nothing to do here
break;
}
}
@ -2512,6 +2521,21 @@ void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucV
GameSettingsA[iPad]->bSettingsChanged = true;
}
break;
case eGameSetting_HideSaveSizeBar:
if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_HIDESAVESIZEBAR) != (ucVal & 0x01) << 27)
{
if (ucVal == 1)
{
GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_HIDESAVESIZEBAR;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_HIDESAVESIZEBAR;
}
ActionGameSettings(iPad, eVal);
GameSettingsA[iPad]->bSettingsChanged = true;
}
break;
}
}
@ -2650,6 +2674,9 @@ unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal)
case eGameSetting_ClassicCrafting:
return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CLASSICCRAFTING) >> 26;
case eGameSetting_HideSaveSizeBar:
return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_HIDESAVESIZEBAR) >> 27;
case eGameSetting_VSync:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_VSYNC)>>24;
@ -3364,6 +3391,15 @@ void CMinecraftApp::HandleXuiActions(void)
SetAction(i,eAppAction_Idle);
// HUCKLE - added for quit game on disconnect
#ifdef _WINDOWS64
if(g_Win64MultiplayerQuitOnDisconnect == true)
{
app.ExitGame();
return;
}
#endif
// If we're already leaving don't exit
if (g_NetworkManager.IsLeavingGame())
{
@ -9589,8 +9625,9 @@ bool CMinecraftApp::DLCContentRetrieved(eDLCMarketplaceType eType)
void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, DWORD dwSkinBoxC)
{
EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER);
Model *pModel = renderer->getModel();
EntityRenderDispatcher *dispatcher = EntityRenderDispatcher::instance;
EntityRenderer *renderer = dispatcher ? dispatcher->getRenderer(eTYPE_PLAYER) : nullptr;
Model *pModel = renderer ? renderer->getModel() : nullptr;
vector<ModelPart *> *pvModelPart = new vector<ModelPart *>;
vector<SKIN_BOX *> *pvSkinBoxes = new vector<SKIN_BOX *>;
@ -9621,8 +9658,9 @@ void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, D
vector<ModelPart *> * CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, vector<SKIN_BOX *> *pvSkinBoxA)
{
EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER);
Model *pModel = renderer->getModel();
EntityRenderDispatcher *dispatcher = EntityRenderDispatcher::instance;
EntityRenderer *renderer = dispatcher ? dispatcher->getRenderer(eTYPE_PLAYER) : nullptr;
Model *pModel = renderer ? renderer->getModel() : nullptr;
vector<ModelPart *> *pvModelPart = new vector<ModelPart *>;
EnterCriticalSection( &csAdditionalModelParts );

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

View file

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

View file

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

View file

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

View file

@ -438,6 +438,7 @@ static bool Win64_DeleteSaveDirectory(const wchar_t* wPath)
// This function performs the meat of exiting from a level. It should be called from a thread other than the main thread.
void IUIScene_PauseMenu::_ExitWorld(LPVOID lpParameter)
{
#ifndef MINECRAFT_SERVER_BUILD
Minecraft *pMinecraft=Minecraft::GetInstance();
// 4J Added: Capture hardcore delete info before the server is destroyed
@ -724,6 +725,7 @@ void IUIScene_PauseMenu::_ExitWorld(LPVOID lpParameter)
// Make sure we don't think saving is disabled in the menus
StorageManager.SetSaveDisabled(false);
#endif
#endif
}
@ -780,4 +782,4 @@ int IUIScene_PauseMenu::DisableAutosaveDialogReturned(void *pParam,int iPad,C4JS
app.SetAction(iPad,eAppAction_SaveGame);
}
return 0;
}
}

View file

@ -94,6 +94,18 @@ S32 UIControl::getYPos()
return m_y;
}
void UIControl::setXPos(S32 x)
{
m_x = x;
IggyValueSetF64RS( getIggyValuePath(), m_nameXPos, nullptr, (F64)x );
}
void UIControl::setYPos(S32 y)
{
m_y = y;
IggyValueSetF64RS( getIggyValuePath(), m_nameYPos, nullptr, (F64)y );
}
S32 UIControl::getWidth()
{
return m_width;

View file

@ -81,6 +81,8 @@ public:
S32 getXPos();
S32 getYPos();
void setXPos(S32 x);
void setYPos(S32 y);
S32 getWidth();
S32 getHeight();

View file

@ -14,6 +14,14 @@ bool UIControl_SaveList::setupControl(UIScene *scene, IggyValuePath *parent, con
return success;
}
void UIControl_SaveList::enableX2Icons()
{
IggyName useX2 = registerFastName(L"m_bUseX2IconButtons");
IggyValueSetBooleanRS(getIggyValuePath(), useX2, nullptr, true);
}
void UIControl_SaveList::addItem(const wstring &label)
{
addItem(label, L"");
@ -92,6 +100,78 @@ void UIControl_SaveList::addItem(const wstring &label, const wstring &iconName,
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_addNewItemFunc , 3 , value );
}
void UIControl_SaveList::addItem(const string &label, const wstring &iconName1, const wstring &iconName2)
{
addItem(label, iconName1, iconName2, m_itemCount);
++m_itemCount;
}
void UIControl_SaveList::addItem(const wstring &label, const wstring &iconName1, const wstring &iconName2)
{
addItem(label, iconName1, iconName2, m_itemCount);
++m_itemCount;
}
void UIControl_SaveList::addItem(const string &label, const wstring &iconName1, const wstring &iconName2, int data)
{
IggyDataValue result;
IggyDataValue value[4];
IggyStringUTF8 stringVal;
stringVal.string = (char*)label.c_str();
stringVal.length = static_cast<S32>(label.length());
value[0].type = IGGY_DATATYPE_string_UTF8;
value[0].string8 = stringVal;
value[1].type = IGGY_DATATYPE_number;
value[1].number = data;
IggyStringUTF16 stringVal2;
stringVal2.string = (IggyUTF16*)iconName1.c_str();
stringVal2.length = iconName1.length();
value[2].type = IGGY_DATATYPE_string_UTF16;
value[2].string16 = stringVal2;
IggyStringUTF16 stringVal3;
stringVal3.string = (IggyUTF16*)iconName2.c_str();
stringVal3.length = iconName2.length();
value[3].type = IGGY_DATATYPE_string_UTF16;
value[3].string16 = stringVal3;
IggyResult out = IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, getIggyValuePath(), m_addNewItemFunc, 4, value);
}
void UIControl_SaveList::addItem(const wstring &label, const wstring &iconName1, const wstring &iconName2, int data)
{
wstring shaped = shapeArabicText(label);
IggyDataValue result;
IggyDataValue value[4];
IggyStringUTF16 stringVal;
stringVal.string = (IggyUTF16*)shaped.c_str();
stringVal.length = static_cast<S32>(shaped.length());
value[0].type = IGGY_DATATYPE_string_UTF16;
value[0].string16 = stringVal;
value[1].type = IGGY_DATATYPE_number;
value[1].number = data;
IggyStringUTF16 stringVal2;
stringVal2.string = (IggyUTF16*)iconName1.c_str();
stringVal2.length = iconName1.length();
value[2].type = IGGY_DATATYPE_string_UTF16;
value[2].string16 = stringVal2;
IggyStringUTF16 stringVal3;
stringVal3.string = (IggyUTF16*)iconName2.c_str();
stringVal3.length = iconName2.length();
value[3].type = IGGY_DATATYPE_string_UTF16;
value[3].string16 = stringVal3;
IggyResult out = IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, getIggyValuePath(), m_addNewItemFunc, 4, value);
}
void UIControl_SaveList::setTextureName(int iId, const wstring &iconName)
{
IggyDataValue result;
@ -107,3 +187,4 @@ void UIControl_SaveList::setTextureName(int iId, const wstring &iconName)
value[1].string16 = stringVal;
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath(), m_funcSetTextureName , 2 , value );
}

View file

@ -20,10 +20,17 @@ public:
void addItem(const string &label, const wstring &iconName);
void addItem(const wstring &label, const wstring &iconName);
void addItem(const string &label, const wstring &iconName1, const wstring &iconName2);
void addItem(const wstring &label, const wstring &iconName1, const wstring &iconName2);
void setTextureName(int iId, const wstring &iconName);
void enableX2Icons();
private:
void addItem(const string &label, const wstring &iconName, int data);
void addItem(const wstring &label, const wstring &iconName, int data);
void addItem(const string &label, const wstring &iconName1, const wstring &iconName2, int data);
void addItem(const wstring &label, const wstring &iconName1, const wstring &iconName2, int data);
};

View file

@ -5,6 +5,7 @@
#include "UIScene.h"
#include "UIControl_Slider.h"
#include "UIControl_TexturePackList.h"
#include "UIControl_CheckBox.h"
#include "UIControl_AchievementsList.h"
#include "UIScene_AchievementsMenu.h"
#include "../../../Minecraft.World/StringHelpers.h"
@ -615,6 +616,8 @@ void UIController::loadSkins()
//used these as skin.swf and skinInGame.swf it breaks some other things
m_iggyLibraries[eLibrary_LCDefault] = loadSkin(L"skinLC.swf", L"skinLC.swf");
m_iggyLibraries[eLibrary_LCInGame] = loadSkin(L"skinInGameLC.swf", L"skinInGameLC.swf");
m_iggyLibraries[eLibrary_LCGraphics] = loadSkin(L"skinGraphicsLC.swf", L"skinGraphicsLC.swf");
m_iggyLibraries[eLibrary_LCLabels] = loadSkin(L"skinLabelsLC.swf", L"skinLabelsLC.swf");
// Some 1080p menu ports (such as LoadCreateJoin) may import DR-specific HD
// libraries by distinct names. Load them opportunistically when present so
@ -834,6 +837,7 @@ void UIController::tickInput()
{
#ifdef _WINDOWS64
m_mouseClickConsumedByScene = false;
UIControl* currHitCtrl = NULL;
if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive())
{
UIScene *pScene = nullptr;
@ -1008,6 +1012,7 @@ void UIController::tickInput()
hitControlId = -1;
hitArea = INT_MAX;
hitCtrl = NULL;
hitCtrl = ctrl;
break; // ButtonList takes priority
}
if (type == UIControl::eAchievementList)
@ -1020,6 +1025,7 @@ void UIController::tickInput()
hitControlId = -1;
hitArea = INT_MAX;
hitCtrl = NULL;
hitCtrl = ctrl;
break;
}
if (type == UIControl::eTexturePackList)
@ -1068,6 +1074,8 @@ void UIController::tickInput()
}
}
}
currHitCtrl = hitCtrl;
UpdateCursorIcon(currHitCtrl);
}
}
@ -1194,6 +1202,27 @@ void UIController::tickInput()
}
}
void UIController::UpdateCursorIcon(UIControl *hitCtrl)
{
// from WinUser.h
if (hitCtrl && (hitCtrl->getControlType() == UIControl::eButton || hitCtrl->getControlType() == UIControl::eButtonList))
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_HAND));
else if (hitCtrl && (hitCtrl->getControlType() == UIControl::eSlider || hitCtrl->getControlType() == UIControl::eTexturePackList))
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_SIZEWE));
else if (hitCtrl && hitCtrl->getControlType() == UIControl::eTextInput)
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_IBEAM));
else if (hitCtrl && hitCtrl->getControlType() == UIControl::eCheckBox) // Show the cross sign shaped cursor only when the checkbox is disabled/grayed out
{
UIControl_CheckBox *pCheck = static_cast<UIControl_CheckBox *>(hitCtrl);
if (pCheck && !pCheck->IsEnabled())
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_NO));
else
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_HAND));
}
else
g_KBMInput.SetCursorIcon(MAKEINTRESOURCEW(IDC_ARROW));
}
void UIController::handleInput()
{
// For each user, loop over each key type and send messages based on the state
@ -1487,10 +1516,16 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key)
// hovering a horizontal list (e.g. TexturePackList), UP/DOWN otherwise.
if (pressed && g_KBMInput.IsKBMActive())
{
if (m_bMouseHoverHorizontalList)
key = (key == ACTION_MENU_OTHER_STICK_UP) ? ACTION_MENU_LEFT : ACTION_MENU_RIGHT;
else
key = (key == ACTION_MENU_OTHER_STICK_UP) ? ACTION_MENU_UP : ACTION_MENU_DOWN;
UIScene* pTopScene = GetTopScene(0); // using 0 as default pad for KBM
bool isJoinMenu = pTopScene && pTopScene->getSceneType() == eUIScene_JoinMenu;
if (!isJoinMenu)
{
if (m_bMouseHoverHorizontalList)
key = (key == ACTION_MENU_OTHER_STICK_UP) ? ACTION_MENU_LEFT : ACTION_MENU_RIGHT;
else
key = (key == ACTION_MENU_OTHER_STICK_UP) ? ACTION_MENU_UP : ACTION_MENU_DOWN;
}
}
}
}
@ -2070,6 +2105,7 @@ bool UIController::NavigateToScene(int iPad, EUIScene scene, void *initData, EUI
SetMenuDisplayed(menuDisplayedPad,true);
bool success = m_groups[static_cast<int>(group)]->NavigateToScene(iPad, scene, initData, layer);
if(success && group == eUIGroup_Fullscreen) setFullscreenMenuDisplayed(true);
UpdateCursorIcon(nullptr);
LeaveCriticalSection(&m_navigationLock);
timer.PrintElapsedTime(L"Navigate to scene");
@ -2109,6 +2145,7 @@ bool UIController::NavigateBack(int iPad, bool forceUsePad, EUIScene eScene, EUI
navComplete = m_groups[static_cast<int>(eUIGroup_Fullscreen)]->NavigateBack(iPad, eScene, eLayer);
if(!m_groups[static_cast<int>(eUIGroup_Fullscreen)]->GetMenuDisplayed()) SetMenuDisplayed(XUSER_INDEX_ANY,false);
}
UpdateCursorIcon(nullptr);
return navComplete;
}

View file

@ -105,6 +105,8 @@ private:
eLibrary_LCDefault,
eLibrary_LCInGame,
eLibrary_LCGraphics,
eLibrary_LCLabels,
#if defined(_WINDOWS64)
// Non-HD skin libraries needed by 720p/480p scene SWFs.
@ -260,6 +262,7 @@ public:
// INPUT
private:
void tickInput();
void UpdateCursorIcon(UIControl *hitCtrl);
void handleInput();
void handleKeyPress(unsigned int iPad, unsigned int key);

View file

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

View file

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

View file

@ -12,10 +12,18 @@
#ifdef _WINDOWS64
#include "../../Windows64/Network/WinsockNetLayer.h"
#include "../../Windows64/4JLibs/inc/4J_Input.h"
#endif
#define UPDATE_PLAYERS_TIMER_ID 0
#define UPDATE_PLAYERS_TIMER_TIME 30000
#define UPDATE_PLAYERS_TIMER_TIME 400.0
// static overlay state for howtoplay
static Iggy* s_movieServerDesc = nullptr;
static vector<unsigned char> s_movieDataServerDesc;
static IggyName s_funcLoadPage = 0;
static bool s_textInjected = false;
static int s_injectionDelay = 0;
UIScene_JoinMenu::UIScene_JoinMenu(int iPad, void *_initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
@ -32,9 +40,67 @@ UIScene_JoinMenu::UIScene_JoinMenu(int iPad, void *_initData, UILayer *parentLay
m_editServerPhase = eEditServer_Idle;
m_editServerButtonIndex = -1;
m_deleteServerButtonIndex = -1;
// reset the howtoplay state
s_textInjected = false;
s_injectionDelay = 0;
// load howtoplay it's like the messagebox xd
if (!s_movieServerDesc)
{
wstring moviePath = L"HowToPlay";
if (m_loadedResolution == eSceneResolution_1080) moviePath.append(L"1080.swf");
else if (m_loadedResolution == eSceneResolution_720) moviePath.append(L"720.swf");
else moviePath.append(L"480.swf");
byteArray baFile = ui.getMovieData(moviePath.c_str());
if (baFile.data)
{
s_movieDataServerDesc.assign((unsigned char*)baFile.data, (unsigned char*)baFile.data + baFile.length);
s_movieServerDesc = IggyPlayerCreateFromMemory(s_movieDataServerDesc.data(), (unsigned int)s_movieDataServerDesc.size(), nullptr);
if (s_movieServerDesc)
{
IggyPlayerInitializeAndTickRS(s_movieServerDesc);
IggyPlayerSetDisplaySize(s_movieServerDesc, m_movieWidth, m_movieHeight);
s_funcLoadPage = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"LoadHowToPlayPage", -1);
// it maintains the resolution at 1080p so that it looks sharp
IggyValuePath *root = IggyPlayerRootPath(s_movieServerDesc);
if (root)
{
IggyValueSetF64RS(root, IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"x", -1), nullptr, 0.0);
IggyValueSetF64RS(root, IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"y", -1), nullptr, 0.0);
IggyValueSetF64RS(root, IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"width", -1), nullptr, (double)m_movieWidth);
IggyValueSetF64RS(root, IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"height", -1), nullptr, (double)m_movieHeight);
// it hides the logo and other things that the howtoplay has
const char* elementsToHide[] = { "__id0_", "__id1_", "__id2_" };
IggyName visibleName = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16 *)L"visible", -1);
for (int i = 0; i < 3; i++) {
IggyValuePath path;
if (IggyValuePathMakeNameRef(&path, root, elementsToHide[i])) {
IggyValueSetBooleanRS(&path, visibleName, nullptr, false);
}
}
updateServerDescription();
}
}
}
}
#endif
}
UIScene_JoinMenu::~UIScene_JoinMenu()
{
// destroy the player when closing the scene to avoid zombie pointers
if (s_movieServerDesc)
{
IggyPlayerDestroy(s_movieServerDesc);
s_movieServerDesc = nullptr;
}
}
void UIScene_JoinMenu::updateTooltips()
{
int iA = -1;
@ -65,45 +131,46 @@ void UIScene_JoinMenu::updateTooltips()
void UIScene_JoinMenu::tick()
{
if( !m_friendInfoRequestIssued )
if (!m_friendInfoRequestIssued)
{
ui.NavigateToScene(m_iPad, eUIScene_Timer);
g_NetworkManager.GetFullFriendSessionInfo(m_selectedSession, &friendSessionUpdated, this);
m_friendInfoRequestIssued = true;
}
if( m_friendInfoUpdatedOK )
if (m_friendInfoUpdatedOK)
{
m_friendInfoUpdatedOK = false;
m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME),eControl_JoinGame);
m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME), eControl_JoinGame);
m_buttonListPlayers.init(eControl_GamePlayers);
m_buttonListPlayers.setYPos(m_buttonListPlayers.getYPos() + 300);
#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__
for( int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++ )
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++)
{
if( m_selectedSession->data.players[i] != nullptr )
if (m_selectedSession->data.players[i] != nullptr)
{
#ifndef _CONTENT_PACKAGE
if(app.DebugSettingsOn() && (app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_DebugLeaderboards)))
#ifndef _CONTENT_PACKAGE
if (app.DebugSettingsOn() && (app.GetGameSettingsDebugMask() & (1L << eDebugSetting_DebugLeaderboards)))
{
m_buttonListPlayers.addItem(L"WWWWWWWWWWWWWWWW");
}
else
#endif
#endif
{
string playerName(m_selectedSession->data.players[i].getOnlineID());
#ifndef __PSVITA__
#ifndef __PSVITA__
// Append guest number (any players in an online game not signed into PSN are guests)
if( m_selectedSession->data.players[i].isSignedIntoPSN() == false )
if (m_selectedSession->data.players[i].isSignedIntoPSN() == false)
{
char suffix[5];
sprintf(suffix, " (%d)", m_selectedSession->data.players[i].getQuadrant() + 1);
playerName.append(suffix);
}
#endif
#endif
m_buttonListPlayers.addItem(playerName);
}
}
@ -114,9 +181,9 @@ void UIScene_JoinMenu::tick()
}
}
#elif defined(_DURANGO)
for( int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++ )
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++)
{
if ( m_selectedSession->searchResult.m_playerNames[i].size() )
if (m_selectedSession->searchResult.m_playerNames[i].size())
{
m_buttonListPlayers.addItem(m_selectedSession->searchResult.m_playerNames[i]);
}
@ -149,73 +216,74 @@ void UIScene_JoinMenu::tick()
m_labelLabels[eLabel_FireOn].init(app.GetString(IDS_LABEL_FIRE_SPREADS));
unsigned int uiGameHostSettings = m_selectedSession->data.m_uiGameHostSettings;
switch(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_Difficulty))
switch (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_Difficulty))
{
case Difficulty::EASY:
m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_EASY) );
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_EASY));
break;
case Difficulty::NORMAL:
m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_NORMAL) );
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_NORMAL));
break;
case Difficulty::HARD:
m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_HARD) );
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_HARD));
break;
case Difficulty::PEACEFUL:
default:
m_labelValues[eLabel_Difficulty].init( app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL) );
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL));
break;
}
int option = app.GetGameHostOption(uiGameHostSettings,eGameHostOption_GameType);
if(option == GameType::CREATIVE->getId())
int option = app.GetGameHostOption(uiGameHostSettings, eGameHostOption_GameType);
if (option == GameType::CREATIVE->getId())
{
m_labelValues[eLabel_GameType].init( app.GetString(IDS_CREATIVE) );
m_labelValues[eLabel_GameType].init(app.GetString(IDS_CREATIVE));
}
else if(option == GameType::ADVENTURE->getId())
else if (option == GameType::ADVENTURE->getId())
{
m_labelValues[eLabel_GameType].init( app.GetString(IDS_ADVENTURE) );
m_labelValues[eLabel_GameType].init(app.GetString(IDS_ADVENTURE));
}
else
{
m_labelValues[eLabel_GameType].init( app.GetString(IDS_SURVIVAL) );
m_labelValues[eLabel_GameType].init(app.GetString(IDS_SURVIVAL));
}
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_Gamertags)) m_labelValues[eLabel_GamertagsOn].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_GamertagsOn].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_Gamertags)) m_labelValues[eLabel_GamertagsOn].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_GamertagsOn].init(app.GetString(IDS_OFF));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_Structures)) m_labelValues[eLabel_Structures].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_Structures].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_Structures)) m_labelValues[eLabel_Structures].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_Structures].init(app.GetString(IDS_OFF));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_LevelType)) m_labelValues[eLabel_LevelType].init( app.GetString(IDS_LEVELTYPE_SUPERFLAT) );
else m_labelValues[eLabel_LevelType].init( app.GetString(IDS_LEVELTYPE_NORMAL) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_LevelType)) m_labelValues[eLabel_LevelType].init(app.GetString(IDS_LEVELTYPE_SUPERFLAT));
else m_labelValues[eLabel_LevelType].init(app.GetString(IDS_LEVELTYPE_NORMAL));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_PvP))m_labelValues[eLabel_PVP].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_PVP].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_PvP))m_labelValues[eLabel_PVP].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_PVP].init(app.GetString(IDS_OFF));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_TrustPlayers)) m_labelValues[eLabel_Trust].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_Trust].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_TrustPlayers)) m_labelValues[eLabel_Trust].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_Trust].init(app.GetString(IDS_OFF));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_TNT)) m_labelValues[eLabel_TNTOn].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_TNTOn].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_TNT)) m_labelValues[eLabel_TNTOn].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_TNTOn].init(app.GetString(IDS_OFF));
if(app.GetGameHostOption(uiGameHostSettings,eGameHostOption_FireSpreads)) m_labelValues[eLabel_FireOn].init( app.GetString(IDS_ON) );
else m_labelValues[eLabel_FireOn].init( app.GetString(IDS_OFF) );
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_FireSpreads)) m_labelValues[eLabel_FireOn].init(app.GetString(IDS_ON));
else m_labelValues[eLabel_FireOn].init(app.GetString(IDS_OFF));
m_bIgnoreInput = false;
// Alert the app the we want to be informed of ethernet connections
app.SetLiveLinkRequired( true );
app.SetLiveLinkRequired(true);
TelemetryManager->RecordMenuShown(m_iPad, eUIScene_JoinMenu, 0);
addTimer(UPDATE_PLAYERS_TIMER_ID,UPDATE_PLAYERS_TIMER_TIME);
addTimer(UPDATE_PLAYERS_TIMER_ID, UPDATE_PLAYERS_TIMER_TIME);
}
if( m_friendInfoUpdatedERROR )
if (m_friendInfoUpdatedERROR)
{
m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME),eControl_JoinGame);
m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME), eControl_JoinGame);
m_buttonListPlayers.init(eControl_GamePlayers);
m_buttonListPlayers.setYPos(m_buttonListPlayers.getYPos() + 300);
m_labelLabels[eLabel_Difficulty].init(app.GetString(IDS_LABEL_DIFFICULTY));
m_labelLabels[eLabel_GameType].init(app.GetString(IDS_LABEL_GAME_TYPE));
@ -228,14 +296,14 @@ void UIScene_JoinMenu::tick()
m_labelLabels[eLabel_FireOn].init(app.GetString(IDS_LABEL_FIRE_SPREADS));
m_labelValues[eLabel_Difficulty].init(app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL));
m_labelValues[eLabel_GameType].init( app.GetString(IDS_CREATIVE) );
m_labelValues[eLabel_GamertagsOn].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_Structures].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_LevelType].init( app.GetString(IDS_LEVELTYPE_NORMAL) );
m_labelValues[eLabel_PVP].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_Trust].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_TNTOn].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_FireOn].init( app.GetString(IDS_OFF) );
m_labelValues[eLabel_GameType].init(app.GetString(IDS_CREATIVE));
m_labelValues[eLabel_GamertagsOn].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_Structures].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_LevelType].init(app.GetString(IDS_LEVELTYPE_NORMAL));
m_labelValues[eLabel_PVP].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_Trust].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_TNTOn].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_FireOn].init(app.GetString(IDS_OFF));
m_friendInfoUpdatedERROR = false;
@ -244,15 +312,109 @@ void UIScene_JoinMenu::tick()
UINT uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
#ifdef _XBOX_ONE
ui.RequestErrorMessage( IDS_CONNECTION_FAILED, IDS_DISCONNECTED_SERVER_QUIT, uiIDA,1,m_iPad,ErrorDialogReturned,this);
ui.RequestErrorMessage(IDS_CONNECTION_FAILED, IDS_DISCONNECTED_SERVER_QUIT, uiIDA, 1, m_iPad, ErrorDialogReturned, this);
#else
ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA,1,m_iPad,ErrorDialogReturned,this);
ui.RequestErrorMessage(IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, m_iPad, ErrorDialogReturned, this);
#endif
}
#ifdef _WINDOWS64
if (s_movieServerDesc)
{
if (IggyPlayerReadyToTick(s_movieServerDesc))
{
IggyPlayerTickRS(s_movieServerDesc);
updateServerDescription();
}
}
#endif
UIScene::tick();
}
void UIScene_JoinMenu::updateServerDescription() {
IggyValuePath* root = IggyPlayerRootPath(s_movieServerDesc);
if (root)
{
// scale the size before Iggy reads it
IggyValuePath textPath;
if (IggyValuePathMakeNameRef(&textPath, root, "HowToPlayText_0"))
{
IggyName nameX = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"x", -1);
IggyName nameY = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"y", -1);
IggyName nameW = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"width", -1);
IggyName nameH = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"height", -1);
if (m_loadedResolution == eSceneResolution_1080)
{
IggyValueSetF64RS(&textPath, nameX, nullptr, 333.0);// horizontal
IggyValueSetF64RS(&textPath, nameY, nullptr, 340.0);// vertical
IggyValueSetF64RS(&textPath, nameW, nullptr, 580.0);
IggyValueSetF64RS(&textPath, nameH, nullptr, 270.0);
}
else //720
{
IggyValueSetF64RS(&textPath, nameX, nullptr, 252.0);
IggyValueSetF64RS(&textPath, nameY, nullptr, 285.0);
IggyValueSetF64RS(&textPath, nameW, nullptr, 440.0);
IggyValueSetF64RS(&textPath, nameH, nullptr, 220.0);
}
}
// harcoded text for test it, later im gonna delete this and
// and convert it so that people can add their description when adding the server
if (s_funcLoadPage != 0)
{
IggyDataValue result;
IggyDataValue args[2];
args[0].type = IGGY_DATATYPE_number;
args[0].number = 0; // 0 is the what's new page on howtoplay don't change it
wstring testText = L"\nNothing yet...";
IggyStringUTF16 iggyStr;
wstring formattedText = app.EscapeHTMLString(testText);
formattedText = app.FormatChatMessage(formattedText);
iggyStr.string = (IggyUTF16*)formattedText.c_str();
iggyStr.length = (unsigned int)formattedText.length();
args[1].type = IGGY_DATATYPE_string_UTF16;
args[1].string16 = iggyStr;
IggyResult res = IggyPlayerCallMethodRS(s_movieServerDesc, &result, root, s_funcLoadPage, 2, args);
if (res == IGGY_RESULT_SUCCESS)
{
s_textInjected = true;
}
}
// keeps the text fixed so it doesn't move from its place
IggyValuePath panelPath;
if (s_textInjected && IggyValuePathMakeNameRef(&panelPath, root, "DynamicHtmlText"))
{
IggyName nameX = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"x", -1);
IggyName nameY = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"y", -1);
IggyName nameW = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"width", -1);
IggyName nameH = IggyPlayerCreateFastName(s_movieServerDesc, (IggyUTF16*)L"height", -1);
if (m_loadedResolution == eSceneResolution_1080)
{
IggyValueSetF64RS(&panelPath, nameX, nullptr, 332.0);// horizontal
IggyValueSetF64RS(&panelPath, nameY, nullptr, 340.0);// vertical
IggyValueSetF64RS(&panelPath, nameW, nullptr, 580.0);
IggyValueSetF64RS(&panelPath, nameH, nullptr, 270.0);
}
else //720p
{
IggyValueSetF64RS(&panelPath, nameX, nullptr, 250.0);
IggyValueSetF64RS(&panelPath, nameY, nullptr, 290.0);
IggyValueSetF64RS(&panelPath, nameW, nullptr, 400.0);
IggyValueSetF64RS(&panelPath, nameH, nullptr, 230.0);
}
}
}
}
void UIScene_JoinMenu::friendSessionUpdated(bool success, void *pParam)
{
UIScene_JoinMenu *scene = static_cast<UIScene_JoinMenu *>(pParam);
@ -275,6 +437,7 @@ int UIScene_JoinMenu::ErrorDialogReturned(void *pParam, int iPad, const C4JStora
return 0;
}
void UIScene_JoinMenu::updateComponents()
{
m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true);
@ -286,6 +449,19 @@ wstring UIScene_JoinMenu::getMoviePath()
return L"JoinMenu";
}
void UIScene_JoinMenu::render(S32 width, S32 height, C4JRender::eViewportType viewpBort)
{
UIScene::render(width, height, viewpBort);
#ifdef _WINDOWS64
if (s_movieServerDesc)
{
IggyPlayerSetDisplaySize(s_movieServerDesc, width, height);
IggyPlayerDraw(s_movieServerDesc);
}
#endif
}
void UIScene_JoinMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
if(m_bIgnoreInput) return;
@ -353,6 +529,21 @@ void UIScene_JoinMenu::handleInput(int iPad, int key, bool repeat, bool pressed,
sendInputToMovie(key, repeat, pressed, released);
handled = true;
break;
#ifdef _WINDOWS64
case ACTION_MENU_OTHER_STICK_UP:
case ACTION_MENU_OTHER_STICK_DOWN:
if (s_movieServerDesc)
{
IggyEvent keyEvent;
IggyKeycode iggyKeyCode = (key == ACTION_MENU_OTHER_STICK_UP) ? IGGY_KEYCODE_F11 : IGGY_KEYCODE_F12;
IggyMakeEventKey(&keyEvent, pressed ? IGGY_KEYEVENT_Down : IGGY_KEYEVENT_Up, iggyKeyCode, IGGY_KEYLOC_Standard);
IggyEventResult res;
IggyPlayerDispatchEventRS(s_movieServerDesc, &keyEvent, &res);
handled = true;
}
break;
#endif
}
}

View file

@ -34,6 +34,10 @@ private:
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
UI_MAP_ELEMENT( m_buttonJoinGame, "JoinGame")
UI_MAP_ELEMENT( m_buttonListPlayers, "GamePlayers")
if (m_loadedResolution == eSceneResolution_720)
{
m_buttonListPlayers.setYPos(170.0);
}
UI_MAP_ELEMENT( m_labelLabels[0], "Label0")
UI_MAP_ELEMENT( m_labelLabels[1], "Label1")
@ -74,19 +78,24 @@ private:
public:
UIScene_JoinMenu(int iPad, void *initData, UILayer *parentLayer);
virtual ~UIScene_JoinMenu();
void tick();
static void friendSessionUpdated(bool success, void *pParam);
static int ErrorDialogReturned(void *pParam, int iPad, const C4JStorage::EMessageResult);
virtual void updateTooltips();
virtual void updateComponents();
virtual void render(S32 width, S32 height, C4JRender::eViewportType viewpBort);
virtual EUIScene getSceneType() { return eUIScene_LoadMenu;}
virtual EUIScene getSceneType() { return eUIScene_JoinMenu;}
protected:
// TODO: This should be pure virtual in this class
virtual wstring getMoviePath();
void updateServerDescription();
public:
public:
// INPUT
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);

View file

@ -751,6 +751,7 @@ UIScene_LoadCreateJoinMenu::UIScene_LoadCreateJoinMenu(int iPad, void *initData,
m_buttonListNewGames.init(eControl_NewGamesList);
m_buttonListGames.init(eControl_GamesList);
m_buttonListGames.enableX2Icons();
@ -1614,6 +1615,32 @@ void UIScene_LoadCreateJoinMenu::UpdateMouseHoverForActiveTab()
if (!ConvertMouseToSceneCoords(sceneMouseX, sceneMouseY))
return;
// tab area threshold (approx coordinates based on handleMouseClick)
float maxY = (getSceneResolution() == eSceneResolution_1080) ? 200.0f : 135.0f;
if (sceneMouseY < maxY)
{
// mouse is high up (near or on tabs) deselect lists to avoid collisions
if (m_buttonListSaves.getCurrentSelection() != -1)
{
m_buttonListSaves.setCurrentSelection(-1);
}
if (m_buttonListNewGames.getCurrentSelection() != -1)
{
m_buttonListNewGames.setCurrentSelection(-1);
}
if (m_buttonListGames.getCurrentSelection() != -1)
{
m_buttonListGames.setCurrentSelection(-1);
}
// reset internal indices to -1 so tick() doesn't restore selection
m_iSaveListIndex = -1;
m_iNewGameListIndex = -1;
m_iGameListIndex = -1;
m_bUpdateSaveSize = true; // refresh save size bar / secondary UI
}
UIControl_ButtonList *pActiveList = nullptr;
switch (m_activeTab)
{
@ -1757,6 +1784,76 @@ void UIScene_LoadCreateJoinMenu::UpdateMouseHoverForActiveTab()
m_bPendingSaveSizeBarRefresh = true;
m_bPendingJoinTabAvailabilityRefresh = true;
}
bool UIScene_LoadCreateJoinMenu::handleMouseClick(F32 x, F32 y)
{
if (!hasFocus(m_iPad) || getMovie() == nullptr || g_KBMInput.IsMouseGrabbed() || !g_KBMInput.IsKBMActive())
{
return false;
}
if (m_bIgnoreInput)
{
return false;
}
float sceneMouseX = 0.0f;
float sceneMouseY = 0.0f;
if (!ConvertMouseToSceneCoords(sceneMouseX, sceneMouseY))
{
return false;
}
float loadMinX = 335.0f;
float loadMaxX = 535.0f;
float createMaxX = 735.0f;
float joinMaxX = 935.0f;
float minY = 77.0f;
float maxY = 135.0f;
if (getSceneResolution() == eSceneResolution_1080)
{
loadMinX = 502.0f;
loadMaxX = 802.0f;
createMaxX = 1102.0f;
joinMaxX = 1402.0f;
minY = 115.0f;
maxY = 200.0f;
}
if (sceneMouseY >= minY && sceneMouseY <= maxY)
{
if (sceneMouseX >= loadMinX && sceneMouseX <= loadMaxX)
{
if (m_activeTab != eTab_Load)
{
SetActiveTab(eTab_Load, true);
ui.PlayUISFX(eSFX_Press);
}
return true; // click consumed by tab
}
else if (sceneMouseX > loadMaxX && sceneMouseX <= createMaxX)
{
if (m_activeTab != eTab_Create)
{
SetActiveTab(eTab_Create, true);
ui.PlayUISFX(eSFX_Press);
}
return true; // click consumed by tab
}
else if (sceneMouseX > createMaxX && sceneMouseX <= joinMaxX)
{
if (m_activeTab != eTab_Join)
{
SetActiveTab(eTab_Join, true);
ui.PlayUISFX(eSFX_Press);
}
return true; // click consumed by tab
}
}
return UIScene::handleMouseClick(x, y);
}
#endif
wstring UIScene_LoadCreateJoinMenu::getMoviePath()
@ -1943,7 +2040,10 @@ void UIScene_LoadCreateJoinMenu::UpdateSaveSizeBarVisibility()
const bool showSaveSizeBar = (m_activeTab == eTab_Load);
// user option to hide the save size bar entirely (added via SettingsUIMenu checkbox)
const bool hideBar = (app.GetGameSettings(m_iPad, eGameSetting_HideSaveSizeBar) != 0);
const bool showSaveSizeBar = (m_activeTab == eTab_Load) && !hideBar;
IggyDataValue result;
@ -1963,6 +2063,10 @@ void UIScene_LoadCreateJoinMenu::tick()
UIScene::tick();
#ifdef _WINDOWS64
UpdateMouseHoverForActiveTab();
#endif
#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined _WINDOWS64 || defined __PSVITA__)
if(m_bExitScene) // navigate forward or back
@ -4587,81 +4691,74 @@ void UIScene_LoadCreateJoinMenu::RebuildJoinGamesListVisual(bool syncFocus)
m_buttonListGames.setCurrentSelection(0);
for( FriendSessionInfo *sessionInfo : *m_currentSessions )
for (FriendSessionInfo *sessionInfo : *m_currentSessions)
{
const int gameType = app.GetGameHostOption(sessionInfo->data.m_uiGameHostSettings, eGameHostOption_GameType);
const wchar_t *modeIconFile = L"SurvivalIcon.png";
const wchar_t *modeIconName = L"SurvivalIcon";
wchar_t textureName[64] = L"\0";
if(sessionInfo->data.texturePackParentId!=0)
if (gameType == GameType::CREATIVE->getId())
{
Minecraft *pMinecraft = Minecraft::GetInstance();
TexturePack *tp = pMinecraft->skins->getTexturePackById(sessionInfo->data.texturePackParentId);
DWORD dwImageBytes=0;
PBYTE pbImageData=nullptr;
if(tp==nullptr)
{
DWORD dwBytes=0;
PBYTE pbData=nullptr;
app.GetTPD(sessionInfo->data.texturePackParentId,&pbData,&dwBytes);
app.GetFileFromTPD(eTPDFileType_Icon,pbData,dwBytes,&pbImageData,&dwImageBytes );
if(dwImageBytes > 0 && pbImageData)
{
swprintf(textureName,64,L"%ls",sessionInfo->displayLabel);
registerSubstitutionTexture(textureName,pbImageData,dwImageBytes);
}
}
else
{
pbImageData = tp->getPackIcon(dwImageBytes);
if(dwImageBytes > 0 && pbImageData)
{
swprintf(textureName,64,L"%ls",sessionInfo->displayLabel);
registerSubstitutionTexture(textureName,pbImageData,dwImageBytes);
}
}
modeIconFile = L"CreativeIcon.png";
modeIconName = L"CreativeIcon";
}
else if (gameType == GameType::ADVENTURE->getId())
{
modeIconFile = L"AdventureIcon.png";
modeIconName = L"AdventureIcon";
}
else
// register game mode icon
TrySetButtonListIcon(m_buttonListGames, -1, modeIconFile, modeIconName);
// texture pack icon logic
wchar_t tpIconName[64] = L"\0";
if (sessionInfo->data.texturePackParentId != 0)
{
Minecraft *pMinecraft = Minecraft::GetInstance();
TexturePack *tp = pMinecraft->skins->getTexturePackById(sessionInfo->data.texturePackParentId);
DWORD dwImageBytes = 0;
PBYTE pbImageData = nullptr;
if (tp == nullptr)
{
DWORD dwBytes = 0;
PBYTE pbData = nullptr;
app.GetTPD(sessionInfo->data.texturePackParentId, &pbData, &dwBytes);
app.GetFileFromTPD(eTPDFileType_Icon, pbData, dwBytes, &pbImageData, &dwImageBytes);
if (dwImageBytes > 0 && pbImageData)
{
swprintf(tpIconName, 64, L"tp_%ls", sessionInfo->displayLabel);
registerSubstitutionTexture(tpIconName, pbImageData, dwImageBytes);
}
}
else
{
pbImageData = tp->getPackIcon(dwImageBytes);
if (dwImageBytes > 0 && pbImageData)
{
swprintf(tpIconName, 64, L"tp_%ls", sessionInfo->displayLabel);
registerSubstitutionTexture(tpIconName, pbImageData, dwImageBytes);
}
}
}
else
{
Minecraft *pMinecraft = Minecraft::GetInstance();
TexturePack *tp = pMinecraft->skins->getTexturePackByIndex(0);
DWORD dwImageBytes;
PBYTE pbImageData = tp->getPackIcon(dwImageBytes);
if(dwImageBytes > 0 && pbImageData)
if (dwImageBytes > 0 && pbImageData)
{
swprintf(textureName,64,L"%ls",sessionInfo->displayLabel);
registerSubstitutionTexture(textureName,pbImageData,dwImageBytes);
swprintf(tpIconName, 64, L"tp_%ls", sessionInfo->displayLabel);
registerSubstitutionTexture(tpIconName, pbImageData, dwImageBytes);
}
}
m_buttonListGames.addItem( sessionInfo->displayLabel, textureName );
m_buttonListGames.addItem(sessionInfo->displayLabel, modeIconName, tpIconName);
if(memcmp( &selectedSessionId, &sessionInfo->sessionId, sizeof(SessionID) ) == 0)
if (memcmp(&selectedSessionId, &sessionInfo->sessionId, sizeof(SessionID)) == 0)
{

View file

@ -220,6 +220,7 @@ private:
void UpdateSaveSizeBarVisibility();
#ifdef _WINDOWS64
void UpdateMouseHoverForActiveTab();
virtual bool handleMouseClick(F32 x, F32 y) override;
bool ConvertMouseToSceneCoords(float &sceneMouseX, float &sceneMouseY);
void GetAbsoluteControlRect(UIControl *pControl, S32 &x, S32 &y, S32 &w, S32 &h);
#endif

View file

@ -1,4 +1,5 @@
#include "stdafx.h"
#include "../App_enums.h"
#include "UI.h"
#include "UIScene_SettingsUIMenu.h"
@ -16,6 +17,8 @@ UIScene_SettingsUIMenu::UIScene_SettingsUIMenu(int iPad, void *initData, UILayer
m_checkboxSplitscreen.init(app.GetString(IDS_CHECKBOX_VERTICAL_SPLIT_SCREEN),eControl_Splitscreen,(app.GetGameSettings(m_iPad,eGameSetting_SplitScreenVertical)!=0));
m_checkboxShowSplitscreenGamertags.init(app.GetString(IDS_CHECKBOX_DISPLAY_SPLITSCREENGAMERTAGS),eControl_ShowSplitscreenGamertags,(app.GetGameSettings(m_iPad,eGameSetting_DisplaySplitscreenGamertags)!=0));
m_checkboxShowClassicCrafting.init(app.GetString(IDS_CHECKBOX_CLASSICCRAFTING), eControl_ShowClassicCrafting, (app.GetGameSettings(m_iPad, eGameSetting_ClassicCrafting) != 0));
// label is hardcoded for now (no IDS_* yet)
m_checkboxHideLoadCreateJoinSaveSizeBar.init(L"Hide world disk space bar", eControl_HideSaveSizeBar, (app.GetGameSettings(m_iPad, eGameSetting_HideSaveSizeBar) != 0));
WCHAR TempString[256];
@ -106,6 +109,7 @@ void UIScene_SettingsUIMenu::handleInput(int iPad, int key, bool repeat, bool pr
app.SetGameSettings(m_iPad,eGameSetting_DeathMessages,m_checkboxDisplayDeathMessages.IsChecked()?1:0);
app.SetGameSettings(m_iPad,eGameSetting_AnimatedCharacter,m_checkboxDisplayAnimatedCharacter.IsChecked()?1:0);
app.SetGameSettings(m_iPad, eGameSetting_ClassicCrafting, m_checkboxShowClassicCrafting.IsChecked() ? 1 : 0);
app.SetGameSettings(m_iPad, eGameSetting_HideSaveSizeBar, m_checkboxHideLoadCreateJoinSaveSizeBar.IsChecked() ? 1 : 0);
// if the splitscreen vertical/horizontal has changed, need to update the scenes

View file

@ -14,11 +14,12 @@ private:
eControl_Splitscreen,
eControl_ShowSplitscreenGamertags,
eControl_ShowClassicCrafting,
eControl_HideSaveSizeBar,
eControl_UISize,
eControl_UISizeSplitscreen
};
UIControl_CheckBox m_checkboxDisplayHUD, m_checkboxDisplayHand, m_checkboxDisplayDeathMessages, m_checkboxDisplayAnimatedCharacter, m_checkboxSplitscreen, m_checkboxShowSplitscreenGamertags, m_checkboxShowClassicCrafting; // Checkboxes
UIControl_CheckBox m_checkboxDisplayHUD, m_checkboxDisplayHand, m_checkboxDisplayDeathMessages, m_checkboxDisplayAnimatedCharacter, m_checkboxSplitscreen, m_checkboxShowSplitscreenGamertags, m_checkboxShowClassicCrafting, m_checkboxHideLoadCreateJoinSaveSizeBar; // Checkboxes
UIControl_Slider m_sliderUISize, m_sliderUISizeSplitscreen; // Sliders
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
UI_MAP_ELEMENT( m_checkboxDisplayHUD, "DisplayHUD")
@ -28,6 +29,7 @@ private:
UI_MAP_ELEMENT( m_checkboxSplitscreen, "Splitscreen")
UI_MAP_ELEMENT( m_checkboxShowSplitscreenGamertags, "ShowSplitscreenGamertags")
UI_MAP_ELEMENT(m_checkboxShowClassicCrafting, "ShowClassicCrafting")
UI_MAP_ELEMENT(m_checkboxHideLoadCreateJoinSaveSizeBar, "LoadCreateJoinSaveSizeBar")
UI_MAP_ELEMENT( m_sliderUISize, "UISize")
UI_MAP_ELEMENT( m_sliderUISizeSplitscreen, "UISizeSplitscreen")
@ -52,4 +54,4 @@ public:
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled);
virtual void handleSliderMove(F64 sliderId, F64 currentValue);
};
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -141,8 +141,9 @@ LevelRenderer::LevelRenderer(Minecraft *mc, Textures *textures)
culledEntities = 0;
chunkFixOffs = 0;
frame = 0;
#ifndef MINECRAFT_SERVER_BUILD
repeatList = MemoryTracker::genLists(1);
#endif
destroyProgress = 0.0f;
totalChunks= offscreenChunks= occludedChunks= renderedChunks= emptyChunks = 0;
@ -171,7 +172,7 @@ LevelRenderer::LevelRenderer(Minecraft *mc, Textures *textures)
this->mc = mc;
this->textures = textures;
#ifndef MINECRAFT_SERVER_BUILD
chunkLists = MemoryTracker::genLists(getGlobalChunkCount() * CHUNK_RENDER_LAYERS); // One render list per chunk render layer.
globalChunkFlags = new unsigned char[getGlobalChunkCount()];
memset(globalChunkFlags, 0, getGlobalChunkCount());
@ -261,6 +262,7 @@ LevelRenderer::LevelRenderer(Minecraft *mc, Textures *textures)
t->end();
glEndList();
}
#endif
Chunk::levelRenderer = this;
@ -536,6 +538,7 @@ void LevelRenderer::allChanged(int playerIndex)
void LevelRenderer::renderEntities(Vec3 *cam, Culler *culler, float a)
{
#ifndef MINECRAFT_SERVER_BUILD
if (mc == nullptr || mc->player == nullptr)
{
return;
@ -662,6 +665,7 @@ void LevelRenderer::renderEntities(Vec3 *cam, Culler *culler, float a)
LeaveCriticalSection(&m_csRenderableTileEntities);
mc->gameRenderer->turnOffLightLayer(a); // 4J - brought forward from 1.8.2
#endif
}
wstring LevelRenderer::gatherStats1()
@ -3960,7 +3964,9 @@ int LevelRenderer::rebuildChunkThreadProc(LPVOID lpParam)
AABB::CreateNewThreadStorage();
IntCache::CreateNewThreadStorage();
Tesselator::CreateNewThreadStorage(1024*1024);
#ifndef MINECRAFT_SERVER_BUILD
RenderManager.InitialiseContext();
#endif
Chunk::CreateNewThreadStorage();
Tile::CreateNewThreadStorage();

View file

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

View file

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

View file

@ -141,8 +141,10 @@ Minecraft::Minecraft(Component *mouseComponent, Canvas *parent, MinecraftApplet
user = nullptr;
parent = nullptr;
pause = false;
#ifndef MINECRAFT_SERVER_BUILD
textures = nullptr;
font = nullptr;
#endif
screen = nullptr;
localPlayerIdx = 0;
rightClickDelay = 0;
@ -151,8 +153,9 @@ Minecraft::Minecraft(Component *mouseComponent, Canvas *parent, MinecraftApplet
InitializeCriticalSection( &ProgressRenderer::s_progress );
InitializeCriticalSection(&m_setLevelCS);
//m_hPlayerRespawned = CreateEvent(nullptr, FALSE, FALSE, nullptr);
#ifndef MINECRAFT_SERVER_BUILD
progressRenderer = nullptr;
#endif
gameRenderer = nullptr;
bgLoader = nullptr;
@ -166,8 +169,12 @@ Minecraft::Minecraft(Component *mouseComponent, Canvas *parent, MinecraftApplet
orgWidth = orgHeight = 0;
achievementPopup = new AchievementPopup(this);
gui = nullptr;
#ifndef MINECRAFT_SERVER_BUILD
noRender = false;
humanoidModel = new HumanoidModel(0);
#else
noRender = true;
#endif
hitResult = nullptr;
options = nullptr;
soundEngine = new SoundEngine();
@ -338,12 +345,13 @@ void Minecraft::init()
options = new Options(this, workingDirectory);
skins = new TexturePackRepository(workingDirectory, this);
skins->addDebugPacks();
#ifndef MINECRAFT_SERVER_BUILD
textures = new Textures(skins, options);
//renderLoadingScreen();
font = new Font(options, L"font/Default.png", textures, false, &DEFAULT_FONT_LOCATION, 23, 20, 8, 8, SFontData::Codepoints);
altFont = new Font(options, L"font/alternate.png", textures, false, &ALT_FONT_LOCATION, 16, 16, 8, 8);
#endif
//if (options.languageCode != null) {
// Language.getInstance().loadLanguage(options.languageCode);
// // font.setEnforceUnicodeSheet("true".equalsIgnoreCase(I18n.get("language.enforceUnicode")));
@ -357,7 +365,9 @@ void Minecraft::init()
//FoliageColor::init(textures->loadTexturePixels(L"misc/foliagecolor.png"));
gameRenderer = new GameRenderer(this);
#ifndef MINECRAFT_SERVER_BUILD
EntityRenderDispatcher::instance->itemInHandRenderer = new ItemInHandRenderer(this,false);
#endif
for( int i=0 ; i<4 ; ++i )
stats[i] = new StatsCounter();
@ -384,6 +394,7 @@ void Minecraft::init()
e.printStackTrace();
}
#endif
#ifndef MINECRAFT_SERVER_BUILD
MemSect(31);
checkGlError(L"Pre startup");
@ -407,12 +418,17 @@ void Minecraft::init()
MemSect(31);
checkGlError(L"Startup");
MemSect(0);
#endif
// openGLCapabilities = new OpenGLCapabilities(); // 4J - removed
#ifndef MINECRAFT_SERVER_BUILD
levelRenderer = new LevelRenderer(this, textures);
#else
levelRenderer = new LevelRenderer(this, nullptr);
#endif
//textures->register(&TextureAtlas::LOCATION_BLOCKS, new TextureAtlas(Icon::TYPE_TERRAIN, TN_TERRAIN));
//textures->register(&TextureAtlas::LOCATION_ITEMS, new TextureAtlas(Icon::TYPE_ITEM, TN_GUI_ITEMS));
#ifndef MINECRAFT_SERVER_BUILD
textures->stitch();
glViewport(0, 0, width, height);
@ -424,6 +440,7 @@ void Minecraft::init()
MemSect(0);
gui = new Gui(this);
if (connectToIp != L"") // 4J - was nullptr comparison
{
// setScreen(new ConnectScreen(this, connectToIp, connectToPort)); // 4J TODO - put back in
@ -435,6 +452,7 @@ void Minecraft::init()
progressRenderer = new ProgressRenderer(this);
RenderManager.CBuffLockStaticCreations();
#endif
}
void Minecraft::renderLoadingScreen()
@ -508,9 +526,10 @@ LevelStorageSource *Minecraft::getLevelSource()
void Minecraft::setScreen(Screen *screen)
{
if (this->screen != nullptr)
Screen *oldScreen = this->screen;
if (oldScreen != nullptr)
{
this->screen->removed();
oldScreen->removed();
}
#ifdef _WINDOWS64
@ -1250,6 +1269,8 @@ void Minecraft::applyFrameMouseLook()
void Minecraft::run_middle()
{
pause = app.IsAppPaused();
static int64_t lastTime = 0;
static bool bFirstTimeIntoGame = true;
static bool bAutosaveTimerSet=false;
@ -1262,11 +1283,14 @@ void Minecraft::run_middle()
if(running)
{
#ifndef MINECRAFT_SERVER_BUILD
if (reloadTextures)
{
reloadTextures = false;
textures->reloadAll();
}
#endif
//while (running)
{
@ -2340,13 +2364,18 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
// soundEngine.playMusicTick();
if (!pause && level != nullptr) gameMode->tick();
#ifndef MINECRAFT_SERVER_BUILD
MemSect(31);
glBindTexture(GL_TEXTURE_2D, textures->loadTexture(TN_TERRAIN)); //L"/terrain.png"));
MemSect(0);
#endif
if( bFirst )
{
PIXBeginNamedEvent(0,"Texture tick");
#ifndef MINECRAFT_SERVER_BUILD
if (!pause) textures->tick(bUpdateTextures);
#endif
PIXEndNamedEvent();
}
@ -4360,12 +4389,13 @@ void Minecraft::setLevel(MultiPlayerLevel *level, int message /*=-1*/, shared_pt
EnterCriticalSection(&m_setLevelCS);
bool playerAdded = false;
this->cameraTargetPlayer = nullptr;
#ifdef MINECRAFT_SERVER_BUILD
if(progressRenderer != nullptr)
{
this->progressRenderer->progressStart(message);
this->progressRenderer->progressStage(-1);
}
#endif
// Stop menu music and transition to game music for the new level
soundEngine->playStreaming(L"", 0, 0, 0, 1, 1);
@ -4409,6 +4439,8 @@ void Minecraft::setLevel(MultiPlayerLevel *level, int message /*=-1*/, shared_pt
// 4J If we are setting the level to nullptr then we are exiting, so delete the levels
if( level == nullptr )
{
if (soundEngine) soundEngine->stopElytraSound();
if(levels[0]!=nullptr)
{
delete levels[0];
@ -4588,11 +4620,14 @@ void Minecraft::setLevel(MultiPlayerLevel *level, int message /*=-1*/, shared_pt
void Minecraft::prepareLevel(int title)
{
#ifndef MINECRAFT_SERVER_BUILD
if(progressRenderer != nullptr)
{
this->progressRenderer->progressStart(title);
this->progressRenderer->progressStage(IDS_PROGRESS_BUILDING_TERRAIN);
}
#endif
int r = 128;
if (gameMode->isCutScene()) r = 64;
int pp = 0;
@ -4616,7 +4651,7 @@ void Minecraft::prepareLevel(int title)
spcc->centerOn(spawnPos->x >> 4, spawnPos->z >> 4);
}
#endif
#ifndef MINECRAFT_SERVER_BUILD
for (int x = -r; x <= r; x += 16)
{
for (int z = -r; z <= r; z += 16)
@ -4632,7 +4667,8 @@ void Minecraft::prepareLevel(int title)
{
if(progressRenderer != nullptr) this->progressRenderer->progressStage(IDS_PROGRESS_SIMULATING_WORLD);
max = 2000;
}
}
#endif
}
wstring Minecraft::gatherStats1()
@ -4892,8 +4928,10 @@ void Minecraft::main()
useLomp = true;
MinecraftWorld_RunStaticCtors();
#ifndef MINECRAFT_SERVER_BUILD
EntityRenderDispatcher::staticCtor();
TileEntityRenderDispatcher::staticCtor();
#endif
User::staticCtor();
Tutorial::staticCtor();
ColourTable::staticCtor();

View file

@ -559,8 +559,10 @@ MinecraftServer::MinecraftServer()
m_bLoaded = false;
stopped = false;
tickCount = 0;
#ifndef MINECRAFT_SERVER_BUILD
wstring progressStatus;
progress = 0;
#endif
motd = L"";
m_isServerPaused = false;
@ -736,8 +738,10 @@ bool MinecraftServer::initServer(int64_t seed, NetworkGameInitData *initData, DW
pLevelType = LevelType::lvl_normal;
}
#ifndef MINECRAFT_SERVER_BUILD
ProgressRenderer *mcprogress = Minecraft::GetInstance()->progressRenderer;
mcprogress->progressStart(IDS_PROGRESS_INITIALISING_SERVER);
#endif
if( findSeed )
{
@ -876,7 +880,9 @@ void MinecraftServer::postProcessTerminate(ProgressRenderer *mcprogress)
if( postProcessItemCount )
{
#ifndef MINECRAFT_SERVER_BUILD
mcprogress->progressStagePercentage((postProcessItemCount - postProcessItemRemaining) * 100 / postProcessItemCount);
#endif
}
CompressedTileStorage::tick();
SparseLightStorage::tick();
@ -1030,7 +1036,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
players->setLevel(levels);
}
#ifndef MINECRAFT_SERVER_BUILD
if( levels[0]->isNew )
{
mcprogress->progressStage(IDS_PROGRESS_GENERATING_SPAWN_AREA);
@ -1039,6 +1045,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
{
mcprogress->progressStage(IDS_PROGRESS_LOADING_SPAWN_AREA);
}
#endif
app.SetGameHostOption( eGameHostOption_HasBeenInCreative, gameType == GameType::CREATIVE || levels[0]->getHasBeenInCreative() );
app.SetGameHostOption( eGameHostOption_Structures, levels[0]->isGenerateMapFeatures() );
@ -1151,7 +1158,12 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
{
delete spawnPos;
m_postUpdateTerminate = true;
#ifndef MINECRAFT_SERVER_BUILD
postProcessTerminate(mcprogress);
#else
postProcessTerminate(nullptr);
#endif
return false;
}
// printf(">>>%d %d %d\n",i,x,z);
@ -1161,7 +1173,9 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
{
int pos = (x + r) * twoRPlusOne + (z + 1);
// setProgress(L"Preparing spawn area", (pos) * 100 / total);
#ifndef MINECRAFT_SERVER_BUILD
mcprogress->progressStagePercentage((pos+r) * 100 / total);
#endif
// lastTime = now;
}
static int count = 0;
@ -1203,7 +1217,11 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
// Wait for post processing, then lighting threads, to end (post-processing may make more lighting changes)
m_postUpdateTerminate = true;
#ifndef MINECRAFT_SERVER_BUILD
postProcessTerminate(mcprogress);
#else
postProcessTerminate(nullptr);
#endif
// stronghold position?
@ -1245,14 +1263,22 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
if( levels[1]->isNew )
{
#ifndef MINECRAFT_SERVER_BUILD
levels[1]->save(true, mcprogress);
#else
levels[1]->save(true, nullptr);
#endif
}
if( s_bServerHalted || !g_NetworkManager.IsInSession() ) return false;
if( levels[2]->isNew )
{
#ifndef MINECRAFT_SERVER_BUILD
levels[2]->save(true, mcprogress);
#else
levels[2]->save(true, nullptr);
#endif
}
if( s_bServerHalted || !g_NetworkManager.IsInSession() ) return false;
@ -1264,7 +1290,11 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
if( levels[0]->isNew )
{
#ifndef MINECRAFT_SERVER_BUILD
levels[0]->save(true, mcprogress);
#else
levels[0]->save(true, nullptr);
#endif
}
if( s_bServerHalted || !g_NetworkManager.IsInSession() ) return false;
@ -1366,15 +1396,19 @@ void MinecraftServer::overwriteHellBordersForNewWorldSize(ServerLevel* level, in
void MinecraftServer::setProgress(const wstring& status, int progress)
{
#ifndef MINECRAFT_SERVER_BUILD
progressStatus = status;
this->progress = progress;
#endif
// logger.info(status + ": " + progress + "%");
}
void MinecraftServer::endProgress()
{
#ifndef MINECRAFT_SERVER_BUILD
progressStatus = L"";
this->progress = 0;
#endif
}
void MinecraftServer::saveAllChunks()
@ -1392,8 +1426,11 @@ void MinecraftServer::saveAllChunks()
ServerLevel *level = levels[levels.length - 1 - i];
if( level ) // 4J - added check as level can be nullptr if we end up in stopServer really early on due to network failure
{
#ifndef MINECRAFT_SERVER_BUILD
level->save(true, Minecraft::GetInstance()->progressRenderer);
#else
level->save(true, nullptr);
#endif
// Only close the level storage when we have saved the last level, otherwise we need to recreate the region files
// when saving the next levels
if( i == (levels.length - 1))
@ -1524,7 +1561,11 @@ void MinecraftServer::stopServer(bool didInit)
{
if (players != nullptr)
{
#ifndef MINECRAFT_SERVER_BUILD
players->saveAll(Minecraft::GetInstance()->progressRenderer, true);
#else
players->saveAll(nullptr, true);
#endif
}
// 4J Stu - Save the levels in reverse order so we don't overwrite the level.dat
// with the data from the nethers leveldata.
@ -1542,7 +1583,11 @@ void MinecraftServer::stopServer(bool didInit)
app.m_gameRules.unloadCurrentGameRules();
if( levels[0] != nullptr ) // This can be null if stopServer happens very quickly due to network error
{
#ifndef MINECRAFT_SERVER_BUILD
levels[0]->saveToDisc(Minecraft::GetInstance()->progressRenderer, false);
#else
levels[0]->saveToDisc(nullptr, false);
#endif
}
}
}
@ -1803,7 +1848,7 @@ void MinecraftServer::run(int64_t seed, void *lpParameter)
lastTime = now;
// 4J Added ability to pause the server
if( !m_isServerPaused )
if( !m_isServerPaused && !app.IsAppPaused() )
{
bool didTick = false;
if (levels[0]->allPlayersAreSleeping())
@ -1972,7 +2017,11 @@ void MinecraftServer::run(int64_t seed, void *lpParameter)
QueryPerformanceCounter(&asAfterRules);
#endif
#ifdef MINECRAFT_SERVER_BUILD
levels[0]->saveToDisc(nullptr, true);
#else
levels[0]->saveToDisc(Minecraft::GetInstance()->progressRenderer, true);
#endif
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
QueryPerformanceCounter(&asAfterFlush);
@ -2005,7 +2054,11 @@ void MinecraftServer::run(int64_t seed, void *lpParameter)
app.EnterSaveNotificationSection();
if (players != nullptr)
{
players->saveAll(Minecraft::GetInstance()->progressRenderer);
#ifndef MINECRAFT_SERVER_BUILD
players->saveAll(Minecraft::GetInstance()->progressRenderer);
#else
players->saveAll(nullptr);
#endif
}
players->broadcastAll(std::make_shared<UpdateProgressPacket>(20));
@ -2017,7 +2070,11 @@ void MinecraftServer::run(int64_t seed, void *lpParameter)
// with the data from the nethers leveldata.
// Fix for #7418 - Functional: Gameplay: Saving after sleeping in a bed will place player at nighttime when restarting.
ServerLevel *level = levels[levels.length - 1 - j];
#ifndef MINECRAFT_SERVER_BUILD
level->save(true, Minecraft::GetInstance()->progressRenderer, (eAction==eXuiServerAction_AutoSaveGame));
#else
level->save(true, nullptr, (eAction == eXuiServerAction_AutoSaveGame));
#endif
players->broadcastAll(std::make_shared<UpdateProgressPacket>(33 + (j * 33)));
}
@ -2025,7 +2082,11 @@ void MinecraftServer::run(int64_t seed, void *lpParameter)
{
saveGameRules();
levels[0]->saveToDisc(Minecraft::GetInstance()->progressRenderer, (eAction==eXuiServerAction_AutoSaveGame));
#ifndef MINECRAFT_SERVER_BUILD
levels[0]->saveToDisc(Minecraft::GetInstance()->progressRenderer, (eAction == eXuiServerAction_AutoSaveGame));
#else
levels[0]->saveToDisc(nullptr, (eAction == eXuiServerAction_AutoSaveGame));
#endif
}
app.LeaveSaveNotificationSection();
break;

View file

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

View file

@ -8,15 +8,18 @@
#include "../Minecraft.World/net.minecraft.world.level.saveddata.h"
#include "../Minecraft.World/net.minecraft.world.level.material.h"
#ifndef MINECRAFT_SERVER_BUILD
#ifdef __ORBIS__
short Minimap::LUT[256]; // 4J added
#else
int Minimap::LUT[256]; // 4J added
#endif
bool Minimap::genLUT = true; // 4J added
#endif
Minimap::Minimap(Font *font, Options *options, Textures *textures, bool optimised)
{
#ifndef MINECRAFT_SERVER_BUILD
#ifdef __PS3__
// we're using the RSX now to upload textures to vram, so we need the main ram textures allocated from io space
this->pixels = intArray((int*)RenderManager.allocIOMem(w*h*sizeof(int)), 16*16);
@ -39,7 +42,6 @@ Minimap::Minimap(Font *font, Options *options, Textures *textures, bool optimise
{
pixels[i] = 0x00000000;
}
// 4J added - generate the colour mapping that we'll be needing as a LUT to minimise processing we actually need to do during normal rendering
if( genLUT )
{
@ -47,10 +49,13 @@ Minimap::Minimap(Font *font, Options *options, Textures *textures, bool optimise
}
renderCount = 0; // 4J added
m_optimised = optimised;
#endif
}
void Minimap::reloadColours()
{
#ifndef MINECRAFT_SERVER_BUILD
ColourTable *colourTable = Minecraft::GetInstance()->getColourTable();
// 4J note that this code has been extracted pretty much as it was in Minimap::render, although with some byte order changes
for( int i = 0; i < (14 * 4); i++ ) // 14 material colours currently, 4 brightnesses of each
@ -95,11 +100,13 @@ void Minimap::reloadColours()
}
genLUT = false;
#endif
}
// 4J added entityId
void Minimap::render(shared_ptr<Player> player, Textures *textures, shared_ptr<MapItemSavedData> data, int entityId)
{
#ifndef MINECRAFT_SERVER_BUILD
// 4J - only update every 8 renders, as an optimisation
// We don't want to use this for ItemFrame renders of maps, as then we can't have different maps together
if( !m_optimised || ( renderCount & 7 ) == 0 )
@ -252,5 +259,6 @@ void Minimap::render(shared_ptr<Player> player, Textures *textures, shared_ptr<M
}
//#endif
glPopMatrix();
#endif
}

View file

@ -11,6 +11,8 @@ class Minimap
private:
static const int w = MapItem::IMAGE_WIDTH;
static const int h = MapItem::IMAGE_HEIGHT;
#ifndef MINECRAFT_SERVER_BUILD
#ifdef __ORBIS__
static short LUT[256]; // 4J added
#else
@ -19,6 +21,7 @@ private:
static bool genLUT; // 4J added
int renderCount; // 4J added
bool m_optimised; // 4J Added
#ifdef __ORBIS__
shortArray pixels;
#else
@ -27,6 +30,7 @@ private:
int mapTexture;
Options *options;
Font *font;
#endif
public:
Minimap(Font *font, Options *options, Textures *textures, bool optimised = true); // 4J Added optimised param

View file

@ -38,6 +38,17 @@
// 4J Added
#include "../Minecraft.World/net.minecraft.world.item.crafting.h"
#include "Options.h"
//neo: Command Includes
#include "TeleportCommand.h"
#include "../Minecraft.World/GiveItemCommand.h"
#include "../Minecraft.World/TimeCommand.h"
#include "../Minecraft.World/KillCommand.h"
#include "../Minecraft.World/GameModeCommand.h"
#include "../Minecraft.World/ToggleDownfallCommand.h"
#include <sstream>
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
#include "../Minecraft.Server/ServerLogManager.h"
#include "../Minecraft.Server/Access/Access.h"
@ -48,6 +59,10 @@
extern bool g_Win64DedicatedServer;
#endif
//neo: added
#include "ItemNameMap.h"
#include "../Minecraft.World/ByteArrayOutputStream.h"
namespace
{
// Anti-cheat thresholds. Keep server-side checks authoritative even in host mode.
@ -168,7 +183,7 @@ void PlayerConnection::tick()
// Ensure server-side player tick runs even when no move packet was received this tick.
// Without this, environmental damage (drowning, fire, lava) is never applied to clients
// that don't send frequent move packets.
if (!didTick && player != nullptr)
if (!didTick && player != nullptr && !server->IsServerPaused() && !app.IsAppPaused())
{
player->doTick(false);
}
@ -1026,10 +1041,377 @@ void PlayerConnection::handleCommand(const wstring& message)
if (FourKitBridge::HandlePlayerCommand(player->entityId, commandLine))
return;
#endif
// 4J - TODO
#if 0
server.getCommandDispatcher().performCommand(player, message);
#endif
wstringstream ss(message.substr(1));
wstring cmd;
ss >> cmd;
if (cmd == L"tp" || cmd == L"teleport")
{
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_Teleport))
{
warn(L"You do not have permission to use this command.");
return;
}
wstring arg1, arg2, arg3, arg4, arg5, arg6;
ss >> arg1 >> arg2 >> arg3 >> arg4 >> arg5 >> arg6;
shared_ptr<ServerPlayer> target;
shared_ptr<ServerPlayer> destination;
if (arg1.empty())
{
warn(L"Usage: /tp [player] <target_player>");
warn(L"Usage: /tp [player] <x> <y> <z> [y_rot] [x_rot]");
return;
}
auto isCoord = [](const wstring& s) -> bool {
if (s.empty()) return false;
for (size_t i = 0; i < s.size(); i++)
if (!iswdigit(s[i]) && s[i] != L'-' && s[i] != L'.') return false;
return true;
};
bool arg2IsCoord = isCoord(arg2);
if (!arg2IsCoord && !arg2.empty())
{
target = server->getPlayers()->getPlayer(arg1);
destination = server->getPlayers()->getPlayer(arg2);
if (target && destination)
{
shared_ptr<GameCommandPacket> packet = TeleportCommand::preparePacket(
target->getXuid(), destination->getXuid());
server->getCommandDispatcher()->performCommand(
player, eGameCommand_Teleport, packet->data);
}
else
{
warn(L"Player not found.");
}
}
else
{
wstring sx, sy, sz, sYRot, sXRot;
shared_ptr<ServerPlayer> tpTarget;
if (arg2IsCoord)
{
tpTarget = player;
sx = arg1;
sy = arg2;
sz = arg3;
sYRot = arg4;
sXRot = arg5;
}
else
{
tpTarget = server->getPlayers()->getPlayer(arg1);
sx = arg2;
sy = arg3;
sz = arg4;
sYRot = arg5;
sXRot = arg6;
}
if (!tpTarget)
{
warn(L"Player not found.");
return;
}
if (sx.empty() || sy.empty() || sz.empty())
{
warn(L"Usage: /tp [player] <x> <y> <z> [y_rot] [x_rot]");
return;
}
float x = stof(sx);
float y = stof(sy);
float z = stof(sz);
byte yRot = sYRot.empty()
? static_cast<byte>(tpTarget->yRot)
: static_cast<byte>(stoi(sYRot) & 0xFF);
byte xRot = sXRot.empty()
? static_cast<byte>(tpTarget->xRot)
: static_cast<byte>(stoi(sXRot) & 0xFF);
shared_ptr<GameCommandPacket> gamePacket = TeleportCommand::preparePacket(
tpTarget->getXuid(), x, y, z, yRot, xRot);
server->getCommandDispatcher()->performCommand(tpTarget, eGameCommand_Teleport, gamePacket->data);
}
} else if (cmd == L"time")
{
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_Time))
{
warn(L"You do not have permission to use this command.");
return;
}
wstring action;
ss >> action;
if (action.empty())
{
warn(L"Usage: /time <set|add|query> ...");
warn(L" /time set <day|night|noon|midnight|sunrise|sunset|0-24000>");
warn(L" /time add <amount>");
warn(L" /time query <daytime|gametime|day>");
return;
}
if (action == L"set")
{
wstring timeVal;
ss >> timeVal;
if (timeVal.empty())
{
warn(L"Usage: /time set <day|night|noon|midnight|sunrise|sunset|0-24000>");
return;
}
static const unordered_map<wstring, int> namedTimes = {
{ L"day", 1000 },
{ L"noon", 6000 },
{ L"sunset", 12000 },
{ L"night", 13000 },
{ L"midnight", 18000 },
{ L"sunrise", 23000 },
};
int ticks = -1;
auto it = namedTimes.find(timeVal);
if (it != namedTimes.end())
{
ticks = it->second;
}
else
{
try {
size_t pos;
ticks = stoi(timeVal, &pos);
if (pos != timeVal.size() || ticks < 0 || ticks > 24000)
{
warn(L"Time value must be between 0 and 24000, or a named time.");
return;
}
}
catch (...) {
warn(L"Unknown time value: " + timeVal);
warn(L"Usage: /time set <day|night|noon|midnight|sunrise|sunset|0-24000>");
return;
}
}
shared_ptr<GameCommandPacket> packet = TimeCommand::preparePacket(ticks);
server->getCommandDispatcher()->performCommand(player, eGameCommand_Time, packet->data);
info(L"Time set to " + timeVal + L" (" + to_wstring(ticks) + L" ticks).");
}
else if (action == L"add")
{
wstring amountStr;
ss >> amountStr;
if (amountStr.empty())
{
warn(L"Usage: /time add <amount>");
return;
}
try {
size_t pos;
int amount = stoi(amountStr, &pos);
if (pos != amountStr.size() || amount < 1)
{
warn(L"Amount must be a positive integer.");
return;
}
int currentTicks = server->getCommandSenderWorld()->getTimeOfDay(0) * 1000;
int newTicks = (currentTicks + amount) % 24000;
shared_ptr<GameCommandPacket> packet = TimeCommand::preparePacket(newTicks);
server->getCommandDispatcher()->performCommand(player, eGameCommand_Time, packet->data);
info(L"Added " + to_wstring(amount) + L" ticks. Time is now " + to_wstring(newTicks) + L".");
}
catch (...) {
warn(L"Invalid amount: " + amountStr);
}
}
else if (action == L"query")
{
wstring queryType;
ss >> queryType;
if (queryType.empty())
{
warn(L"Usage: /time query <daytime|gametime|day>");
return;
}
int currentTicks = server->getCommandSenderWorld()->getTimeOfDay(0) * 1000;
if (queryType == L"daytime")
{
info(L"The current daytime is " + to_wstring(currentTicks % 24000) + L" ticks.");
}
else if (queryType == L"gametime")
{
info(L"The total game time is " + to_wstring(currentTicks) + L" ticks.");
}
else if (queryType == L"day")
{
info(L"The current day is " + to_wstring(currentTicks / 24000) + L".");
}
else
{
warn(L"Unknown query type: " + queryType);
warn(L"Usage: /time query <daytime|gametime|day>");
}
}
else
{
warn(L"Unknown action: " + action);
warn(L"Usage: /time <set|add|query> ...");
}
}
else if (cmd == L"kill")
{
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_Kill))
{
warn(L"You do not have permission to use this command.");
return;
}
wstring targetName;
ss >> targetName;
if (targetName.empty())
{
server->getCommandDispatcher()->performCommand(player, eGameCommand_Kill, byteArray());
}
else
{
ByteArrayOutputStream baos;
DataOutputStream dos(&baos);
dos.writeUTF(targetName);
byteArray data = baos.toByteArray();
server->getCommandDispatcher()->performCommand(player, eGameCommand_Kill, data);
}
}
else if (cmd == L"toggledownfall")
{
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_ToggleDownfall))
{
warn(L"You do not have permission to use this command.");
return;
}
shared_ptr<GameCommandPacket> packet = ToggleDownfallCommand::preparePacket();
server->getCommandDispatcher()->performCommand(player, eGameCommand_ToggleDownfall, packet->data);
} else if (cmd == L"gamemode") {
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_GameMode))
{
warn(L"You do not have permission to use this command.");
return;
}
wstring modeStr, targetName;
ss >> modeStr >> targetName;
if (modeStr.empty()) {
warn(L"Usage: /gamemode <mode> [player]");
return;
}
int mode = -1;
if (modeStr == L"0" || modeStr == L"s" || modeStr == L"survival")
mode = 0;
else if (modeStr == L"1" || modeStr == L"c" || modeStr == L"creative")
mode = 1;
else if (modeStr == L"2" || modeStr == L"a" || modeStr == L"adventure")
mode = 2;
else {
warn(L"Unknown game mode: " + modeStr);
return;
}
shared_ptr<ServerPlayer> target;
if (targetName.empty()) {
target = player;
} else {
target = server->getPlayers()->getPlayer(targetName);
if (!target) {
warn(L"Player not found: " + targetName);
return;
}
}
shared_ptr<GameCommandPacket> packet = GameModeCommand::preparePacket(target, mode);
server->getCommandDispatcher()->performCommand(player, eGameCommand_GameMode, packet->data);
} else if (cmd == L"give") {
if (!app.GetGameHostOption(eGameHostOption_CheatsEnabled))
{
warn(L"Cheats are not enabled on this server.");
return;
}
if (!player->hasPermission(eGameCommand_Give))
{
warn(L"You do not have permission to use this command.");
return;
}
wstring targetName, itemStr, amountStr, auxStr;
ss >> targetName >> itemStr >> amountStr >> auxStr;
if (targetName.empty() || itemStr.empty()) {
warn(L"Usage: /give <player> <item_id>|minecraft:<item_name> [amount] [data]");
return;
}
shared_ptr<ServerPlayer> target = server->getPlayers()->getPlayer(targetName);
if (!target) {
warn(L"Player not found: " + targetName);
return;
}
int item = 0;
int amount = 1, aux = 0;
try {
item = itemStr.find(L"minecraft:") == 0 ? GetItemIdByName(itemStr.substr(10)) : std::stoi(itemStr);
if (!amountStr.empty()) amount = std::stoi(amountStr);
if (!auxStr.empty()) aux = std::stoi(auxStr);
} catch (...) {
warn(L"Invalid item ID/Name or amount");
return;
}
shared_ptr<GameCommandPacket> packet = GiveItemCommand::preparePacket(target, item, amount, aux);
server->getCommandDispatcher()->performCommand(player, eGameCommand_Give, packet->data);
}
}
void PlayerConnection::handleAnimate(shared_ptr<AnimatePacket> packet)
@ -1127,14 +1509,12 @@ int PlayerConnection::countDelayedPackets()
void PlayerConnection::info(const wstring& string)
{
// 4J-PB - removed, since it needs to be localised in the language the client is in
//send( shared_ptr<ChatPacket>( new ChatPacket(L"<22>7" + string) ) );
send( shared_ptr<ChatPacket>( new ChatPacket(L"§7" + string) ) );
}
void PlayerConnection::warn(const wstring& string)
{
// 4J-PB - removed, since it needs to be localised in the language the client is in
//send( shared_ptr<ChatPacket>( new ChatPacket(L"<22>9" + string) ) );
send( shared_ptr<ChatPacket>( new ChatPacket(L"§c" + string) ) );
}
wstring PlayerConnection::getConsoleName()
@ -1546,6 +1926,8 @@ void PlayerConnection::handleGameCommand(shared_ptr<GameCommandPacket> packet)
player->getName().c_str(), player->isModerator() ? 1 : 0, isHost ? 1 : 0,
static_cast<int>(packet->command));
#endif
MinecraftServer::getInstance()->getCommandDispatcher()->performCommand(player, packet->command, packet->data);
}
@ -2095,7 +2477,7 @@ void PlayerConnection::handleCustomPayload(shared_ptr<CustomPayloadPacket> custo
player->inventory->setItem(player->inventory->selected, sentItem);
}
}
else if (CustomPayloadPacket::QUICK_EQUIP_PACKET.compare(customPayloadPacket->identifier) == 0) {
/*else if (CustomPayloadPacket::QUICK_EQUIP_PACKET.compare(customPayloadPacket->identifier) == 0) {
//ByteArrayInputStream bais(customPayloadPacket->data);
//DataInputStream input(&bais);
//shared_ptr<ItemInstance> sentItem = Packet::readItem(&input);
@ -2126,7 +2508,7 @@ void PlayerConnection::handleCustomPayload(shared_ptr<CustomPayloadPacket> custo
//PlayerList* playerList = MinecraftServer::getInstance()->getPlayers();
//playerList->broadcastAll(std::make_shared<SetEquippedItemPacket>(player->entityId, slot, sentItem));
}
}*/
else if (CustomPayloadPacket::TRADER_SELECTION_PACKET.compare(customPayloadPacket->identifier) == 0)
{
ByteArrayInputStream bais(customPayloadPacket->data);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -19,89 +19,95 @@ EGameCommand TeleportCommand::getId()
void TeleportCommand::execute(shared_ptr<CommandSender> source, byteArray commandData)
{
ByteArrayInputStream bais(commandData);
DataInputStream dis(&bais);
ByteArrayInputStream bais(commandData);
DataInputStream dis(&bais);
byte flag = dis.readByte();
PlayerUID subjectID = dis.readPlayerUID();
PlayerList *players = MinecraftServer::getInstance()->getPlayerList();
shared_ptr<ServerPlayer> subject = players->getPlayer(subjectID);
if (subject == nullptr || !subject->isAlive())
return;
PlayerUID subjectID = dis.readPlayerUID();
PlayerUID destinationID = dis.readPlayerUID();
bais.reset();
if (flag == 1)
{
float x = dis.readFloat();
float y = dis.readFloat();
float z = dis.readFloat();
byte yRot = dis.readByte();
byte xRot = dis.readByte();
PlayerList *players = MinecraftServer::getInstance()->getPlayerList();
shared_ptr<ServerPlayer> subject = players->getPlayer(subjectID);
shared_ptr<ServerPlayer> destination = players->getPlayer(destinationID);
if(subject != nullptr && destination != nullptr && subject->level->dimension->id == destination->level->dimension->id && subject->isAlive() )
{
subject->ride(nullptr);
subject->ride(nullptr);
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
{
double outX, outY, outZ;
bool cancelled = FourKitBridge::FirePlayerTeleport(subject->entityId,
subject->x, subject->y, subject->z, subject->dimension,
destination->x, destination->y, destination->z, destination->dimension,
1 /* COMMAND */,
&outX, &outY, &outZ);
if (cancelled)
return;
subject->connection->teleport(outX, outY, outZ, destination->yRot, destination->xRot);
}
{
double outX, outY, outZ;
bool cancelled = FourKitBridge::FirePlayerTeleport(subject->entityId,
subject->x, subject->y, subject->z, subject->dimension,
x, y, z, subject->dimension,
1, &outX, &outY, &outZ);
if (cancelled)
return;
subject->connection->teleport(outX, outY, outZ, yRot, xRot);
}
#else
subject->connection->teleport(destination->x, destination->y, destination->z, destination->yRot, destination->xRot);
subject->connection->teleport(x, y, z, yRot, xRot);
#endif
//logAdminAction(source, "commands.tp.success", subject->getAName(), destination->getAName());
logAdminAction(source, ChatPacket::e_ChatCommandTeleportSuccess, subject->getName(), eTYPE_SERVERPLAYER, destination->getName());
logAdminAction(source, ChatPacket::e_ChatCommandTeleportSuccess, subject->getName(), eTYPE_SERVERPLAYER, subject->getName());
}
else
{
PlayerUID destinationID = dis.readPlayerUID();
shared_ptr<ServerPlayer> destination = players->getPlayer(destinationID);
if (destination == nullptr)
return;
if(subject == source)
{
destination->sendMessage(subject->getName(), ChatPacket::e_ChatCommandTeleportToMe);
}
else
{
subject->sendMessage(destination->getName(), ChatPacket::e_ChatCommandTeleportMe);
}
}
if (subject->level->dimension->id != destination->level->dimension->id)
return;
//if (args.length >= 1) {
// MinecraftServer server = MinecraftServer.getInstance();
// ServerPlayer victim;
// if (args.length == 2 || args.length == 4) {
// victim = server.getPlayers().getPlayer(args[0]);
// if (victim == null) throw new PlayerNotFoundException();
// } else {
// victim = (ServerPlayer) convertSourceToPlayer(source);
// }
// if (args.length == 3 || args.length == 4) {
// if (victim.level != null) {
// int pos = args.length - 3;
// int maxPos = Level.MAX_LEVEL_SIZE;
// int x = convertArgToInt(source, args[pos++], -maxPos, maxPos);
// int y = convertArgToInt(source, args[pos++], Level.minBuildHeight, Level.maxBuildHeight);
// int z = convertArgToInt(source, args[pos++], -maxPos, maxPos);
// victim.teleportTo(x + 0.5f, y, z + 0.5f);
// logAdminAction(source, "commands.tp.coordinates", victim.getAName(), x, y, z);
// }
// } else if (args.length == 1 || args.length == 2) {
// ServerPlayer destination = server.getPlayers().getPlayer(args[args.length - 1]);
// if (destination == null) throw new PlayerNotFoundException();
// victim.connection.teleport(destination.x, destination.y, destination.z, destination.yRot, destination.xRot);
// logAdminAction(source, "commands.tp.success", victim.getAName(), destination.getAName());
// }
//}
subject->ride(nullptr);
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
{
double outX, outY, outZ;
bool cancelled = FourKitBridge::FirePlayerTeleport(subject->entityId,
subject->x, subject->y, subject->z, subject->dimension,
destination->x, destination->y, destination->z, destination->dimension,
1, &outX, &outY, &outZ);
if (cancelled)
return;
subject->connection->teleport(outX, outY, outZ, destination->yRot, destination->xRot);
}
#else
subject->connection->teleport(destination->x, destination->y, destination->z, destination->yRot, destination->xRot);
#endif
logAdminAction(source, ChatPacket::e_ChatCommandTeleportSuccess, subject->getName(), eTYPE_SERVERPLAYER, destination->getName());
if (subject == source)
destination->sendMessage(subject->getName(), ChatPacket::e_ChatCommandTeleportToMe);
else
subject->sendMessage(destination->getName(), ChatPacket::e_ChatCommandTeleportMe);
}
}
shared_ptr<GameCommandPacket> TeleportCommand::preparePacket(PlayerUID subject, PlayerUID destination)
{
ByteArrayOutputStream baos;
DataOutputStream dos(&baos);
ByteArrayOutputStream baos;
DataOutputStream dos(&baos);
dos.writeByte(0);
dos.writePlayerUID(subject);
dos.writePlayerUID(destination);
return std::make_shared<GameCommandPacket>(eGameCommand_Teleport, baos.toByteArray());
}
dos.writePlayerUID(subject);
dos.writePlayerUID(destination);
return std::make_shared<GameCommandPacket>(eGameCommand_Teleport, baos.toByteArray());
//neo: added
shared_ptr<GameCommandPacket> TeleportCommand::preparePacket(PlayerUID subject, float x, float y, float z, byte yRot, byte xRot)
{
ByteArrayOutputStream baos;
DataOutputStream dos(&baos);
dos.writeByte(1);
dos.writePlayerUID(subject);
dos.writeFloat(x);
dos.writeFloat(y);
dos.writeFloat(z);
dos.writeByte(yRot);
dos.writeByte(xRot);
return std::make_shared<GameCommandPacket>(eGameCommand_Teleport, baos.toByteArray());
}

View file

@ -9,4 +9,7 @@ public:
virtual void execute(shared_ptr<CommandSender> source, byteArray commandData);
static shared_ptr<GameCommandPacket> preparePacket(PlayerUID subject, PlayerUID destination);
//neo: added
static shared_ptr<GameCommandPacket> preparePacket(PlayerUID subject, float x, float y, float z, byte yRot, byte xRot);
};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2962,23 +2962,23 @@ Can also be used for low-level lighting.</value>
</data>
<data name="IDS_TILE_OAKWOOD_PLANKS">
<value>Oak Wood Planks</value>
<value>Oak Planks</value>
</data>
<data name="IDS_TILE_SPRUCEWOOD_PLANKS">
<value>Spruce Wood Planks</value>
<value>Spruce Planks</value>
</data>
<data name="IDS_TILE_BIRCHWOOD_PLANKS">
<value>Birch Wood Planks</value>
<value>Birch Planks</value>
</data>
<data name="IDS_TILE_JUNGLE_PLANKS">
<value>Jungle Wood Planks</value>
<value>Jungle Planks</value>
</data>
<data name="IDS_TILE_PLANKS">
<value>Wood Planks (any type)</value>
<value>Planks (any type)</value>
</data>
<data name="IDS_TILE_SAPLING">
@ -8853,11 +8853,11 @@ All Ender Chests in a world are linked. Items placed into an Ender Chest are acc
</data>
<data name="IDS_TILE_ACACIA_PLANKS">
<value>Acacia Wood Planks</value>
<value>Acacia Planks</value>
</data>
<data name="IDS_TILE_DARK_OAK_PLANKS">
<value>Dark Oak Wood Planks</value>
<value>Dark Oak Planks</value>
</data>
<data name="IDS_TILE_STAIRS_ACACIAWOOD">
@ -9100,7 +9100,7 @@ All Ender Chests in a world are linked. Items placed into an Ender Chest are acc
</data>
<data name="IDS_ITEM_RABBIT_STEW">
<value>{*ICON_SHANK_01*}</value>
<value>Rabbit Stew</value>
</data>
<data name="IDS_TILE_DOUBLE_TALL_GRASS">
@ -9570,4 +9570,8 @@ All Ender Chests in a world are linked. Items placed into an Ender Chest are acc
<data name="IDS_ACHIEVEMENT_VIEW"><value>Hold {*CONTROLLER_VK_Y*} to view</value></data>
<data name="IDS_CHECKBOX_CLASSICCRAFTING"><value>Classic Crafting</value></data>
<data name="IDS_DESC_RABBIT_STEW">
<value>Restores 5{*ICON_SHANK_01*}.</value>
</data>
</root>

View file

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

View file

@ -488,39 +488,11 @@ int main(int argc, char **argv)
config.worldHellScale);
#endif
LogStartupStep("registering hidden window class");
HINSTANCE hInstance = GetModuleHandle(NULL);
MyRegisterClass(hInstance);
LogStartupStep("creating hidden window");
if (!InitInstance(hInstance, SW_HIDE))
{
LogError("startup", "Failed to create window instance.");
return 2;
}
ShowWindow(g_hWnd, SW_HIDE);
LogStartupStep("initializing graphics device wrappers");
if (FAILED(InitDevice()))
{
LogError("startup", "Failed to initialize D3D device.");
CleanupDevice();
return 2;
}
LogStartupStep("loading media/string tables");
app.loadMediaArchive();
RenderManager.Initialise(g_pd3dDevice, g_pSwapChain);
app.loadStringTable();
ui.init(g_pd3dDevice, g_pImmediateContext, g_pRenderTargetView, g_pDepthStencilView, g_iScreenWidth, g_iScreenHeight);
InputManager.Initialise(1, 3, MINECRAFT_ACTION_MAX, ACTION_MAX_MENU);
g_KBMInput.Init();
DefineActions();
InputManager.SetJoypadMapVal(0, 0);
InputManager.SetKeyRepeatRate(0.3f, 0.2f);
ProfileManager.Initialise(
TITLEID_MINECRAFT,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -273,4 +273,10 @@ void DataOutputStream::writePlayerUID(PlayerUID player)
#else
writeLong(player);
#endif // PS3
}
//neo: added
OutputStream* DataOutputStream::getChildOutputStream()
{
return stream;
}

View file

@ -35,4 +35,7 @@ public:
virtual void writeUTF(const wstring& a);
virtual void writePlayerUID(PlayerUID player);
virtual void flush();
//neo: added for future use cases, dont ask.
virtual OutputStream* getChildOutputStream();
};

View file

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

View file

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

View file

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

View file

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

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