Compare commits

..

541 commits

Author SHA1 Message Date
Frank
9be4311ca7 Version Bump, Minecraft 1.19.2 2022-08-07 14:14:17 +02:00
Frank
579f2a80ca [Feature] More Advancements 2022-08-01 00:14:44 +02:00
Frank
74faf97a93 [Feature] New Advancements 2022-07-31 23:51:01 +02:00
Frank
ed620a1c57 Fixed broken JSON 2022-07-31 19:44:34 +02:00
Frank
f9996d1dbc [Changes] Create recipe advancements for Infusion 2022-07-31 14:52:49 +02:00
Frank
6b193bfa63 EMI Defaults 2022-07-31 00:03:05 +02:00
Frank
19541a0ed0 Adopting BCLib EMI-API Changes 2022-07-29 11:10:05 +02:00
Frank
9db2ebb424 Asset License 2022-07-29 11:10:00 +02:00
Frank
321c94379d Allow Return-Gateways to span in our Biomes 2022-07-29 02:12:48 +02:00
Frank
89eb24ef04 Minecraft 1.19.1 for Issue-Form 2022-07-29 02:03:00 +02:00
Frank
85f288a30b Correct build-settings 2022-07-29 01:54:17 +02:00
Frank
32b581b903 Graphics Update 2022-07-29 01:51:35 +02:00
Frank
00f5fbdc46 Minor changes 2022-07-29 01:48:45 +02:00
Frank
c9b42aa843 Added Blasting Recipes for Endstone Smelter (quiqueck/BetterEnd#51) 2022-07-29 01:29:43 +02:00
Frank
fca6a6641b Added Infusion Recipes to EMI (quiqueck/BetterEnd#51) 2022-07-29 01:04:00 +02:00
Frank
59b4f5fb9a Improved Anvil-Level handling 2022-07-28 19:52:07 +02:00
Frank
e45eade668 [Change] Moved Alloying Recipes to BCLib 2022-07-28 18:30:53 +02:00
Frank
34d55debce Fixed compiler error 2022-07-27 00:34:19 +02:00
Frank
6eb31a9e88 Dependency Bump 2022-07-27 00:29:02 +02:00
Frank
e10a5680c5 [Fix] Charcoal Block uses new Fuel API to prevent Quilt from early generating an Empty Item (#41, QuiltMC/quilted-fabric-api#25) 2022-07-27 00:07:43 +02:00
Frank
a340de4adc [Fix] Enforce loading order (#41) 2022-07-26 21:40:18 +02:00
Frank
052f538444 Version Bump 2022-07-26 19:37:03 +02:00
Frank
d2b526970c [Feature] Test Support for EMI (#51) 2022-07-26 16:53:38 +02:00
Frank
d734b8b140 [Feature] partial Integration with JEI 2022-07-26 16:21:47 +02:00
Frank
0c3a152caf [Change] Added Updater icon 2022-07-26 14:35:14 +02:00
Frank
fe09d2a249 [Change] Different Mixin for Chorus model switch (will no longer show up in error logs tho) (#52) 2022-07-26 14:34:23 +02:00
Frank
c77d9678e0 Added Updater Icon 2022-07-22 18:39:06 +02:00
Frank
b4c163e293 Added Updater Icon 2022-07-22 18:38:54 +02:00
Frank
c2fba34de7 Some fixes 2022-07-22 01:28:55 +02:00
Frank
746315b5c1 Dependency Bump 2022-07-21 14:04:38 +02:00
Frank
76a0b299b2 [Change] Use static Tick function for elytra 2022-07-21 14:04:01 +02:00
Frank
620633046a [Feature] Thai Translation (by "I'm waiting") 2022-07-21 13:39:21 +02:00
Frank
c8e80bf1cf Do not used Deprecated API 2022-07-21 13:29:30 +02:00
Frank
eb3aeef901 Use moved ColorUtil 2022-07-17 02:39:18 +02:00
Frank
060019ee8e Dependency Bump 2022-07-17 02:20:27 +02:00
Frank
3be1721ce5 [Change] Flag for 1.19.1 2022-07-13 17:25:01 +02:00
Frank
a9d10350c8 Version/Dependency Bump 2022-07-12 16:42:40 +02:00
Frank
4cc52c2616 Version Bump 2022-07-12 12:15:17 +02:00
Frank
930dcbd4ee [Fix] EndStoneSmelterMenu Whisperer Menu initialized in Client-Only Code. Crashing Servers when players open Whisperer Screen (#38) 2022-07-12 12:10:59 +02:00
Frank
d3507b212e [Fix] EndStoneSmelterMenu was flagged as client only (#38) 2022-07-12 09:08:55 +02:00
Frank
4920da49a0 Version Bump 2022-07-11 23:15:14 +02:00
Frank
2148db6ea4 Removed duplicate file 2022-07-11 22:52:25 +02:00
Frank
03773ccc3f [Fix] MixinArmorFeatureRenderer stability improvements (#36) 2022-07-11 17:30:29 +02:00
Frank
9360da1518 Some deprecation fixes 2022-07-11 00:11:32 +02:00
Frank
6c60f422c8 [Change] Restored BYG Integration Biomes 2022-07-11 00:09:51 +02:00
Frank
de7b6afb5d [Change] Bring back parts of BYG integration 2022-07-10 23:31:24 +02:00
Frank
a6ad8b689f [Change] Vanilla like EndStone Smelter Behaviour with Hoppers (#30) 2022-07-10 23:09:52 +02:00
Frank
f6df2a2504 [Fix] EndStone Smelter destroys result item when recipe is clicked in book 2022-07-10 22:42:22 +02:00
Frank
3694bf1eee [Fix] Lazy loading of ScreenHandler after registry was already frozen (#35) 2022-07-10 18:07:30 +02:00
Frank
9d2ed61413 Dependency Update 2022-07-10 03:52:52 +02:00
Frank
4d866cc78a [Change] No special case for BetterEnd in BiomeSource 2022-07-10 03:49:01 +02:00
Frank
4607536c67 Bump Version 2022-07-10 02:40:33 +02:00
Frank
5cbccb1387 Removed promenade debug logging 2022-07-10 00:26:49 +02:00
Frank
09aca11883 Make sure the end land picker is high priority 2022-07-10 00:26:35 +02:00
Frank
e0ad076de5 Added Back Biome-Check for Cave Features 2022-07-09 22:54:23 +02:00
Frank
faa94911ef Some value balancing for blossoming spires 2022-07-09 05:19:15 +02:00
Frank
fac94c6f31 Serialize Surface rules in Biomes 2022-07-09 05:12:33 +02:00
Frank
f6ad608c53 Dependency Update 2022-07-08 13:03:42 +02:00
Frank
4664a819b3 [Fix] Endless recursion in Infusion Ritual (#31) 2022-07-08 11:02:44 +02:00
Frank
77a71cb746 Fixed CaveBiome Codecs 2022-07-08 00:13:59 +02:00
Frank
3f3454e634 [Feature] More flexible/extensible End-Biome Placement 2022-07-08 00:12:39 +02:00
Frank
c695e0af5e Serialize Cave Features 2022-07-07 19:33:55 +02:00
Frank
883a809ed0 Updated Dependency 2022-07-07 19:05:44 +02:00
Frank
015e0969a9 [Change] BCLBiome Data is managed in a Datapack-Aware registry now 2022-07-07 18:53:08 +02:00
Frank
a1175480b3 [Change] removed some deprecated api calls 2022-07-05 20:09:06 +02:00
Frank
19add56099 This should no longer be needed 2022-07-05 19:14:23 +02:00
Frank
f679e5241b [Fix] Cave Biomes should never get added to a picker 2022-07-03 23:29:02 +02:00
Frank
87d6aab4f9 Version Update 2022-07-03 12:50:02 +02:00
Frank
8803444b12 [Change] Adopting BCLBiome Changes] 2022-07-03 12:49:56 +02:00
Frank
e5127bf918 Changed Exception to Log-info 2022-07-01 20:19:05 +02:00
Frank
a2956a4cba [Fix] Crash when a second world is loaded 2022-07-01 20:18:10 +02:00
Frank
4259c704a2 Fixed broken placement count 2022-07-01 18:30:56 +02:00
Frank
6dd711930e More Feature Changes 2022-07-01 18:23:04 +02:00
Frank
5c3a9986bc Migrated Feature Code to new BCLib API 2022-07-01 16:54:17 +02:00
Frank
031a14f278 [Change] Migrated to new Feature API 2022-07-01 13:23:36 +02:00
Frank
0ec39fa2da [Fix] Some End-Features can spawn under/on water (#12) 2022-07-01 02:32:45 +02:00
Frank
8ca4331c6d [Change] Moved erode code to BCLib 2022-07-01 01:42:21 +02:00
Frank
41d3fc8e17 [Fix] Crash when Spawn-Point was changed (#23) 2022-07-01 00:59:28 +02:00
Frank
cda391ac07 Dependency Update 2022-06-30 23:55:31 +02:00
Frank
21616d4c6f Version Update 2022-06-30 17:53:58 +02:00
Frank
ccd4a6f57d [Change] Use Refactored Plant API (#24) 2022-06-30 17:52:25 +02:00
Frank
372d7ddd13 [Change] Re-Enabled Patchouli 2022-06-30 15:40:35 +02:00
Frank
50c305adc9 [Fix] Crash when trinkets is not installed 2022-06-30 15:30:20 +02:00
Frank
442e4a438a Do not include Trinkets 2022-06-30 11:17:31 +02:00
Frank
d6dbac05b3 [Fix] Do not include REI (possible cuase of quiqueck/BCLib#9) 2022-06-30 09:27:46 +02:00
Frank
a7442d4c36 Latest FAPI 2022-06-30 09:19:55 +02:00
Frank
e3b2249a68 Dependency Update 2022-06-30 08:20:06 +02:00
Frank
06a677169e Added tpnext command 2022-06-25 20:34:44 +02:00
Frank
dc6e0ae5e5 Fixed Feature Order 2022-06-25 20:34:12 +02:00
quiqueck
6d619f5df2 Version Updates 2022-06-24 20:37:24 +02:00
quiqueck
719811b391 Updated in preparation for 1.19.1 2022-06-24 20:36:55 +02:00
Frank
c6411dc237 CrystalMossCover 2022-06-24 14:17:10 +02:00
Frank
84f9c7de9e Changes to CrystalMountains 2022-06-24 12:10:31 +02:00
Frank
1909aea351 Some Biome Work 2022-06-24 10:58:44 +02:00
Frank
02e43f9eb6 Solving an old Dead-Lock 2022-06-24 02:15:41 +02:00
Frank
3d9b031e03 Using new Together-API 2022-06-24 02:14:21 +02:00
Frank
6770bbbbea Adopted new BCLib API 2022-06-21 19:25:57 +02:00
Frank
0f5d4e73fa [Fix] Correct Tags for Dragon-Immune (#11) 2022-06-19 23:31:08 +02:00
Frank
6c79046ef7 Non default Terrain Heights for EndBiomeSource 2022-06-19 22:06:34 +02:00
Frank
a57db4c84e Make sure Terrain Fade adapts to configured End-Height. 2022-06-19 21:26:34 +02:00
Frank
4003fb98bc Make sure we do not force our TerrainBuilder when BCLEndBiomeSource is not in use! 2022-06-19 21:14:27 +02:00
Frank
a5ea5f5989 Version Update 2022-06-16 15:14:22 +02:00
Frank
959ccb360f Changed handling of vanilla/fabric end biomes 2022-06-14 14:29:50 +02:00
Frank
1bc283dfa1 Version Update 2022-06-10 18:45:58 +02:00
Frank
f3ceaa8c72 [Feature] Trinket Support for BE-Elytra 2022-06-10 18:25:24 +02:00
Frank
36b75ed25f Move Elytra API to BCLib 2022-06-10 15:10:45 +02:00
Frank
3cecb7dd8c [Change] CRYSTALITE_ELYTRA spedd modifier 2022-06-10 14:48:11 +02:00
Frank
aec75669ed [Change] Replaced custom Elytra code with fabric version 2022-06-10 14:45:30 +02:00
Frank
5622ae316a Version Updates 2022-06-10 03:51:57 +02:00
Frank
34fd95ac11 Merge branch '1.19' of github.com:quiqueck/BetterEnd into 1.19
 Conflicts:
	src/main/java/org/betterx/betterend/integration/EnderscapeIntegration.java
2022-06-09 16:56:42 +02:00
Frank
d1eee13a31 [Fix] Remove old Enderscape Integration (again) 2022-06-09 16:56:25 +02:00
Frank
60e8008cb7 Reformated 2022-06-08 20:58:41 +02:00
Frank
fc1da134e7 Version Updated 2022-06-08 19:59:09 +02:00
Frank
237e0385cf Checked some ToDo's 2022-06-08 19:37:41 +02:00
Frank
72bb944fb2 Migrated REI Entry Point 2022-06-08 19:32:41 +02:00
Frank
e0d44ef54e Re-Enabled REI 2022-06-08 18:53:42 +02:00
Frank
2eed66008a Some changes to portal frame locator code 2022-06-08 17:37:23 +02:00
Frank
1356a91e77 [Fix] Reduced Radius for Eternal Portal Search 2022-06-08 16:41:44 +02:00
Frank
8b845a0a8f [Change] Use POI to find EternalPortalFrame 2022-06-08 14:30:54 +02:00
Frank
6d58f088e4 Migrated all to BCLibs ParticleType API 2022-06-08 12:38:13 +02:00
Frank
bddfa09b12 Disabled REI as it crashes with release 1.19 2022-06-08 01:26:32 +02:00
Frank
170608fef5 Updated for 1.19 release Version 2022-06-08 00:48:14 +02:00
Frank
bddb5fe0d7 Refactored BCLib Package Structure 2022-06-07 16:44:13 +02:00
Frank
81227198fd Added Issue Template 2022-06-07 14:49:23 +02:00
Frank
c40f104418 Updated build dependencies 2022-06-07 14:34:19 +02:00
Frank
a7da5889a1 jitpack update location 2022-06-07 14:19:33 +02:00
Евгений
e7d2b75c12 Correction of remarks.
(cherry picked from commit b8242bb1910d0097d304c920c12474ab2ad0ebcc)
2022-06-07 14:17:36 +02:00
Frank
c66e878847 Updated to latest BCLib API 2022-06-02 08:14:48 +02:00
Frank
ce0afb4cc7 Addressed multiple ToDo's 2022-05-19 23:00:16 +02:00
Frank
ed6263b886 Fixes for 1.19-pre1 2022-05-19 21:13:50 +02:00
Frank
d201a67f74 Fixed Grup 2022-05-19 00:01:23 +02:00
Frank
770a5b4046 Reorganized Imports/Packages 2022-05-18 23:56:18 +02:00
Frank
a8beba9196 Simplified TagAPI due to changes in 1.18.2 2022-05-18 22:25:37 +02:00
Frank
adfe267cd3 Fixed Sky rendering errors 2022-05-17 23:08:25 +02:00
Frank
c66a1a1824 Fixed Generation Bugs 2022-05-17 22:11:14 +02:00
Frank
277dcc04b7 Fixed some boot-crashes 2022-05-17 21:03:08 +02:00
Frank
54bbb75d77 Fixed all compile errors 2022-05-17 20:21:04 +02:00
Frank
60e7489fa4 Cave related changes 2022-05-17 20:17:18 +02:00
Frank
3d93b8607b Adapted Structures to 1.19 2022-05-17 19:04:44 +02:00
Frank
e3953167ba Compile-Fixes in BetterEnd 2022-05-17 18:09:43 +02:00
Frank
6d6a1175b5 Disabled REI (not available in 1.19) 2022-05-17 16:54:09 +02:00
Frank
cfffd1fad8 Versions for 1.19 2022-05-17 16:53:50 +02:00
paulevsGitch
be746ba286 Version update 2022-04-26 05:52:26 +03:00
paulevsGitch
4cf563fc68 Enchantment affect elytra (#448) 2022-04-26 05:39:32 +03:00
paulevsGitch
913516d35b Make all Aeternium items fire-resistant (#458) 2022-04-26 05:29:15 +03:00
paulevsGitch
36828329be Entity glowing map transparency (#439) 2022-04-26 05:17:31 +03:00
paulevsGitch
5a3e8083c1 Infusion fix 2022-04-26 05:06:35 +03:00
paulevsGitch
54202bbc51 Cleanup 2022-04-25 23:24:22 +03:00
paulevsGitch
00d65c2f6d Melt Mojang registry back, restore biome features 2022-04-25 12:13:44 +03:00
paulevsGitch
b0da1d244a Working terrain generator 2022-04-25 12:01:22 +03:00
Frank
f59cf8bad2 Fixed initial runtime crashes in BetterEnd 2022-04-08 18:17:14 +02:00
Frank
defa88bbff Changed Hammer Tool handling 2022-04-08 17:32:13 +02:00
Frank
8f8ff011ac Fixed Compiler errors on 1.18.2 2022-04-08 17:25:18 +02:00
Frank
7cf60dc206 Some more minor fixes 2022-04-03 23:48:35 +02:00
Frank
1cdbcacd7b Biome, Structure and Feature fixes 2022-04-03 23:45:18 +02:00
Frank
bcde62209b Dependency Update 2022-04-03 22:51:51 +02:00
Frank
b59eb42d35 More Tag Related Changes 2022-04-03 22:51:04 +02:00
Frank
5ba0488c9b Tool and Tag related Changes 2022-04-03 22:39:09 +02:00
Frank
0c9dcc2e06 Updated Versions for 1.18.2 2022-04-03 22:38:35 +02:00
Frank
49c0a4f9e1 Merge branch 'master' into 1.18 2022-04-03 21:57:44 +02:00
Frank
a5d5511d27 updated dependencies 2022-03-07 12:57:34 +01:00
Frank
79b435b7b1 Version update 2022-02-24 16:08:18 +01:00
Frank
58a2894658 Removed unneeded hammer tag assignment 2022-02-24 13:07:43 +01:00
Frank
4ab1d89258 Renamed markDirty (#431) 2022-02-24 11:49:00 +01:00
Frank
e5ed351f3e Make sure all hammers have the c:hammer Tag (#436) 2022-02-24 11:43:43 +01:00
Frank
f6bdd43170 Merge branch 'master' of github.com-quiqueck:paulevsGitch/BetterEnd 2022-02-24 11:39:44 +01:00
Frank
288bf2e473 Adding c:end_stones to terrain Blockas and all blocks that are used in surface rules for our end biomes. (#436) 2022-02-24 11:38:42 +01:00
Frank
34369a9443
Merge pull request #433 from rjuven2401/rjuven2401-ko_kr-edit-2
Update guidebook/ko_kr/categories/end_veil.json
2022-02-07 13:22:36 +01:00
Frank
22fb74380c
Merge pull request #434 from rjuven2401/patch-1
Update guidebook/ko_kr/categories/biomes.json
2022-02-07 13:22:26 +01:00
Frank
a1110d8e45
Merge pull request #435 from rjuven2401/patch-2
Update lang/ko_kr.json
2022-02-07 13:22:14 +01:00
rjuven2401
6797721d7c
Update lang/ko_kr.json
Corrected grammar errors and typos in lang/ko_kr.json
2022-02-06 16:00:08 +09:00
rjuven2401
f0e97febfd
Update guidebook/ko_kr/categories/biomes.json
Corrected a grammar error in guidebook/ko_kr/categories/biomes.json
2022-02-06 15:58:26 +09:00
rjuven2401
0764708b04
Update guidebook/ko_kr/categories/end_veil.json
Corrected a grammar error in guidebook/ko_kr/categories/biomes.json
2022-02-06 15:35:02 +09:00
Frank
4e008ab208 Using ThreadLocal storage 2022-01-28 17:45:26 +01:00
Frank
755a0ad7ab Improved Thread safety (may help with #394) 2022-01-28 17:13:34 +01:00
Frank
2ef8fd08af Dependency Updates 2022-01-27 16:00:34 +01:00
Frank
0ec07dbaa0 Moved ModIntegration class 2022-01-27 15:04:55 +01:00
Frank
7d9d95fc1c Fixed Helix Drops (#418) 2022-01-27 14:53:29 +01:00
Frank
a1c87165ae Adopted new TagAPI 2022-01-23 22:32:25 +01:00
Frank
e6ca1220a2 Version/Dependency update 2022-01-20 19:40:38 +01:00
Frank
4b27f00eb6 Added Codecs for SurfaceRule Objects (paulevsGitch/BetterNether#503) 2022-01-20 19:39:49 +01:00
Frank
2892e6fa11 Updated gradle script (might help with #376) 2022-01-19 23:25:23 +01:00
Frank
5d765d3877 Version update 2022-01-18 17:39:02 +01:00
Frank
dc271f08a5 Adopted Changes to BCLBiomeBuilder(paulevsGitch/BCLib#63) 2022-01-17 14:09:13 +01:00
paulevsGitch
6b27fba242 Jitpack update (#391) 2022-01-13 17:07:43 +03:00
paulevsGitch
a345be1b3e Fix island distance (#381) 2022-01-13 17:04:22 +03:00
Frank
989bd387d1 Updated jitpack to Java 17 (closes #391) 2022-01-11 17:12:02 +01:00
paulevsGitch
417350db2d
Merge pull request #372 from paulevsGitch/1.18
1.18
2021-12-30 06:43:55 +03:00
paulevsGitch
5bd0fc4f4c Removed debug string 2021-12-30 06:33:53 +03:00
paulevsGitch
2c5f4287d3 Biome structure loot, texture fixes 2021-12-30 06:17:27 +03:00
paulevsGitch
57641fe02c Structures loot, Umbrella Jungle features rebalance 2021-12-30 05:31:42 +03:00
paulevsGitch
789f1ccabd Fixed glass in structure 2021-12-30 03:23:35 +03:00
paulevsGitch
d0f2e6cd59 Fixed textures wrong pixels 2021-12-30 03:08:08 +03:00
paulevsGitch
25f4dc0ed5 Library update 2021-12-30 02:49:26 +03:00
paulevsGitch
023708f72f Island feature restored (ritual) 2021-12-28 23:00:48 +03:00
paulevsGitch
2f701885f4 Small crystal rendering fixes 2021-12-28 22:58:41 +03:00
paulevsGitch
30046b25c8 Pedestals entity fix 2021-12-28 22:11:24 +03:00
paulevsGitch
1ae6d0d63e Partial pedestals fix 2021-12-28 21:50:15 +03:00
paulevsGitch
87c37f1cef Mosses & glowshrooms count re-balance 2021-12-25 18:38:20 +03:00
paulevsGitch
ce11929d5a Biome formatting fix 2021-12-25 18:15:42 +03:00
paulevsGitch
a307cb7dc5 Neon Oasis surface fix 2021-12-25 18:13:03 +03:00
paulevsGitch
f668a3b0ef Mod json changes 2021-12-25 17:56:31 +03:00
paulevsGitch
b6e87d9103 New logo 2021-12-25 14:44:32 +03:00
paulevsGitch
bf493330ec Dust Wastelands dust depth 2021-12-23 21:17:45 +03:00
paulevsGitch
7ab1d6917f Shadow Forest re-balance 2021-12-23 21:02:32 +03:00
paulevsGitch
a5e203acb3 Sulphur Springs fixes 2021-12-23 20:25:26 +03:00
paulevsGitch
a25a02592a Chorus Forest re-balance 2021-12-23 20:16:59 +03:00
paulevsGitch
c81e072b20 Blossoming Spires re-balance 2021-12-23 20:09:11 +03:00
paulevsGitch
a4ec4522cf Ore fix, amber lands re-balance 2021-12-23 19:41:46 +03:00
paulevsGitch
35f9cd8769 Biome features 2021-12-23 16:22:38 +03:00
paulevsGitch
54258d38e3 Erosion with fixes 2021-12-23 10:16:02 +03:00
paulevsGitch
affd63646a Tree fixes 2021-12-23 09:47:34 +03:00
paulevsGitch
d0b23a9c9f Tunnel caves fixes 2021-12-23 09:37:50 +03:00
paulevsGitch
6bd2a08726 Cave floor generation 2021-12-23 07:10:58 +03:00
paulevsGitch
2c819071a5 Biome setting in caves 2021-12-23 07:06:01 +03:00
paulevsGitch
800bf72faf Feature fixes 2021-12-23 06:43:57 +03:00
paulevsGitch
5f516ac2a0 Lake generation fixes 2021-12-23 06:41:20 +03:00
paulevsGitch
064c8509e2 Plant distribution fix 2021-12-23 06:29:33 +03:00
paulevsGitch
5585d8952c Umbra valley filler & arches fixes 2021-12-23 05:44:44 +03:00
paulevsGitch
2f490fa75c Lib update, ability to use local jars fom libs folder 2021-12-23 04:47:03 +03:00
Frank
1c43af9025 Merge branch '1.18' of github.com:paulevsGitch/BetterEnd into 1.18 2021-12-21 16:59:58 +01:00
paulevsGitch
1300e1a09b Cave feature adding fix 2021-12-21 18:18:14 +03:00
paulevsGitch
6840225f1d Updated Enderscape integration 2021-12-21 18:12:31 +03:00
paulevsGitch
c2ab690d37 End city new random 2021-12-21 18:11:01 +03:00
paulevsGitch
58310d020c Replaced spaces, proper biome getter, imports cleanup 2021-12-21 18:06:48 +03:00
paulevsGitch
91e7bab993 Library update 2021-12-21 17:51:48 +03:00
paulevsGitch
4256e954ca Terrain generator fixes 2021-12-19 00:21:45 +03:00
paulevsGitch
ce88ec23f7 Terrain generator (WIP) 2021-12-18 23:57:44 +03:00
paulevsGitch
c515c3c367 Library integration update 2021-12-16 21:27:43 +03:00
paulevsGitch
fb19abdc45 Library update 2021-12-16 20:29:16 +03:00
paulevsGitch
934efc9aed Land generator (WIP) 2021-12-16 15:13:25 +03:00
paulevsGitch
5460ccba2b Average depth getter 2021-12-15 19:03:28 +03:00
paulevsGitch
e4d534d1c6 Small distance fix 2021-12-15 18:51:30 +03:00
Frank
dd1ef90f7e Dependency update 2021-12-15 16:03:35 +01:00
Frank
b624693b88 Merge branch '1.18' of github.com-quiqueck:paulevsGitch/BetterEnd into 1.18 2021-12-15 16:03:03 +01:00
Frank
e019dc2031 Loader update 2021-12-15 16:02:53 +01:00
paulevsGitch
ae755a6d11 Library update 2021-12-15 17:25:58 +03:00
Frank
784834aef8 Make sure we set the distance as a square 2021-12-15 12:01:29 +01:00
Frank
19b48a87a4 Use LifeCycle API 2021-12-15 11:59:53 +01:00
Frank
1593e7dc41 Fixed priorities in SurfaceRules 2021-12-15 11:59:01 +01:00
Frank
71ecd6d17e Exclude *the_void* biome 2021-12-15 10:25:16 +01:00
Frank
65dd58d86f Migrated to SurfaceBuilder 2021-12-15 10:25:01 +01:00
Frank
ce727b2633 Updated version 2021-12-14 13:46:45 +01:00
Frank
70e7071021 New location for parent class 2021-12-13 18:15:56 +01:00
Frank
d11dc97fd9 Version update 2021-12-10 12:51:42 +01:00
Frank
f731351a6c Fixed build errors 2021-12-09 23:03:45 +01:00
Frank
a27f3e35e2 top Material handling 2021-12-09 23:01:08 +01:00
Frank
ef02d0ee5f Removed tested ToDo's 2021-12-09 22:35:56 +01:00
Frank
33d8fe86fd Updated fabric loader 2021-12-09 22:30:14 +01:00
Frank
520fca63c3 reenabled feature add 2021-12-09 22:16:16 +01:00
Frank
514749d121 Another BCLib compat fix 2021-12-09 21:52:08 +01:00
Frank
ef025d05dd Fixed BCLib compat 2021-12-09 21:39:12 +01:00
Frank
2a0f58a729 Fixed surface block setting 2021-12-09 00:19:48 +01:00
Frank
633c5ad553 Add info about top/underMaterial to BE-biomes 2021-12-08 23:38:52 +01:00
Frank
5c12813b3e Fixed surface gen in UmbraValleyBiome 2021-12-08 21:11:24 +01:00
Frank
338aee76e9 cache last noise result for rule sequences 2021-12-08 20:43:03 +01:00
Frank
e8a40246b4 Example implementation of custom noise for SurfaceRules 2021-12-08 19:50:26 +01:00
Frank
1c79354e13 Removed double features 2021-12-08 17:28:09 +01:00
Frank
2c5c030f29 Added BiomeTest to feature placers 2021-12-08 17:04:24 +01:00
Frank
df6845642f Fixed call 2021-12-08 16:36:10 +01:00
Frank
5affe912be Merge branch '1.18' of github.com-quiqueck:paulevsGitch/BetterEnd into 1.18 2021-12-08 16:36:03 +01:00
Frank
b5b8963da4 Minor cleanup 2021-12-08 16:35:20 +01:00
Frank
396eb27175 Mixin fix 2021-12-08 16:34:41 +01:00
paulevsGitch
4ff84c5e86 Library update 2021-12-08 17:29:06 +03:00
Frank
a966671e45 disabled Patchouli until they release a 1.18 version 2021-12-08 10:45:57 +01:00
Frank
fb422d07be Make sure enderman ar default spawns 2021-12-08 09:35:45 +01:00
Frank
6b63be32b0 Fixed some bootup errors 2021-12-07 18:12:09 +01:00
Frank
6c89c76c26 Fixed all remaining compile errors (mind the TODOs, a lot of things are disabled) 2021-12-07 17:42:18 +01:00
Frank
108d2bd710 Fixed compiler errors for REI 2021-12-07 16:45:20 +01:00
Frank
78cc82932f removed reading of top/under/underwater material for now 2021-12-07 16:39:30 +01:00
Frank
dca9f84ccf More compiler fixes 2021-12-07 14:53:33 +01:00
Frank
6097311ca6 Adapted Feature Classes 2021-12-07 14:38:16 +01:00
Frank
6a8ad29a70 BYG-Integration compile fixes 2021-12-07 12:35:05 +01:00
Frank
016a3048bd Converted Biome generation to new BCLib builder 2021-12-07 12:11:08 +01:00
Frank
96c65b7bb2 fixed liquid tick call 2021-12-07 02:58:43 +01:00
paulevsGitch
64de980cab Some feature pieces fixes, changed API calls 2021-12-05 07:04:26 +03:00
paulevsGitch
6a6f29bf99 Feature API usage 2021-12-05 06:52:04 +03:00
paulevsGitch
823108aa62 Gradle change 2021-12-05 05:52:24 +03:00
paulevsGitch
2367b5d5be Partial API calls fixes 2021-12-05 05:51:51 +03:00
Frank
c2ca3f396b Fixed deprecated property 2021-12-05 00:34:26 +01:00
Frank
6671b43cac pull loom version to ptoperties 2021-12-04 14:24:53 +01:00
Frank
f16f116b7f version updates 2021-12-04 14:10:32 +01:00
Frank
c88745c7fe gradlew update to 7.3 2021-12-04 14:07:23 +01:00
Frank
f6657f91fb gradlew update to 7.3 2021-12-04 14:07:15 +01:00
paulevsGitch
a4f26e843d Gradle changes 2021-12-04 16:01:48 +03:00
paulevsGitch
2f9c131ca9 Dragon bone crafting recipes 2021-11-30 15:14:47 +03:00
paulevsGitch
191c907e24 End Fish fire damage & enchantments cooking 2021-11-30 15:11:55 +03:00
paulevsGitch
1ce74f64bf Distance fix 2021-11-30 14:50:12 +03:00
paulevsGitch
a06427c060 Small moth AI changes 2021-11-30 14:48:34 +03:00
paulevsGitch
9fb0bc9d67 Menger sponge render fixes 2021-11-30 14:40:33 +03:00
paulevsGitch
1448336709 Updated portal position code 2021-11-30 13:55:21 +03:00
paulevsGitch
5386d2e0f2 Code update 2021-11-30 12:52:10 +03:00
paulevsGitch
eca922058f Merge remote-tracking branch 'origin/master' 2021-11-30 12:38:59 +03:00
paulevsGitch
e276f5af0b Removed dimension swap 2021-11-30 12:38:49 +03:00
Frank
3413fb5c4e Revert "Use new lifetime hook for level loading"
This reverts commit c90540c33e.
2021-11-29 17:45:34 +01:00
Frank
0392fd4059 set ore hostBlock to END_STONE 2021-11-29 14:40:53 +01:00
Frank
c90540c33e Use new lifetime hook for level loading 2021-11-29 14:32:31 +01:00
Frank
ae615748b3 Make sure our Ambient Creatures can Despawn (paulevsGitch/BetterNether#438) 2021-11-28 22:04:14 +01:00
Frank
7bc0f9d63d Spelling Fix 2021-11-28 22:03:02 +01:00
paulevsGitch
0235a524bb Small enhancement 2021-11-28 07:17:40 +03:00
paulevsGitch
acec6a2213 New mob spawning API 2021-11-28 07:15:07 +03:00
paulevsGitch
a55cbe67de Version changes 2021-11-24 07:39:07 +03:00
paulevsGitch
1cf6cb3880 Enderscape ore tags 2021-11-22 17:22:07 +03:00
paulevsGitch
d8bad90731 Enderscape integration 2021-11-22 15:51:00 +03:00
paulevsGitch
ae0efb1f52 Bone blocks recipe & ore, biome formatting fix 2021-11-22 14:44:18 +03:00
paulevsGitch
9d9d640d7d Version change 2021-11-22 14:33:21 +03:00
paulevsGitch
4fddd1d258 Sky rendering cleanup & refactoring 2021-11-22 14:26:08 +03:00
paulevsGitch
3c19dad176
Merge pull request #355 from mindy15963/patch-1
Update ko_kr.json
2021-11-22 13:15:07 +03:00
paulevsGitch
360f57feed
Merge pull request #356 from Waterpicker/master
Made sky rendering work with the new fabric api.
2021-11-22 13:14:52 +03:00
Waterpicker
2f047e7132 Added to wrong section. 2021-11-22 04:07:03 -06:00
Waterpicker
a76646b029 Made sky rendering work with the new fabric api. 2021-11-22 03:55:41 -06:00
E. Kim
8aac1b5b8d
Update ko_kr.json 2021-11-22 15:01:12 +09:00
paulevsGitch
82c5485b58 Updated biome config values 2021-11-21 07:43:46 +03:00
paulevsGitch
1ca8ffca7c New Composter API usage, missing items fix 2021-11-21 07:22:42 +03:00
paulevsGitch
2afb62d6c8 Merge remote-tracking branch 'origin/master' 2021-11-21 07:09:28 +03:00
paulevsGitch
5bed4993c3 BCLib update 2021-11-21 07:09:22 +03:00
Frank
eccaa7625e Version update 2021-11-19 23:00:21 +01:00
Frank
0f04d151c7 Merge branch 'master' of github.com-quiqueck:paulevsGitch/BetterEnd 2021-11-15 14:46:20 +01:00
Frank
379789d74f Check Air-Items on Composter (paulevsGitch/BetterNether#442) 2021-11-15 14:46:16 +01:00
paulevsGitch
76ddb1fab2 Version changes 2021-11-09 21:03:19 +03:00
paulevsGitch
c4230de3c0 Removed old functions 2021-11-06 16:47:22 +03:00
paulevsGitch
a9d1082ed2 Update to BCLib 0.5.0 and new Fabric API 2021-11-06 16:45:43 +03:00
Frank
1d333071dc Fix for vanilla elytra handling 2021-11-05 15:29:43 +01:00
Frank
337b608ee8 Code cleanup for FlyFallingLib Workaround (#231) 2021-11-05 15:13:11 +01:00
Frank
0aa814c4f2 Removed old Mixin 2021-11-05 14:54:48 +01:00
Frank
653a76d86b Added workaround for incompat with FallFlyingLib 2021-11-05 14:46:21 +01:00
Frank
f11e5d3e88 Bumped BCLib dependencies 2021-11-04 16:06:36 +01:00
Frank
0f8b7d683c Updated Dependencies 2021-11-03 16:31:44 +01:00
paulevsGitch
3662820fa9
Merge pull request #336 from Dalethium/patch-1
Removed unneeded client side annotation
2021-10-29 23:16:39 +03:00
Daleth Darko
8973944b2d
Removed unneeded client side annotation
This is unneeded and causes issues with other mods such as LevelZ, see https://github.com/Noaaan/MythicMetals/issues/44
2021-10-29 08:37:27 +02:00
paulevsGitch
5fd0595a78 Fix missing cave config entries 2021-10-26 17:22:39 +03:00
paulevsGitch
ce7a8fc70a Enchantment config (#334) 2021-10-26 16:49:28 +03:00
paulevsGitch
3b570cd80e Registry update 2021-10-26 16:12:38 +03:00
paulevsGitch
9c1c1edb12 Removed redundant code (moved to BCLib lists) 2021-10-26 14:13:26 +03:00
Frank
8a1490f00e Adapted to changes in BCLib 2021-10-25 17:25:26 +02:00
paulevsGitch
0cb8a94be3 Additional fluid fix, mountain cut fix, removed redundant config options 2021-10-25 16:06:42 +03:00
paulevsGitch
74188554f5
Merge pull request #332 from SolidBlock-cn/patch-1
Update zh_cn.json
2021-10-21 15:40:41 +03:00
SolidBlock
039a599f31
Update zh_cn.json
Fix translation
2021-10-21 20:22:33 +08:00
Frank
15c78e8f1a Version up 2021-10-19 13:36:14 +02:00
Frank
ee692399be Buildsystem update 2021-10-18 20:55:11 +02:00
Frank
2ab04e9ac0 forced mixin priority might help with #231 2021-10-18 20:48:29 +02:00
Frank
effe958017 Make sure we can handle null-dimensionTypes (fixes #288) 2021-10-18 20:14:49 +02:00
Frank
da8813ba06 Using Auto-Tag feature for saplings (resolves #303) 2021-10-18 20:10:07 +02:00
Frank
1d81c16451 Added some common tags (#303) 2021-10-18 20:00:11 +02:00
Frank
14ddd13ed2 Correct Parent Block for Flammalix (corrects the error from #316) 2021-10-18 18:10:09 +02:00
Frank
6ed8e3f68d fixes #291 2021-10-18 12:52:38 +02:00
Frank
6f867a0455 changed auto-integration for BCLib 2021-10-18 12:41:25 +02:00
Frank
2e61a58e26 Moved AnvilReceipts to BCLib 2021-10-18 12:31:51 +02:00
Frank
83b6c84f7d Translate to brazilian portuguese by MatheusRibeiro07 (closes #321) 2021-10-18 09:48:29 +02:00
Frank
c0ab96453a moved IPNIgnore to BCLib 2021-10-18 09:29:18 +02:00
Frank
b713e2f4d6
WIP: Merge pull request #326 from blackd/ipn-integration
Add integration with Inventory Profiles Next for End Stone Smelter.

`IPNIgnore` needs to be moved to BCLib and some more testing is required.
2021-10-18 09:17:07 +02:00
Frank Bauer
6148bdc451 Removed build-dependency to IPN 2021-10-17 18:45:35 +02:00
Plamen K. Kosseff
3c3a9c299f Add integration with Inventory Profiles Next for End Stone Smelter. 2021-10-17 13:32:37 +03:00
paulevsGitch
61c7604641
Merge pull request #290 from MobButcher/typo
Fix typo
2021-08-24 01:21:55 +03:00
MobButcher
61547a1518
Fix typo 2021-08-23 19:50:26 +03:00
paulevsGitch
64038e94fa Datapack & other mod biome features injector fix 2021-08-20 15:25:38 +03:00
paulevsGitch
19aee44357 Merge remote-tracking branch 'origin/master' 2021-08-14 18:39:53 +03:00
paulevsGitch
f0e9303869 New BCLib biome API migration (WIP) 2021-08-14 18:39:40 +03:00
Frank
121332920f Added Ignore 2021-08-14 15:00:41 +02:00
Frank Bauer
79aa3397f6 Added Code to build-script that would support local bclib in IntelliJ (disabled in settings.gradle) 2021-08-11 13:56:52 +02:00
paulevsGitch
8bea55a8d2 Level biome source fix (WIP) 2021-08-10 14:39:34 +03:00
paulevsGitch
708c4d6fa2 Aurora crystal view block 2021-08-10 13:56:59 +03:00
paulevsGitch
3e6bcd2bc6 Effect fixes 2021-08-10 13:53:38 +03:00
paulevsGitch
57191936dc Fixed wrong custom spawn point 2021-08-10 13:41:06 +03:00
paulevsGitch
bfbaebe7b2 Disabling synq for client configs 2021-08-10 12:30:10 +03:00
paulevsGitch
73b617e8b0 Small format fix 2021-08-10 12:18:01 +03:00
paulevsGitch
9c8de4a70a Cleanup, update entity render registry 2021-08-10 12:15:15 +03:00
paulevsGitch
bc887e8cd7 Small surface builder changes 2021-08-03 06:08:27 +03:00
paulevsGitch
d0661b94f1 Umbra valley ambience 2021-08-03 05:48:13 +03:00
paulevsGitch
a8fcf0fce7 Flammalix item & lang 2021-08-03 04:58:14 +03:00
paulevsGitch
b6e4608ef2 Flammalix (WIP) 2021-08-03 03:18:12 +03:00
paulevsGitch
71cdc55a60
Merge pull request #271 from RDKRACZ/optimize
Optimize assets.
2021-08-02 10:33:39 +03:00
K0RR
16b652cc76 Optimize assets.
Lossless compression.
2021-08-01 23:53:19 +02:00
paulevsGitch
919ed868da Jungle structures & small texture fix 2021-07-31 16:29:09 +03:00
paulevsGitch
533dd7c92c Small pot fix, potted inflexia 2021-07-31 15:44:41 +03:00
paulevsGitch
757ed82817 Pallidium textures & block update 2021-07-30 21:40:04 +03:00
paulevsGitch
aee9a88003 Flower pot fixes 2021-07-29 14:20:53 +03:00
paulevsGitch
b6cf041fc4 Chorus plant changes & fixes 2021-07-25 07:29:22 +03:00
paulevsGitch
4b4d4bd5ae Simple datafixer 2021-07-25 04:37:50 +03:00
paulevsGitch
da8237c359 Complex material package move 2021-07-24 12:19:58 +03:00
paulevsGitch
a151132478 Wooden complex material migration 2021-07-23 18:36:32 +03:00
paulevsGitch
e5fde106fc Removed render registration 2021-07-22 23:59:38 +03:00
paulevsGitch
6c24a2022b Inflexia (WIP) 2021-07-22 07:20:42 +03:00
paulevsGitch
e32c6c76cb Simple WorldBlender crash fix, Pallidium blocks (WIP) 2021-07-22 04:12:13 +03:00
paulevsGitch
80590c1a7e Arches 2021-07-21 18:42:39 +03:00
paulevsGitch
a390486d5b Tag migration 2021-07-21 16:04:24 +03:00
paulevsGitch
92a392cffe Fixed sky issue with Optifine 2021-07-21 04:07:46 +03:00
paulevsGitch
253e192f1b Umbralith textures 2021-07-21 01:46:28 +03:00
paulevsGitch
a3d2b2458a Tag update 2021-07-20 05:05:34 +03:00
paulevsGitch
b2bb33d644 Anvils fixes 2021-07-20 03:40:34 +03:00
paulevsGitch
b2431153dc Update to BCLib 0.3.0 2021-07-20 00:39:58 +03:00
paulevsGitch
1a52251af0 Portal generation fix 2021-07-19 17:53:15 +03:00
paulevsGitch
4793a072c3 Umbra valley (WIP), lang files 2021-07-19 17:48:09 +03:00
paulevsGitch
663163a816 Umbralith textures update (WIP) 2021-07-19 16:42:31 +03:00
paulevsGitch
5e3848326b Some Umbralith blocks (WIP) 2021-07-19 14:05:06 +03:00
paulevsGitch
957c785c7d Umbralith (WIP) 2021-07-19 12:48:31 +03:00
paulevsGitch
55f7a858a6 Some small changes 2021-07-19 05:53:30 +03:00
Aleksey
1342326e70 Anvils fix 2021-07-16 23:50:58 +03:00
paulevsGitch
193fc41fb7 Possible sky rendering fix with optifine and immersive portals 2021-07-16 13:11:00 +03:00
paulevsGitch
a07f271866
Merge pull request #246 from quiqueck/1.17
Mine Sand with shovel
2021-07-14 13:41:43 +03:00
Frank Bauer
fbdb4559c1 Mine sand using shovel 2021-07-14 12:12:21 +02:00
Frank Bauer
8cce3303eb Merge branch 'master' of github.com:paulevsGitch/BetterEnd into 1.17 2021-07-13 18:07:06 +02:00
paulevsGitch
4684b80fc9 Version update 2021-07-12 20:30:49 +03:00
paulevsGitch
b49dfb45b0 Flower pot drop 2021-07-12 19:13:13 +03:00
paulevsGitch
f072f22605 Aeternium hammer fix 2021-07-12 13:39:43 +03:00
paulevsGitch
4b047f771a Update dependency 2021-07-12 10:20:22 +03:00
paulevsGitch
c61b90bd2a Replaced tags with procedural tags 2021-07-12 10:19:20 +03:00
paulevsGitch
f6d4684427
Merge pull request #239 from paulevsGitch/1.17
Pots update
2021-07-12 09:48:40 +03:00
paulevsGitch
c6a6ccfa32 Spanish translation by HeySoyYato 2021-07-12 09:41:43 +03:00
paulevsGitch
868e983282 Pottable crops and fixes 2021-07-12 09:18:33 +03:00
paulevsGitch
7ba38c4b27 Hydrogen biome array fox (#237) 2021-07-12 07:18:39 +03:00
paulevsGitch
01238800ed Flower pot plant overriding 2021-07-12 07:13:23 +03:00
paulevsGitch
5341daf326 Small fixes 2021-07-11 23:12:22 +03:00
paulevsGitch
eeb05a7797 Small fix 2021-07-11 23:09:03 +03:00
paulevsGitch
797db9d2d4 More pottable plants & config save/load 2021-07-11 23:05:07 +03:00
paulevsGitch
e41fd592c7 Flower pots 2021-07-11 18:16:55 +03:00
paulevsGitch
13e5e9e088 More pots (WIP) 2021-07-11 13:24:04 +03:00
paulevsGitch
287e25bbcf Pot prototype (WIP) 2021-07-11 00:46:44 +03:00
paulevsGitch
4040597a6d Removed color provider 2021-07-10 16:25:34 +03:00
paulevsGitch
71148f4af5
Merge pull request #232 from paulevsGitch/1.17
1.17.1
2021-07-09 23:00:17 +03:00
paulevsGitch
2c8862a37b Updated readme and jitpack 2021-07-09 22:59:43 +03:00
paulevsGitch
607d46f2f4 Amber land ambience 2021-07-09 22:49:54 +03:00
paulevsGitch
cc7b992f11 Neon cactus blocks fixes 2021-07-09 22:07:47 +03:00
paulevsGitch
c473068e2d Color lights integration 2021-07-09 21:59:12 +03:00
paulevsGitch
461333650a Smaragdant enhancements 2021-07-09 21:16:23 +03:00
paulevsGitch
ba7ea67f0c Anvil crafting fix 2021-07-09 15:50:06 +03:00
Frank Bauer
60f07ab437 Merge remote-tracking branch 'upstream/1.17' into 1.17 2021-07-09 11:16:43 +02:00
Frank Bauer
ccfc3adce0 Latest REI 2021-07-09 11:16:20 +02:00
paulevsGitch
a2aacd79b7
Merge pull request #229 from paulevsGitch/1.17
Update to 1.17.1
2021-07-09 11:56:41 +03:00
paulevsGitch
b5f3a4f511 Dragon respawn changes 2021-07-09 11:39:46 +03:00
paulevsGitch
2ea71cf8d6 Infusion ritual fix 2021-07-09 11:32:35 +03:00
paulevsGitch
92f6f47058 Infusion REI recipe fix 2021-07-09 11:12:13 +03:00
paulevsGitch
5fe4439096 Updated readme 2021-07-09 03:33:03 +03:00
paulevsGitch
9bd38a9629 Small addition 2021-07-09 03:24:35 +03:00
paulevsGitch
910e2304ae
Merge pull request #228 from quiqueck/1.17
German translation and duplicate fix
2021-07-09 03:17:05 +03:00
paulevsGitch
b05f2fcf57 Fixed water rendering, duplicate ID and missing hammer tag 2021-07-09 03:16:49 +03:00
Frank Bauer
df64b5e3ce Fixed duplicate of additional_gold 2021-07-09 02:11:23 +02:00
Frank Bauer
9ad0c3c417 german tarnslation for guidebook 2021-07-09 02:10:50 +02:00
Frank Bauer
4a8108f8e1 Merge remote-tracking branch 'upstream/1.17' into 1.17 2021-07-09 02:00:33 +02:00
paulevsGitch
ea9b3c72a4 Fixed elytra boost 2021-07-09 02:14:54 +03:00
paulevsGitch
a8ace0005b Removed old method 2021-07-09 02:03:32 +03:00
paulevsGitch
2f88ac5358 Guidebook fix 2021-07-09 02:03:11 +03:00
paulevsGitch
7e7dad084e Eternal pedestals fix 2021-07-09 01:57:38 +03:00
Frank Bauer
4e1dcac17e Merge remote-tracking branch 'upstream/1.17' into 1.17 2021-07-09 00:54:46 +02:00
Frank Bauer
cca7d9d3b2 Fixed item rendering bug 2021-07-09 00:54:42 +02:00
paulevsGitch
86a37e5770 Cache clearing 2021-07-09 01:51:26 +03:00
paulevsGitch
3086f6181b Terrain generator enhancements 2021-07-09 01:50:08 +03:00
paulevsGitch
fc3b6ea5b2 Crystal colors fix 2021-07-08 16:50:41 +03:00
paulevsGitch
ef3b286103 Fixed items on pedestals 2021-07-08 15:27:16 +03:00
paulevsGitch
dbfaa09b5b Test fix for "Detected setBlock in a far chunk" 2021-07-08 13:27:47 +03:00
paulevsGitch
e9e39f7152 Hydrotermal vent ticks fix 2021-07-08 12:01:38 +03:00
paulevsGitch
93ca944472 Fixed sky rendering 2021-07-08 11:12:00 +03:00
paulevsGitch
c623da26ed Fixed REI integration 2021-07-08 01:22:57 +03:00
paulevsGitch
80918ea7e4 Vent smoke fixes 2021-07-08 00:31:18 +03:00
paulevsGitch
44962e18b6 Code style changes, entities fixes 2021-07-08 00:21:47 +03:00
paulevsGitch
9d604b2d25 Raw thallasium, more ore tweaks 2021-07-07 23:27:32 +03:00
paulevsGitch
2d93ac3853 Ore generation tweaks 2021-07-07 23:05:37 +03:00
paulevsGitch
43e127bf75 New ores recipes & smelter light fix 2021-07-07 22:56:14 +03:00
paulevsGitch
2591cb1555 Fast lakes fix 2021-07-07 22:27:09 +03:00
paulevsGitch
5a7a00ddd5 Pickaxe mining speed fixes 2021-07-07 22:04:38 +03:00
paulevsGitch
c98186fefa Merge remote-tracking branch 'origin/master' into 1.17 2021-07-07 21:23:36 +03:00
paulevsGitch
62ba56eee6
Merge pull request #213 from quiqueck/1.17
1.17/1.17.1 Conversion
2021-07-07 21:22:29 +03:00
paulevsGitch
e2030c2598
Merge pull request #227 from paulevsGitch/1.16.5
Merge pull request #226 from paulevsGitch/master
2021-07-07 21:14:29 +03:00
paulevsGitch
c52f80242a
Merge pull request #226 from paulevsGitch/master
Translation
2021-07-07 21:14:01 +03:00
Frank Bauer
9b92ad3967 Merge remote-tracking branch 'upstream/master' into 1.17 2021-07-07 15:49:13 +02:00
Frank Bauer
18bc3a9664 Fixes for 1.17.1 2021-07-07 13:49:27 +02:00
Frank Bauer
885a72486d Updated Versions for 1.17.1 2021-07-07 13:39:33 +02:00
Frank Bauer
9db7f4d940 Added mining labels 2021-07-04 23:54:40 +02:00
Frank Bauer
18d78acd07 Revert "Automatic tool configuration for Blocks"
This reverts commit 8c1f9567a5.
2021-07-04 23:48:37 +02:00
Frank Bauer
8c1f9567a5 Automatic tool configuration for Blocks 2021-07-04 18:53:00 +02:00
Aleksey
e28dcf1ee4 Possibility to add NBT data for Anvil recipes output 2021-06-30 16:23:32 +03:00
Aleksey
3f225c59a1 Possibility to add NBT data for Infusion recipes output (#215) 2021-06-30 16:20:16 +03:00
Frank Bauer
2b71f7782a Updated EndSky-Rendering 2021-06-30 13:24:01 +02:00
Frank Bauer
3386f1c6b0 Latest REI Version 2021-06-30 12:25:01 +02:00
Frank Bauer
9a28623230 Fabric 1.17 does not contain the ArmorRenderingRegistry. Temporarily added the missing files to a shadow-namespace to allw testing of the CrystaliteArmor. 2021-06-30 12:24:07 +02:00
Frank Bauer
2ba7ed4ec8 Fixed crash for unplacable Anvil 2021-06-29 23:33:32 +02:00
Frank Bauer
ab6d015c98 Fixed Tick for InfusionPedestal 2021-06-29 23:05:36 +02:00
Frank Bauer
b6c4e73481 Fixed crash for anvil items on REI 2021-06-29 22:02:30 +02:00
Frank Bauer
c5fb156042 Fixes for REI 2021-06-29 21:32:55 +02:00
Frank Bauer
e7c85c8148 Partially working REI 2021-06-29 20:23:19 +02:00
Aleksey
13e169c458 Possible avoid #214 2021-06-29 21:14:28 +03:00
Frank Bauer
ea62902ee8 Fixed EndPodiumFeatureMixin 2021-06-28 22:39:37 +02:00
Frank Bauer
2aa6243f40 Fixed runtime crashes 2021-06-28 22:12:19 +02:00
Frank Bauer
770f12ee20 Fixed UV-Coordinate rendering 2021-06-28 17:56:03 +02:00
Frank Bauer
3d6f0adc56 Added Patchouli back 2021-06-28 12:24:39 +02:00
Frank Bauer
fb645f8f58 Fixed some class names 2021-06-28 12:15:48 +02:00
Frank Bauer
90f865d1af Fixed model Bugs 2021-06-28 12:14:56 +02:00
Aleksey
daefcc4dbf Fix #216 and #217 2021-06-27 17:30:15 +03:00
Frank Bauer
42b436e408 Type changes 2021-06-25 00:00:30 +02:00
Frank Bauer
e25ab5698d Mixin Fixes 2021-06-25 00:00:09 +02:00
Frank Bauer
e104752c6d Fixed argument mixin 2021-06-24 23:27:49 +02:00
Frank Bauer
072e8b47db Make sure REI does compile (deactivated some code for the moment!) 2021-06-24 23:27:34 +02:00
Frank Bauer
49386dc7e1 Continued work on **rei** 2021-06-24 23:02:29 +02:00
Frank Bauer
aa1b0d87bb Some fixes for **rei** 6.x 2021-06-24 22:36:27 +02:00
Frank Bauer
63b524af62 rei for 1.17 2021-06-24 21:14:20 +02:00
Frank Bauer
2d130fac96 Make sure CrystaliteArmorProvider compiles 2021-06-24 19:40:38 +02:00
Frank Bauer
539a574cca Using FabricBlockEntityTypeBuilder 2021-06-24 19:30:53 +02:00
Frank Bauer
5089a44a39 Rendering fixes 2021-06-24 19:21:26 +02:00
Frank Bauer
3fbacddf3c Smaller UI updates 2021-06-24 18:54:22 +02:00
Frank Bauer
78bf62bdca Biome Features Updated 2021-06-24 17:58:09 +02:00
Frank Bauer
aca43764ad Updated PedestalItemRenderer 2021-06-24 17:57:53 +02:00
Frank Bauer
371d491e5f Updated Armor Models 2021-06-24 17:32:11 +02:00
Frank Bauer
10a9a81725 Various smaller updates 2021-06-24 17:11:48 +02:00
Frank Bauer
fdd61262c5 TODOs and WorldRenderMixin Update 2021-06-24 16:03:04 +02:00
Frank Bauer
20859ae133 Updated OldBulbisGardens 2021-06-24 16:02:41 +02:00
Frank Bauer
05f59b4856 Fixed place-Methods (Pt. II) 2021-06-24 15:32:30 +02:00
Frank Bauer
a82f30b95d Fixed 'place'-Methods 2021-06-24 15:10:10 +02:00
Frank Bauer
4bf09362be Fixed PlayerListMixin 2021-06-24 14:47:23 +02:00
Frank Bauer
f6cbb15917 Fixed LivingEntityMixin 2021-06-24 12:50:22 +02:00
Frank Bauer
8555931932 Another round of minor changes 2021-06-24 12:34:12 +02:00
Frank Bauer
32f9bf288e StructurePiece constructor and addAdditionalSaveData Signature 2021-06-24 12:33:49 +02:00
Frank Bauer
036d594012 updated isFeatureChunk and generatePieces Signatures 2021-06-24 12:13:09 +02:00
Frank Bauer
8531be7b94 *ArmoredElytra* Fixes 2021-06-24 11:48:48 +02:00
Frank Bauer
e03c8433db *ShadowWalker* renderer 2021-06-24 11:03:04 +02:00
Frank Bauer
df8eb8f040 Helper to convert old RenderModel calls to new syntax 2021-06-24 10:58:56 +02:00
Frank Bauer
fb29dd75f7 *SilkMoth* Model 2021-06-24 10:58:05 +02:00
Frank Bauer
b0ecc1152c *EndFish* Model 2021-06-24 10:21:50 +02:00
Frank Bauer
813880aa19 *Dragonfly* Model 2021-06-24 10:09:02 +02:00
Frank Bauer
fd062bf9a9 Minor fixes 2021-06-24 09:19:46 +02:00
Frank Bauer
e5bf933758 Render *EndSlime* 2021-06-24 09:19:20 +02:00
Frank Bauer
d6696feb16 Signature changes 2021-06-23 23:50:46 +02:00
Frank Bauer
6e9d8e8b49 using getters for abilities and yRot 2021-06-23 23:50:30 +02:00
Frank Bauer
d8383121e3 *Cubozoa* Model 2021-06-23 23:46:26 +02:00
Frank Bauer
9372ecf28f version updates 2021-06-23 22:23:35 +02:00
Frank Bauer
e541763ada Additional compiler fixes 2021-06-23 22:23:20 +02:00
Frank Bauer
4f053c161a More compiler fixes 2021-06-23 21:59:24 +02:00
Frank Bauer
cfa765437c Àgeable, MobBucketItem, UniformGenerator and ShuffleList` 2021-06-23 20:31:56 +02:00
Frank Bauer
0ac3814cd5 Updated tick 2021-06-23 20:30:49 +02:00
Frank Bauer
08fc14439a Compiler Fixes for EndStoneSmelter 2021-06-23 17:27:12 +02:00
Frank Bauer
09a19845a4 Merge commit '30204a2aee' into 1.17 2021-06-23 17:25:25 +02:00
paulevsGitch
30204a2aee Wrong chest registry fix 2021-06-22 13:32:44 +03:00
paulevsGitch
262b249654 Version change 2021-06-21 21:52:05 +03:00
paulevsGitch
37394eba11 Parallel cave generation & block fixing 2021-06-21 21:38:56 +03:00
paulevsGitch
4dce2d5d7e Fix for caves breaking surface vertically 2021-06-21 12:46:52 +03:00
paulevsGitch
684f3073ca Fixed missing cave population & tags 2021-06-21 12:25:26 +03:00
paulevsGitch
bed07d2ad7 Fixed missing caves in most biomes 2021-06-21 12:16:54 +03:00
paulevsGitch
ff3194fedf Small water plant placing fix 2021-06-21 01:22:30 +03:00
paulevsGitch
b0922d967f Server side crash fix 2021-06-20 18:49:53 +03:00
paulevsGitch
2461df6674 Merge branch '1.17' of https://github.com/paulevsGitch/BetterEnd into 1.17 2021-06-20 15:14:19 +03:00
Aleksey
772e6b38e3 Update dependecies 2021-06-20 15:13:54 +03:00
Aleksey
49814fea0f Update dependecies 2021-06-18 15:09:28 +03:00
2236 changed files with 57156 additions and 40689 deletions

84
.github/ISSUE_TEMPLATE/BUG_REPORT.yml vendored Normal file
View file

@ -0,0 +1,84 @@
name: Report a Bug
description: File a bug report
title: "[Bug] "
labels: [ "bug" ]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report a Bug in BetterEnd!
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
value: "A bug happened!"
validations:
required: true
- type: markdown
attributes:
value: |
## Versions
- type: input
id: bn_version
attributes:
label: BetterEnd
description: What version of BetterEnd are you running?
placeholder: 2.0.x
validations:
required: true
- type: input
id: bclib_version
attributes:
label: BCLib
description: What version of BCLib are you running?
placeholder: 2.0.x
validations:
required: true
- type: input
id: fabric_api_version
attributes:
label: Fabric API
description: What version of Fabric API is installed
placeholder: 0.5x.x
validations:
required: false
- type: input
id: fabric_loader_version
attributes:
label: Fabric Loader
description: What version of Fabric Loader do you use
placeholder: 0.14.x
validations:
required: false
- type: dropdown
id: mc_version
attributes:
label: Minecraft
description: What version of Minecraft is installed?
options:
- 1.19.1
- 1.19
- 1.18.2
- 1.18.1
- 1.18
- Older
validations:
required: true
- type: markdown
attributes:
value: |
## Additional Information
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
- type: textarea
id: other_mods
attributes:
label: Other Mods
description: If you can, please supply a list of installed Mods (besides BetterEnd and BCLib). This information may already be included in the log above.
render: shell

18
.github/ISSUE_TEMPLATE/SUGGEST_FROM.yml vendored Normal file
View file

@ -0,0 +1,18 @@
name: Suggest a Feature or Change
description: Have a new Idea, then suggest a Feature here.
title: "[Suggestion] "
labels: ["suggestion"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to suggest a new Feature for BCLib. We appreciate your time!
- type: textarea
id: describe
attributes:
label: Description
description: Tell us your idea
placeholder:
value:
validations:
required: true

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1 @@
blank_issues_enabled: true

7
.gitignore vendored
View file

@ -27,5 +27,10 @@ bin/
# fabric
run/
run-client/
run-server/
output/
*.log
*.getBlock("log")
Convert.class
ModelPart.class
libs/

161
Convert.java Normal file
View file

@ -0,0 +1,161 @@
class ModelPart {
static java.util.ArrayList<ModelPart> parts = new java.util.ArrayList<>(20);
final String name;
ModelPart parent = null;
boolean mirror = false;
float x = 0, y = 0, z = 0, rx = 0, ry = 0, rz = 0;
int u = 0, v = 0;
float bx = 0, by = 0, bz = 0, ba = 0, bb = 0, bc = 0;
float scale = 1;
static int wd = 64;
static int hg = 32;
boolean hadBox = false;
ModelPart(Convert c, String name) {
this(c, 0, 0, name);
}
ModelPart(Convert c, int u, int v, String name) {
this.name = name;
this.u = u;
this.v = v;
parts.add(this);
}
ModelPart(int wd, int hg, int u, int v, String name) {
this.name = name;
this.u = u;
this.v = v;
ModelPart.wd = wd;
ModelPart.hg = hg;
parts.add(this);
}
ModelPart setPos(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
return this;
}
ModelPart setRotationAngle(float x, float y, float z) {
this.rx = x;
this.ry = y;
this.rz = z;
return this;
}
ModelPart addChild(ModelPart p) {
p.parent = this;
return this;
}
ModelPart texOffs(int u, int v) {
this.u = u;
this.v = v;
return this;
}
ModelPart addBox(float x, float y, float z, float a, float b, float c) {
return addBox(x, y, z, a, b, c, 1);
}
ModelPart addBox(float x, float y, float z, float a, float b, float c, float _d) {
bx = x;
by = y;
bz = z;
ba = a;
bb = b;
bc = c;
scale = _d;
hadBox = true;
return this;
}
ModelPart addBox(float x, float y, float z, float a, float b, float c, float _d, boolean mirror) {
this.mirror = mirror;
bx = x;
by = y;
bz = z;
ba = a;
bb = b;
bc = c;
hadBox = true;
return this;
}
public String toString() {
String s = "";
String pName = parent == null ? "modelPartData" : parent.name;
if (scale != 1) {
s += "CubeDeformation deformation_" + name + " = new CubeDeformation(" + scale + "f);\n";
}
s += "PartDefinition " + name + " = ";
s += pName + ".addOrReplaceChild(\"" + name + "\", CubeListBuilder.create()\n";
if (this.mirror) s += ".mirror()\n";
s += ".texOffs(" + u + ", " + v + ")";
if (this.hadBox) {
s += "\n";
if (scale != 1)
s += ".addBox(" + bx + "f, " + by + "f, " + bz + "f, " + ba + "f, " + bb + "f, " + bc + "f, deformation_" + name + "),\n";
else s += ".addBox(" + bx + "f, " + by + "f, " + bz + "f, " + ba + "f, " + bb + "f, " + bc + "f),\n";
}
else {
s += ",\n";
}
if (x == 0 && y == 0 && z == 0 && rx == 0 && ry == 0 && rz == 0) {
s += "PartPose.ZERO";
}
else if (rx == 0 && ry == 0 && rz == 0) {
s += "PartPose.offset(" + x + "f, " + y + "f, " + z + "f)";
}
else {
s += "PartPose.offsetAndRotation(" + x + "f, " + y + "f, " + z + "f, \n" + rx + "f, " + ry + "f, " + rz + "f)";
}
s += ");";
return s;
}
public static void print() {
System.out.println("public static LayerDefinition getTexturedModelData() {");
System.out.println(" MeshDefinition modelData = new MeshDefinition();");
System.out.println(" PartDefinition modelPartData = modelData.getRoot();");
for (ModelPart p : parts) {
System.out.println(p);
System.out.println();
}
System.out.println("return LayerDefinition.create(modelData, " + wd + ", " + hg + ");");
System.out.println("}");
System.out.println();
System.out.println();
for (ModelPart p : parts) {
String pName = p.parent == null ? "modelPart" : p.parent.name;
System.out.println(p.name + " = " + pName + ".getChild(\"" + p.name + "\");");
}
}
}
ModelPart.print();
}
void setRotationAngle(ModelPart p, float x, float y, float z){
p.setRotationAngle(x, y, z);
}
public void c (){
float scale = 1;
ModelPart[] SHARDS = new ModelPart[4];
SHARDS[0] = new ModelPart(16, 16, 2, 4, "SHARDS[0]").addBox(-5.0F, 1.0F, -3.0F, 2.0F, 8.0F, 2.0F);
SHARDS[1] = new ModelPart(16, 16, 2, 4, "SHARDS[1]").addBox(3.0F, -1.0F, -1.0F, 2.0F, 8.0F, 2.0F);
SHARDS[2] = new ModelPart(16, 16, 2, 4, "SHARDS[2]").addBox(-1.0F, 0.0F, -5.0F, 2.0F, 4.0F, 2.0F);
SHARDS[3] = new ModelPart(16, 16, 2, 4, "SHARDS[3]").addBox(0.0F, 3.0F, 4.0F, 2.0F, 6.0F, 2.0F);
ModelPart CORE = new ModelPart(16, 16, 0, 0, "CORE");
CORE.addBox(-2.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F);
}
}

View file

@ -19,3 +19,7 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
___________________________
Some of our Assets (see LICENSE.ASSETS for a Listing) is licensed under CC BY-NC-SA 4.0
See https://creativecommons.org/licenses/by-nc-sa/4.0/ for Details.

9
LICENSE.ASSETS Normal file
View file

@ -0,0 +1,9 @@
Some of our Assets (see List below) is licensed under CC BY-NC-SA 4.0
See https://creativecommons.org/licenses/by-nc-sa/4.0/ for Details.
Please use the Attribution "Team BetterX".
The following Files are distributed under this License:
* src/main/resources/assets/betterend/textures/gui/infusion.png
* src/main/resources/assets/betterend/icon_updater.png
* src/main/resources/assets/betterend/lang/de_de.json

View file

@ -1,17 +1,19 @@
[![](https://jitpack.io/v/paulevsGitch/BetterEnd.svg)](https://jitpack.io/#paulevsGitch/BetterEnd)
[![](https://jitpack.io/v/quiqueck/BetterEnd.svg)](https://jitpack.io/#quiqueck/BetterEnd)
# Better End
Better End Mod for Fabric, MC 1.16.4
Better End Mod for Fabric, MC 1.19
Importing:
* Clone repo
* Edit gradle.properties if necessary
* Run command line in folder: gradlew genSources eclipse (or Another-IDE-Name)
* Run command line in folder: gradlew genSources idea (or eclipse)
* Import project to IDE
Building:
* Clone repo
* Run command line in folder: gradlew build
* Mod .jar will be in ./build/libs
Mappings:
* https://modmuss50.me/fabric.html?&version=1.16.4

View file

@ -5,75 +5,75 @@ buildscript {
}
plugins {
id 'idea'
id 'eclipse'
id 'fabric-loom' version '0.7-SNAPSHOT'
id 'fabric-loom' version "${loom_version}"
id 'maven-publish'
}
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
archivesBaseName = project.archives_base_name
version = project.mod_version
group = project.maven_group
def local_bclib = findProject(':BCLib') != null
repositories {
maven { url "https://maven.dblsaiko.net/" }
maven { url "https://server.bbkr.space:8081/artifactory/libs-release/" }
maven { url "https://maven.fabricmc.net/" }
maven { url 'https://maven.blamejared.com' }
maven { url "https://maven.shedaniel.me/" }
maven { url 'https://jitpack.io' }
maven { url 'https://maven.terraformersmc.com/releases' }
maven { url = "https://maven.terraformersmc.com/" }
maven { url "https://ladysnake.jfrog.io/artifactory/mods" }
maven { url = "https://dvs1.progwml6.com/files/maven/" }
maven { url = "https://modmaven.dev" }
flatDir {
dirs 'libs'
}
}
loom {
accessWidenerPath = file("src/main/resources/betterend.accesswidener")
interfaceInjection {
// When enabled injected interfaces from dependecies will be applied.
enableDependencyInterfaceInjection = false
}
}
dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings minecraft.officialMojangMappings()
mappings loom.officialMojangMappings()
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
useApi "vazkii.patchouli:Patchouli:1.16.4-${project.patchouli_version}"
useApi "com.github.paulevsGitch:BCLib:${project.bclib_version}"
modApi "vazkii.patchouli:Patchouli:${project.patchouli_version}"
println "Using local BCLib: ${local_bclib}"
if (local_bclib) {
implementation(project(path: ":BCLib", configuration: 'dev'))
} else {
modImplementation "com.github.quiqueck:BCLib:${project.bclib_version}"
}
modCompileOnly "me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}"
modCompileOnly "me.shedaniel:RoughlyEnoughItems-api-fabric:${project.rei_version}"
useOptional "me.shedaniel:RoughlyEnoughItems:${project.rei_version}"
useOptional "me.shedaniel:RoughlyEnoughItems-api:${project.rei_version}"
//useOptional "grondag:canvas-mc116:${project.canvas_version}"
}
// compile against the JEI API but do not include it at runtime
modCompileOnlyApi "mezz.jei:jei-1.19-common-api:${project.jei_version}"
modCompileOnlyApi "mezz.jei:jei-1.19-fabric-api:${project.jei_version}"
// at runtime, use the full JEI jar for Fabric
//modRuntimeOnly "mezz.jei:jei-${project.minecraft_version}-fabric:${project.jei_version}"
def useOptional(String dep) {
dependencies.modRuntime (dep) {
exclude group: "net.fabricmc.fabric-api"
exclude group: "net.fabricmc"
if (!dep.contains("me.shedaniel")) {
exclude group: "me.shedaniel"
}
}
dependencies.modCompileOnly (dep) {
exclude group: "net.fabricmc.fabric-api"
exclude group: "net.fabricmc"
if (!dep.contains("me.shedaniel")) {
exclude group: "me.shedaniel"
}
}
}
def useApi(String dep) {
dependencies.modApi (dep) {
exclude group: "net.fabricmc.fabric-api"
exclude group: "net.fabricmc"
if (!dep.contains("me.shedaniel")) {
exclude group: "me.shedaniel"
}
}
//needed for trinkets, otherwise BetterEnd would require users to install trinkets
modApi "dev.onyxstudios.cardinal-components-api:cardinal-components-base:${project.cca_version}"
modCompileOnly "dev.emi:trinkets:${project.trinkets_version}"
modCompileOnly "dev.emi:emi:${emi_version}"
//modRuntimeOnly "dev.emi:emi:${emi_version}"
}
processResources {
println "Version: ${project.version}"
inputs.property "version", project.version
duplicatesStrategy = 'WARN'
from(sourceSets.main.resources.srcDirs) {
include "fabric.mod.json"
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
@ -83,6 +83,7 @@ processResources {
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
it.options.release = 17
}
javadoc {
@ -102,8 +103,16 @@ task sourcesJar(type: Jar, dependsOn: classes) {
from sourceSets.main.allSource
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
}
jar {
from "LICENSE"
from "LICENSE.ASSETS"
}
artifacts {
@ -123,11 +132,11 @@ task release(dependsOn: [remapJar, sourcesJar, javadocJar]) {
doLast {
def github = GitHub.connectUsingOAuth(env.GITHUB_TOKEN as String)
def repository = github.getRepository("paulevsGitch/BetterEnd")
def repository = github.getRepository("quiqueck/BetterEnd")
def releaseBuilder = new GHReleaseBuilder(repository, version as String)
releaseBuilder.name("${archivesBaseName}-${version}")
releaseBuilder.body("A changelog can be found at https://github.com/paulevsGitch/BetterEnd/commits")
releaseBuilder.body("A changelog can be found at https://github.com/quiqueck/BetterEnd/commits")
releaseBuilder.commitish("master")
def ghRelease = releaseBuilder.create()
@ -138,21 +147,21 @@ task release(dependsOn: [remapJar, sourcesJar, javadocJar]) {
}
// configure the maven publication
//publishing {
// publications {
// mavenJava(MavenPublication) {
// artifact(remapJar) {
// builtBy remapJar
// }
// artifact(sourcesJar) {
// builtBy remapSourcesJar
// }
// }
// }
//
// // select the repositories you want to publish to
// repositories {
// // uncomment to publish to the local maven
// // mavenLocal()
// }
//}
publishing {
publications {
mavenJava(MavenPublication) {
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
}
}
// select the repositories you want to publish to
repositories {
// uncomment to publish to the local maven
// mavenLocal()
}
}

View file

@ -1,21 +1,22 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx2G
# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version=1.16.5
yarn_mappings=6
loader_version=0.11.3
# check these on https://fabricmc.net/versions.html
minecraft_version=1.19
loader_version=0.14.8
fabric_version=0.58.0+1.19
#Loom
loom_version=0.12-SNAPSHOT
# Mod Properties
mod_version = 0.9.8-pre
maven_group = ru.betterend
archives_base_name = better-end
mod_version=2.0.12
maven_group=org.betterx.betterend
archives_base_name=better-end
# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
patchouli_version = 50-FABRIC
fabric_version = 0.32.9+1.16
canvas_version = 1.0.+
bclib_version = 0.1.38
rei_version = 5.8.10
patchouli_version=1.19-73-FABRIC
bclib_version=2.0.20
rei_version=9.1.500
jei_version=11.1.0.235
emi_version=0.3.0+1.19
trinkets_version=3.4.0
cca_version=5.0.0-beta.1

Binary file not shown.

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

269
gradlew vendored
View file

@ -1,7 +1,7 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -17,78 +17,113 @@
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@ -105,79 +140,95 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

22
gradlew.bat vendored
View file

@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -54,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -64,28 +64,14 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

6
jitpack.yml Normal file
View file

@ -0,0 +1,6 @@
# From https://github.com/jitpack/jitpack.io/issues/4506#issuecomment-864562270
before_install:
- source "$HOME/.sdkman/bin/sdkman-init.sh"
- sdk update
- sdk install java 17.0.1-tem
- sdk use java 17.0.1-tem

View file

@ -1,7 +1,16 @@
{
"variants": {
"axis=x": { "model": "betterend:block/%name%_pillar", "x": 90, "y": 90 },
"axis=y": { "model": "betterend:block/%name%_pillar" },
"axis=z": { "model": "betterend:block/%name%_pillar", "x": 90 }
"axis=x": {
"model": "betterend:block/%name%_pillar",
"x": 90,
"y": 90
},
"axis=y": {
"model": "betterend:block/%name%_pillar"
},
"axis=z": {
"model": "betterend:block/%name%_pillar",
"x": 90
}
}
}

View file

@ -1,5 +1,6 @@
pluginManagement {
repositories {
jcenter()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
@ -7,3 +8,39 @@ pluginManagement {
gradlePluginPortal()
}
}
// #### Custom Settings ####
//Change the next line to disable local BCLib loading
def allowLocalLibUse = true
//When true, the local BCLib is also used in commandline builds
def allowLocalLibInConsoleMode = false
//The path were to look for the local BCLib
def BCLibPath = '../BCLib'
// #### Logic ####
def isIDE = properties.containsKey('android.injected.invoked.from.ide')
|| (System.getenv("XPC_SERVICE_NAME") ?: "").contains("intellij")
|| (System.getenv("XPC_SERVICE_NAME") ?: "").contains(".idea")
|| System.getenv("IDEA_INITIAL_DIRECTORY") != null
println "IntelliJ: ${isIDE}"
def BCLibFolder = new File( BCLibPath )
if( allowLocalLibUse && (isIDE || allowLocalLibInConsoleMode) && BCLibFolder.exists() ) {
println "Using local BCLib from '${BCLibFolder}' in IntelliJ"
println "If you do not want to load the local version of BClib"
println "either rename the Folder containing BCLib to something"
println "else, or set 'allowLocalLibUse' in settings.gradle"
println "to false."
println ""
println "If you receive version-errors when launching minecraft"
println "in IntelliJ, make sure you have set up gradle instead"
println "of IntelliJ to compile and run."
include ':BCLib'
project(":BCLib").projectDir = BCLibFolder
project(':BCLib').buildFileName = './bclib-composit.gradle'
}

View file

@ -0,0 +1,91 @@
package org.betterx.betterend;
import org.betterx.bclib.api.v2.generator.BiomeDecider;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.betterend.advancements.BECriteria;
import org.betterx.betterend.api.BetterEndPlugin;
import org.betterx.betterend.commands.CommandRegistry;
import org.betterx.betterend.config.Configs;
import org.betterx.betterend.effects.EndPotions;
import org.betterx.betterend.integration.Integrations;
import org.betterx.betterend.recipe.*;
import org.betterx.betterend.registry.*;
import org.betterx.betterend.util.BonemealPlants;
import org.betterx.betterend.util.LootTableUtil;
import org.betterx.betterend.world.generator.EndLandBiomeDecider;
import org.betterx.betterend.world.generator.GeneratorOptions;
import org.betterx.worlds.together.util.Logger;
import org.betterx.worlds.together.world.WorldConfig;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biomes;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
public class BetterEnd implements ModInitializer {
public static final String MOD_ID = "betterend";
public static final Logger LOGGER = new Logger(MOD_ID);
public static final boolean RUNS_TRINKETS = FabricLoader.getInstance()
.getModContainer("trinkets")
.isPresent();
@Override
public void onInitialize() {
WorldConfig.registerModCache(MOD_ID);
EndPortals.loadPortals();
EndSounds.register();
EndMenuTypes.ensureStaticallyLoaded();
EndBlockEntities.register();
EndPoiTypes.register();
EndFeatures.register();
EndEntities.register();
EndBiomes.register();
EndTags.register();
EndBlocks.ensureStaticallyLoaded();
EndItems.ensureStaticallyLoaded();
EndEnchantments.register();
EndPotions.register();
CraftingRecipes.register();
FurnaceRecipes.register();
AlloyingRecipes.register();
AnvilRecipes.register();
SmithingRecipes.register();
InfusionRecipes.register();
EndStructures.register();
BonemealPlants.init();
GeneratorOptions.init();
LootTableUtil.init();
CommandRegistry.register();
BECriteria.register();
EndAdvancements.register();
FabricLoader.getInstance()
.getEntrypoints("betterend", BetterEndPlugin.class)
.forEach(BetterEndPlugin::register);
Integrations.init();
Configs.saveConfigs();
if (GeneratorOptions.useNewGenerator()) {
BiomeDecider.registerHighPriorityDecider(makeID("end_land"), new EndLandBiomeDecider());
}
BiomeAPI.registerEndBiomeModification((biomeID, biome) -> {
if (!biomeID.equals(Biomes.THE_VOID.location())) {
EndFeatures.addBiomeFeatures(biomeID, biome);
}
});
BiomeAPI.onFinishingEndBiomeTags((biomeID, biome) -> {
if (!biomeID.equals(Biomes.THE_VOID.location())) {
EndStructures.addBiomeStructures(biomeID, biome);
}
});
if (RUNS_TRINKETS) {
org.betterx.betterend.integration.trinkets.Elytra.register();
}
}
public static ResourceLocation makeID(String path) {
return new ResourceLocation(MOD_ID, path);
}
}

View file

@ -0,0 +1,37 @@
package org.betterx.betterend.advancements;
import org.betterx.betterend.BetterEnd;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.advancements.critereon.EntityPredicate;
import net.minecraft.advancements.critereon.PlayerTrigger;
public class BECriteria {
public static PlayerTrigger PORTAL_ON;
public static PlayerTrigger PORTAL_TRAVEL;
public static PlayerTrigger INFUSION_FINISHED;
public static PlayerTrigger.TriggerInstance PORTAL_ON_TRIGGER;
public static PlayerTrigger.TriggerInstance PORTAL_TRAVEL_TRIGGER;
public static PlayerTrigger.TriggerInstance INFUSION_FINISHED_TRIGGER;
public static void register() {
PORTAL_ON = CriteriaTriggers.register(new PlayerTrigger(BetterEnd.makeID("portal_on")));
PORTAL_TRAVEL = CriteriaTriggers.register(new PlayerTrigger(BetterEnd.makeID("portal_travel")));
INFUSION_FINISHED = CriteriaTriggers.register(new PlayerTrigger(BetterEnd.makeID("infusion_finished")));
PORTAL_ON_TRIGGER = new PlayerTrigger.TriggerInstance(
PORTAL_ON.getId(),
EntityPredicate.Composite.ANY
);
PORTAL_TRAVEL_TRIGGER = new PlayerTrigger.TriggerInstance(
PORTAL_TRAVEL.getId(),
EntityPredicate.Composite.ANY
);
INFUSION_FINISHED_TRIGGER = new PlayerTrigger.TriggerInstance(
INFUSION_FINISHED.getId(),
EntityPredicate.Composite.ANY
);
}
}

View file

@ -0,0 +1,38 @@
package org.betterx.betterend.api;
public interface BetterEndPlugin {
/**
* Alloying recipes registration.
* See AlloyingRecipe.Builder for details.
*/
default void registerAlloyingRecipes() {
}
/**
* Smithing recipes registration.
* See AnvilSmithingRecipe.Builder for details.
*/
default void registerSmithingRecipes() {
}
/**
* Additional biomes registration.
* See BiomeRegistry.registerBiome for details.
*/
default void registerEndBiomes() {
}
/**
* Register other mod stuff, for example, EndITEM_HAMMERS.
*/
default void registerOthers() {
}
static void register(BetterEndPlugin plugin) {
plugin.registerAlloyingRecipes();
plugin.registerSmithingRecipes();
plugin.registerEndBiomes();
plugin.registerOthers();
}
}

View file

@ -0,0 +1,27 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.items.BaseAnvilItem;
import org.betterx.betterend.blocks.basis.EndAnvilBlock;
import org.betterx.betterend.item.material.EndToolMaterial;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.BlockItem;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
public class AeterniumAnvil extends EndAnvilBlock {
public AeterniumAnvil() {
super(EndBlocks.AETERNIUM_BLOCK.defaultMaterialColor(), EndToolMaterial.AETERNIUM.getLevel());
}
@Override
public int getMaxDurability() {
return 8;
}
@Override
public BlockItem getCustomItem(ResourceLocation blockID, FabricItemSettings settings) {
return new BaseAnvilItem(this, settings.fireproof());
}
}

View file

@ -0,0 +1,30 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.interfaces.CustomItemProvider;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class AeterniumBlock extends BaseBlock implements CustomItemProvider {
public AeterniumBlock() {
super(FabricBlockSettings
.of(Material.METAL, MaterialColor.COLOR_GRAY)
.hardness(65F)
.resistance(1200F)
.requiresCorrectToolForDrops()
.sound(SoundType.NETHERITE_BLOCK)
);
}
@Override
public BlockItem getCustomItem(ResourceLocation blockID, FabricItemSettings settings) {
return new BlockItem(this, settings.fireproof());
}
}

View file

@ -0,0 +1,15 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.interfaces.tools.AddMineableAxe;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.material.Material;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class AmaranitaCapBlock extends BaseBlock implements AddMineableAxe {
public AmaranitaCapBlock() {
super(FabricBlockSettings.of(Material.WOOD).sound(SoundType.WOOD));
}
}

View file

@ -0,0 +1,22 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.interfaces.tools.AddMineableAxe;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.material.Material;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class AmaranitaHymenophoreBlock extends BaseBlock implements RenderLayerProvider, AddMineableAxe {
public AmaranitaHymenophoreBlock() {
super(FabricBlockSettings.of(Material.WOOD).sound(SoundType.WOOD));
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
}

View file

@ -1,12 +1,14 @@
package ru.betterend.blocks;
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseRotatedPillarBlock;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.material.MaterialColor;
import ru.bclib.blocks.BaseRotatedPillarBlock;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class AmaranitaStemBlock extends BaseRotatedPillarBlock {
public AmaranitaStemBlock() {
super(FabricBlockSettings.copyOf(Blocks.OAK_PLANKS).materialColor(MaterialColor.COLOR_LIGHT_GREEN));
super(FabricBlockSettings.copyOf(Blocks.OAK_PLANKS).mapColor(MaterialColor.COLOR_LIGHT_GREEN));
}
}

View file

@ -1,12 +1,14 @@
package ru.betterend.blocks;
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.material.MaterialColor;
import ru.bclib.blocks.BaseBlock;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class AmberBlock extends BaseBlock {
public AmberBlock() {
super(FabricBlockSettings.copyOf(Blocks.DIAMOND_BLOCK).materialColor(MaterialColor.COLOR_YELLOW));
super(FabricBlockSettings.copyOf(Blocks.DIAMOND_BLOCK).mapColor(MaterialColor.COLOR_YELLOW));
}
}

View file

@ -0,0 +1,89 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndParticles;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Collections;
import java.util.List;
public class AncientEmeraldIceBlock extends BaseBlock {
public AncientEmeraldIceBlock() {
super(FabricBlockSettings.copyOf(Blocks.BLUE_ICE).randomTicks());
}
@Override
@SuppressWarnings("deprecation")
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
Direction dir = BlocksHelper.randomDirection(random);
if (random.nextBoolean()) {
int x = MHelper.randRange(-2, 2, random);
int y = MHelper.randRange(-2, 2, random);
int z = MHelper.randRange(-2, 2, random);
BlockPos p = pos.offset(x, y, z);
if (world.getBlockState(p).is(Blocks.WATER)) {
world.setBlockAndUpdate(p, EndBlocks.EMERALD_ICE.defaultBlockState());
makeParticles(world, p, random);
}
}
pos = pos.relative(dir);
state = world.getBlockState(pos);
if (state.is(Blocks.WATER)) {
world.setBlockAndUpdate(pos, EndBlocks.EMERALD_ICE.defaultBlockState());
makeParticles(world, pos, random);
} else if (state.is(EndBlocks.EMERALD_ICE)) {
world.setBlockAndUpdate(pos, EndBlocks.DENSE_EMERALD_ICE.defaultBlockState());
makeParticles(world, pos, random);
}
}
private void makeParticles(ServerLevel world, BlockPos pos, RandomSource random) {
world.sendParticles(
EndParticles.SNOWFLAKE,
pos.getX() + 0.5,
pos.getY() + 0.5,
pos.getZ() + 0.5,
20,
0.5,
0.5,
0.5,
0
);
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL);
if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) != 0) {
return Collections.singletonList(new ItemStack(this));
} else {
return Collections.emptyList();
}
}
@Override
public void stepOn(Level level, BlockPos blockPos, BlockState blockState, Entity entity) {
super.stepOn(level, blockPos, blockState, entity);
entity.setIsInPowderSnow(true);
}
}

View file

@ -0,0 +1,134 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.CustomColorProvider;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.interfaces.tools.AddMineableHammer;
import org.betterx.bclib.interfaces.tools.AddMineablePickaxe;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.registry.EndItems;
import org.betterx.ui.ColorUtil;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.AbstractGlassBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import com.google.common.collect.Lists;
import java.util.List;
public class AuroraCrystalBlock extends AbstractGlassBlock implements RenderLayerProvider, CustomColorProvider, AddMineablePickaxe, AddMineableHammer {
public static final Vec3i[] COLORS;
private static final int MIN_DROP = 1;
private static final int MAX_DROP = 4;
public AuroraCrystalBlock() {
super(FabricBlockSettings
.of(Material.GLASS)
.hardness(1F)
.resistance(1F)
.luminance(15)
.noOcclusion()
.isSuffocating((state, world, pos) -> false)
.sound(SoundType.GLASS));
}
@Override
@Deprecated
public VoxelShape getVisualShape(
BlockState blockState,
BlockGetter blockGetter,
BlockPos blockPos,
CollisionContext collisionContext
) {
return this.getCollisionShape(blockState, blockGetter, blockPos, collisionContext);
}
@Override
public BlockColor getProvider() {
return (state, world, pos, tintIndex) -> {
if (pos == null) {
pos = BlockPos.ZERO;
}
long i = (long) pos.getX() + (long) pos.getY() + (long) pos.getZ();
double delta = i * 0.1;
int index = MHelper.floor(delta);
int index2 = (index + 1) & 3;
delta -= index;
index &= 3;
Vec3i color1 = COLORS[index];
Vec3i color2 = COLORS[index2];
int r = MHelper.floor(Mth.lerp(delta, color1.getX(), color2.getX()));
int g = MHelper.floor(Mth.lerp(delta, color1.getY(), color2.getY()));
int b = MHelper.floor(Mth.lerp(delta, color1.getZ(), color2.getZ()));
return ColorUtil.color(r, g, b);
};
}
@Override
public ItemColor getItemProvider() {
return (stack, tintIndex) -> {
return ColorUtil.color(COLORS[3].getX(), COLORS[3].getY(), COLORS[3].getZ());
};
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.TRANSLUCENT;
}
@Override
@SuppressWarnings("deprecation")
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && tool.isCorrectToolForDrops(state)) {
int count = 0;
int enchant = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool);
if (enchant > 0) {
return Lists.newArrayList(new ItemStack(this));
}
enchant = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, tool);
if (enchant > 0) {
int min = Mth.clamp(MIN_DROP + enchant, MIN_DROP, MAX_DROP);
int max = MAX_DROP + (enchant / Enchantments.BLOCK_FORTUNE.getMaxLevel());
if (min == max) {
return Lists.newArrayList(new ItemStack(EndItems.CRYSTAL_SHARDS, max));
}
count = MHelper.randRange(min, max, MHelper.RANDOM_SOURCE);
} else {
count = MHelper.randRange(MIN_DROP, MAX_DROP, MHelper.RANDOM_SOURCE);
}
return Lists.newArrayList(new ItemStack(EndItems.CRYSTAL_SHARDS, count));
}
return Lists.newArrayList();
}
static {
COLORS = new Vec3i[]{
new Vec3i(247, 77, 161),
new Vec3i(120, 184, 255),
new Vec3i(120, 255, 168),
new Vec3i(243, 58, 255)
};
}
}

View file

@ -0,0 +1,24 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.UpDownPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty;
public class BlueVineBlock extends UpDownPlantBlock {
public static final EnumProperty<BlockProperties.TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE;
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SHAPE);
}
@Override
protected boolean isTerrain(BlockState state) {
return state.getBlock() == EndBlocks.END_MOSS || state.getBlock() == EndBlocks.END_MYCELIUM;
}
}

View file

@ -0,0 +1,59 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.interfaces.tools.AddMineableAxe;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.Material;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class BlueVineLanternBlock extends BaseBlock implements AddMineableAxe {
public static final BooleanProperty NATURAL = BlockProperties.NATURAL;
public BlueVineLanternBlock() {
super(FabricBlockSettings.of(Material.WOOD)
.luminance(15)
.sound(SoundType.WART_BLOCK));
this.registerDefaultState(this.stateDefinition.any().setValue(NATURAL, false));
}
@Override
@SuppressWarnings("deprecation")
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
return !state.getValue(NATURAL) || world.getBlockState(pos.below()).getBlock() == EndBlocks.BLUE_VINE;
}
@Override
@SuppressWarnings("deprecation")
public BlockState updateShape(
BlockState state,
Direction facing,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
if (!canSurvive(state, world, pos)) {
return Blocks.AIR.defaultBlockState();
} else {
return state;
}
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(NATURAL);
}
}

View file

@ -0,0 +1,81 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock;
import org.betterx.betterend.blocks.basis.FurBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
public class BlueVineSeedBlock extends EndPlantWithAgeBlock {
public BlueVineSeedBlock() {
super(basePlantSettings().offsetType(BlockBehaviour.OffsetType.NONE));
}
@Override
public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) {
int height = MHelper.randRange(2, 5, random);
int h = BlocksHelper.upRay(world, pos, height + 2);
if (h < height + 1) {
return;
}
BlocksHelper.setWithoutUpdate(
world,
pos,
EndBlocks.BLUE_VINE.defaultBlockState()
.setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.BOTTOM)
);
for (int i = 1; i < height; i++) {
BlocksHelper.setWithoutUpdate(
world,
pos.above(i),
EndBlocks.BLUE_VINE.defaultBlockState()
.setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.MIDDLE)
);
}
BlocksHelper.setWithoutUpdate(
world,
pos.above(height),
EndBlocks.BLUE_VINE.defaultBlockState()
.setValue(BlockProperties.TRIPLE_SHAPE, BlockProperties.TripleShape.TOP)
);
placeLantern(world, pos.above(height + 1));
}
private void placeLantern(WorldGenLevel world, BlockPos pos) {
BlocksHelper.setWithoutUpdate(
world,
pos,
EndBlocks.BLUE_VINE_LANTERN.defaultBlockState().setValue(BlueVineLanternBlock.NATURAL, true)
);
for (Direction dir : BlocksHelper.HORIZONTAL) {
BlockPos p = pos.relative(dir);
if (world.isEmptyBlock(p)) {
BlocksHelper.setWithoutUpdate(
world,
p,
EndBlocks.BLUE_VINE_FUR.defaultBlockState().setValue(FurBlock.FACING, dir)
);
}
}
if (world.isEmptyBlock(pos.above())) {
BlocksHelper.setWithoutUpdate(
world,
pos.above(),
EndBlocks.BLUE_VINE_FUR.defaultBlockState().setValue(FurBlock.FACING, Direction.UP)
);
}
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.END_MOSS) || state.is(EndBlocks.END_MYCELIUM);
}
}

View file

@ -0,0 +1,54 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.EndPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import com.google.common.collect.Lists;
import java.util.List;
public class BoluxMushroomBlock extends EndPlantBlock {
private static final VoxelShape SHAPE = Block.box(1, 0, 1, 15, 9, 15);
public BoluxMushroomBlock() {
super(basePlantSettings(10).offsetType(BlockBehaviour.OffsetType.NONE));
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.RUTISCUS);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE;
}
@Override
public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) {
return false;
}
@Override
public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) {
return false;
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
return Lists.newArrayList(new ItemStack(this));
}
}

View file

@ -0,0 +1,108 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.MaterialColor;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import org.jetbrains.annotations.Nullable;
public class BrimstoneBlock extends BaseBlock {
public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVE;
public BrimstoneBlock() {
super(FabricBlockSettings.copyOf(Blocks.END_STONE).mapColor(MaterialColor.COLOR_BROWN).randomTicks());
registerDefaultState(stateDefinition.any().setValue(ACTIVATED, false));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(ACTIVATED);
}
@Override
public void setPlacedBy(
Level world,
BlockPos pos,
BlockState state,
@Nullable LivingEntity placer,
ItemStack itemStack
) {
if (world.isClientSide()) {
updateChunks((ClientLevel) world, pos);
}
}
public void destroy(LevelAccessor world, BlockPos pos, BlockState state) {
if (world.isClientSide()) {
updateChunks((ClientLevel) world, pos);
}
}
private void updateChunks(ClientLevel world, BlockPos pos) {
int y = pos.getY() >> 4;
int x1 = (pos.getX() - 2) >> 4;
int z1 = (pos.getZ() - 2) >> 4;
int x2 = (pos.getX() + 2) >> 4;
int z2 = (pos.getZ() + 2) >> 4;
for (int x = x1; x <= x2; x++) {
for (int z = z1; z <= z2; z++) {
world.setSectionDirtyWithNeighbors(x, y, z);
}
}
}
@Override
@SuppressWarnings("deprecation")
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
boolean deactivate = true;
for (Direction dir : BlocksHelper.DIRECTIONS) {
if (world.getFluidState(pos.relative(dir)).getType().equals(Fluids.WATER)) {
deactivate = false;
break;
}
}
if (state.getValue(ACTIVATED)) {
if (deactivate) {
world.setBlockAndUpdate(pos, defaultBlockState().setValue(ACTIVATED, false));
} else if (state.getValue(ACTIVATED) && random.nextInt(16) == 0) {
Direction dir = BlocksHelper.randomDirection(random);
BlockPos side = pos.relative(dir);
BlockState sideState = world.getBlockState(side);
if (sideState.getBlock() instanceof SulphurCrystalBlock) {
if (sideState.getValue(SulphurCrystalBlock.AGE) < 2 && sideState.getValue(SulphurCrystalBlock.WATERLOGGED)) {
int age = sideState.getValue(SulphurCrystalBlock.AGE) + 1;
world.setBlockAndUpdate(side, sideState.setValue(SulphurCrystalBlock.AGE, age));
}
} else if (sideState.getFluidState().getType() == Fluids.WATER) {
BlockState crystal = EndBlocks.SULPHUR_CRYSTAL.defaultBlockState()
.setValue(SulphurCrystalBlock.FACING, dir)
.setValue(SulphurCrystalBlock.WATERLOGGED, true)
.setValue(SulphurCrystalBlock.AGE, 0);
world.setBlockAndUpdate(side, crystal);
}
}
} else if (!deactivate && !state.getValue(ACTIVATED)) {
world.setBlockAndUpdate(pos, defaultBlockState().setValue(ACTIVATED, true));
}
}
}

View file

@ -0,0 +1,54 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.interfaces.tools.AddMineableShears;
import org.betterx.betterend.blocks.basis.EndUnderwaterPlantBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
public class BubbleCoralBlock extends EndUnderwaterPlantBlock implements AddMineableShears {
private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 14, 16);
public BubbleCoralBlock() {
super(baseUnderwaterPlantSettings()
.sound(SoundType.CORAL_BLOCK)
.offsetType(BlockBehaviour.OffsetType.NONE)
);
}
@Environment(EnvType.CLIENT)
public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {
double x = pos.getX() + random.nextDouble();
double y = pos.getY() + random.nextDouble() * 0.5F + 0.5F;
double z = pos.getZ() + random.nextDouble();
world.addParticle(ParticleTypes.BUBBLE, x, y, z, 0.0D, 0.0D, 0.0D);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE;
}
@Override
public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) {
return false;
}
@Override
public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) {
return false;
}
}

View file

@ -0,0 +1,49 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseVineBlock;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndItems;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext;
import com.google.common.collect.Lists;
import java.util.List;
public class BulbVineBlock extends BaseVineBlock {
public BulbVineBlock() {
super(15, true);
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
if (state.getValue(SHAPE) == TripleShape.BOTTOM) {
return Lists.newArrayList(new ItemStack(EndItems.GLOWING_BULB));
} else if (MHelper.RANDOM.nextInt(8) == 0) {
return Lists.newArrayList(new ItemStack(EndBlocks.BULB_VINE_SEED));
} else {
return Lists.newArrayList();
}
}
@Override
public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) {
return false;
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
boolean canPlace = super.canSurvive(state, world, pos);
return (state.is(this) && state.getValue(SHAPE) == TripleShape.BOTTOM)
? canPlace
: canPlace && world.getBlockState(
pos.below()).is(this);
}
}

View file

@ -0,0 +1,87 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.client.models.ModelsHelper;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.BlockModelProvider;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.interfaces.tools.AddMineablePickaxe;
import org.betterx.betterend.blocks.basis.EndLanternBlock;
import org.betterx.betterend.client.models.Patterns;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import com.google.common.collect.Maps;
import java.util.Map;
import java.util.Optional;
import org.jetbrains.annotations.Nullable;
public class BulbVineLanternBlock extends EndLanternBlock implements RenderLayerProvider, BlockModelProvider, AddMineablePickaxe {
private static final VoxelShape SHAPE_CEIL = Block.box(4, 4, 4, 12, 16, 12);
private static final VoxelShape SHAPE_FLOOR = Block.box(4, 0, 4, 12, 12, 12);
public BulbVineLanternBlock() {
this(FabricBlockSettings.of(Material.METAL)
.hardness(1)
.resistance(1)
.mapColor(MaterialColor.COLOR_LIGHT_GRAY)
.luminance(15)
.requiresCorrectToolForDrops()
.sound(SoundType.LANTERN));
}
public BulbVineLanternBlock(Properties settings) {
super(settings);
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return state.getValue(IS_FLOOR) ? SHAPE_FLOOR : SHAPE_CEIL;
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
@Environment(EnvType.CLIENT)
public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) {
Map<String, String> textures = Maps.newHashMap();
textures.put("%glow%", getGlowTexture());
textures.put("%metal%", getMetalTexture(resourceLocation));
Optional<String> pattern = blockState.getValue(IS_FLOOR)
? Patterns.createJson(
Patterns.BLOCK_BULB_LANTERN_FLOOR,
textures
)
: Patterns.createJson(Patterns.BLOCK_BULB_LANTERN_CEIL, textures);
return ModelsHelper.fromPattern(pattern);
}
protected String getMetalTexture(ResourceLocation blockId) {
String name = blockId.getPath();
name = name.substring(0, name.indexOf('_'));
return name + "_bulb_vine_lantern_metal";
}
protected String getGlowTexture() {
return "bulb_vine_lantern_bulb";
}
}

View file

@ -0,0 +1,40 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.interfaces.CustomColorProvider;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.ui.ColorUtil;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.item.ItemColor;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class BulbVineLanternColoredBlock extends BulbVineLanternBlock implements CustomColorProvider {
public BulbVineLanternColoredBlock(FabricBlockSettings settings) {
super(settings);
}
@Override
public BlockColor getProvider() {
return (state, world, pos, tintIndex) -> getColor();
}
@Override
public ItemColor getItemProvider() {
return (stack, tintIndex) -> getColor();
}
private int getColor() {
int color = BlocksHelper.getBlockColor(this);
int b = (color & 255);
int g = ((color >> 8) & 255);
int r = ((color >> 16) & 255);
float[] hsv = ColorUtil.RGBtoHSB(r, g, b, new float[3]);
return ColorUtil.HSBtoRGB(hsv[0], hsv[1], hsv[1] > 0.2 ? 1 : hsv[2]);
}
@Override
protected String getGlowTexture() {
return "bulb_vine_lantern_overlay";
}
}

View file

@ -0,0 +1,49 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import net.minecraft.core.BlockPos;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.state.BlockState;
public class BulbVineSeedBlock extends EndPlantWithAgeBlock {
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState up = world.getBlockState(pos.above());
return up.is(CommonBlockTags.GEN_END_STONES) || up.is(BlockTags.LOGS) || up.is(BlockTags.LEAVES);
}
@Override
public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) {
int h = BlocksHelper.downRay(world, pos, random.nextInt(24)) - 1;
if (h > 2) {
BlocksHelper.setWithoutUpdate(
world,
pos,
EndBlocks.BULB_VINE.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP)
);
for (int i = 1; i < h; i++) {
BlocksHelper.setWithoutUpdate(
world,
pos.below(i),
EndBlocks.BULB_VINE.defaultBlockState()
.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE)
);
}
BlocksHelper.setWithoutUpdate(
world,
pos.below(h),
EndBlocks.BULB_VINE.defaultBlockState().setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM)
);
}
}
}

View file

@ -0,0 +1,72 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlockNotFull;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Collections;
import java.util.List;
public class CavePumpkinBlock extends BaseBlockNotFull implements RenderLayerProvider {
public static final BooleanProperty SMALL = BlockProperties.SMALL;
private static final VoxelShape SHAPE_SMALL;
private static final VoxelShape SHAPE_BIG;
public CavePumpkinBlock() {
super(FabricBlockSettings.copyOf(Blocks.PUMPKIN).luminance((state) -> state.getValue(SMALL) ? 10 : 15));
registerDefaultState(defaultBlockState().setValue(SMALL, false));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SMALL);
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
return state.getValue(SMALL) ? SHAPE_SMALL : SHAPE_BIG;
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
return state.getValue(SMALL)
? Collections.singletonList(new ItemStack(EndBlocks.CAVE_PUMPKIN_SEED))
: Collections
.singletonList(new ItemStack(this));
}
static {
VoxelShape lantern = Block.box(1, 0, 1, 15, 13, 15);
VoxelShape cap = Block.box(0, 12, 0, 16, 15, 16);
VoxelShape top = Block.box(5, 15, 5, 11, 16, 11);
SHAPE_BIG = Shapes.or(lantern, cap, top);
lantern = Block.box(5, 7, 5, 11, 13, 11);
cap = Block.box(4, 12, 4, 12, 15, 12);
top = Block.box(6, 15, 6, 10, 16, 10);
SHAPE_SMALL = Shapes.or(lantern, cap, top);
}
}

View file

@ -0,0 +1,81 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class CavePumpkinVineBlock extends EndPlantWithAgeBlock {
public CavePumpkinVineBlock() {
super(basePlantSettings().offsetType(BlockBehaviour.OffsetType.NONE));
}
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 16, 12);
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState down = world.getBlockState(pos.above());
return isTerrain(down);
}
@Override
public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
int age = state.getValue(AGE);
BlockState down = world.getBlockState(pos.below());
if (down.getMaterial()
.isReplaceable() || (down.is(EndBlocks.CAVE_PUMPKIN) && down.getValue(BlockProperties.SMALL))) {
if (age < 3) {
world.setBlockAndUpdate(pos, state.setValue(AGE, age + 1));
}
if (age == 2) {
world.setBlockAndUpdate(
pos.below(),
EndBlocks.CAVE_PUMPKIN.defaultBlockState().setValue(BlockProperties.SMALL, true)
);
} else if (age == 3) {
world.setBlockAndUpdate(pos.below(), EndBlocks.CAVE_PUMPKIN.defaultBlockState());
}
}
}
@Override
public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) {
}
@Override
public BlockState updateShape(
BlockState state,
Direction facing,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
state = super.updateShape(state, facing, neighborState, world, pos, neighborPos);
if (state.is(this) && state.getValue(BlockProperties.AGE) > 1) {
BlockState down = world.getBlockState(pos.below());
if (!down.is(EndBlocks.CAVE_PUMPKIN)) {
state = state.setValue(BlockProperties.AGE, 1);
}
}
return state;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE;
}
}

View file

@ -0,0 +1,120 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseAttachedBlock;
import org.betterx.bclib.client.models.ModelsHelper;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.BlockModelProvider;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.betterend.client.models.Patterns;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.BlockModelRotation;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import com.google.common.collect.Maps;
import java.util.EnumMap;
import java.util.Map;
import java.util.Optional;
import org.jetbrains.annotations.Nullable;
public class ChandelierBlock extends BaseAttachedBlock implements RenderLayerProvider, BlockModelProvider {
private static final EnumMap<Direction, VoxelShape> BOUNDING_SHAPES = Maps.newEnumMap(Direction.class);
public ChandelierBlock(Block source) {
super(FabricBlockSettings.copyOf(source)
.luminance(15)
.noCollission()
.noOcclusion()
.requiresCorrectToolForDrops());
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return BOUNDING_SHAPES.get(state.getValue(FACING));
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation blockId) {
return ModelsHelper.createItemModel(blockId);
}
@Override
@Environment(EnvType.CLIENT)
public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) {
Optional<String> pattern;
switch (blockState.getValue(FACING)) {
case UP:
pattern = Patterns.createJson(Patterns.BLOCK_CHANDELIER_FLOOR, resourceLocation.getPath());
break;
case DOWN:
pattern = Patterns.createJson(Patterns.BLOCK_CHANDELIER_CEIL, resourceLocation.getPath());
break;
default:
pattern = Patterns.createJson(Patterns.BLOCK_CHANDELIER_WALL, resourceLocation.getPath());
}
return ModelsHelper.fromPattern(pattern);
}
@Override
@Environment(EnvType.CLIENT)
public UnbakedModel getModelVariant(
ResourceLocation stateId,
BlockState blockState,
Map<ResourceLocation, UnbakedModel> modelCache
) {
String state = "_wall";
BlockModelRotation rotation = BlockModelRotation.X0_Y0;
switch (blockState.getValue(FACING)) {
case UP:
state = "_floor";
break;
case DOWN:
state = "_ceil";
break;
case EAST:
rotation = BlockModelRotation.X0_Y270;
break;
case NORTH:
rotation = BlockModelRotation.X0_Y180;
break;
case WEST:
rotation = BlockModelRotation.X0_Y90;
break;
default:
break;
}
ResourceLocation modelId = new ResourceLocation(stateId.getNamespace(), "block/" + stateId.getPath() + state);
registerBlockModel(stateId, modelId, blockState, modelCache);
return ModelsHelper.createMultiVariant(modelId, rotation.getRotation(), false);
}
static {
BOUNDING_SHAPES.put(Direction.UP, Block.box(5, 0, 5, 11, 13, 11));
BOUNDING_SHAPES.put(Direction.DOWN, Block.box(5, 3, 5, 11, 16, 11));
BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.0, 0.0, 0.5, 1.0, 1.0, 1.0));
BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 0.5));
BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.0, 0.0, 1.0, 1.0, 1.0));
BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.0, 0.0, 0.5, 1.0, 1.0));
}
}

View file

@ -0,0 +1,19 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.interfaces.Fuel;
import net.minecraft.world.level.block.Blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class CharcoalBlock extends BaseBlock implements Fuel {
public CharcoalBlock() {
super(FabricBlockSettings.copyOf(Blocks.COAL_BLOCK));
}
@Override
public int getFuelTime() {
return 16000;
}
}

View file

@ -0,0 +1,17 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.EndUnderwaterPlantBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluids;
public class CharniaBlock extends EndUnderwaterPlantBlock {
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
return canSupportCenter(world, pos.below(), Direction.UP) && world.getFluidState(pos).getType() == Fluids.WATER;
}
}

View file

@ -0,0 +1,17 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.EndPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.world.level.block.state.BlockState;
public class ChorusGrassBlock extends EndPlantBlock {
public ChorusGrassBlock() {
super(true);
}
@Override
protected boolean isTerrain(BlockState state) {
return state.getBlock() == EndBlocks.CHORUS_NYLIUM;
}
}

View file

@ -0,0 +1,122 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class CrystalMossCoverBlock extends MultifaceBlock implements BonemealableBlock, SimpleWaterloggedBlock, RenderLayerProvider {
private static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
private final MultifaceSpreader spreader = new MultifaceSpreader(this);
public CrystalMossCoverBlock(MaterialColor color) {
super(FabricBlockSettings.of(Material.REPLACEABLE_PLANT, color)
.noCollission()
.strength(0.2f)
.sound(SoundType.GLOW_LICHEN)
.lightLevel(GlowLichenBlock.emission(7)));
this.registerDefaultState(this.defaultBlockState().setValue(WATERLOGGED, false));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(WATERLOGGED);
}
@Override
public BlockState updateShape(
BlockState blockState,
Direction direction,
BlockState blockState2,
LevelAccessor levelAccessor,
BlockPos blockPos,
BlockPos blockPos2
) {
if (blockState.getValue(WATERLOGGED).booleanValue()) {
levelAccessor.scheduleTick(blockPos, Fluids.WATER, Fluids.WATER.getTickDelay(levelAccessor));
}
return super.updateShape(blockState, direction, blockState2, levelAccessor, blockPos, blockPos2);
}
@Override
public boolean canBeReplaced(BlockState blockState, BlockPlaceContext blockPlaceContext) {
return !blockPlaceContext.getItemInHand().is(EndBlocks.CRYSTAL_MOSS_COVER.asItem()) || super.canBeReplaced(
blockState,
blockPlaceContext
);
}
@Override
public boolean isValidBonemealTarget(
BlockGetter blockGetter,
BlockPos blockPos,
BlockState blockState,
boolean bl
) {
return Direction.stream()
.anyMatch(direction -> this.spreader.canSpreadInAnyDirection(
blockState,
blockGetter,
blockPos,
direction.getOpposite()
));
}
@Override
public boolean isBonemealSuccess(Level level, RandomSource randomSource, BlockPos blockPos, BlockState blockState) {
return true;
}
@Override
public void performBonemeal(
ServerLevel serverLevel,
RandomSource randomSource,
BlockPos blockPos,
BlockState blockState
) {
this.spreader.spreadFromRandomFaceTowardRandomDirection(blockState, serverLevel, blockPos, randomSource);
}
@Override
public FluidState getFluidState(BlockState blockState) {
if (blockState.getValue(WATERLOGGED).booleanValue()) {
return Fluids.WATER.getSource(false);
}
return super.getFluidState(blockState);
}
@Override
public boolean propagatesSkylightDown(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos) {
return blockState.getFluidState().isEmpty();
}
@Override
public MultifaceSpreader getSpreader() {
return this.spreader;
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
}

View file

@ -0,0 +1,39 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Collections;
import java.util.List;
public class DenseEmeraldIceBlock extends BaseBlock implements RenderLayerProvider {
public DenseEmeraldIceBlock() {
super(FabricBlockSettings.copyOf(Blocks.PACKED_ICE));
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.TRANSLUCENT;
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL);
if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) != 0) {
return Collections.singletonList(new ItemStack(this));
} else {
return Collections.emptyList();
}
}
}

View file

@ -1,9 +1,11 @@
package ru.betterend.blocks;
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.material.Material;
import ru.bclib.blocks.BaseBlock;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class DenseSnowBlock extends BaseBlock {
public DenseSnowBlock() {

View file

@ -0,0 +1,28 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.PottableFeatureSapling;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndFeatures;
import org.betterx.betterend.world.features.trees.DragonTreeFeature;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public class DragonTreeSaplingBlock extends PottableFeatureSapling<DragonTreeFeature, NoneFeatureConfiguration> {
public DragonTreeSaplingBlock() {
super((state) -> EndFeatures.DRAGON_TREE.configuredFeature);
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
return world.getBlockState(pos.below()).is(EndBlocks.SHADOW_GRASS);
}
@Override
public boolean canPlantOn(Block block) {
return block == EndBlocks.SHADOW_GRASS;
}
}

View file

@ -0,0 +1,102 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.BlockModelProvider;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.HalfTransparentBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Collections;
import java.util.List;
import org.jetbrains.annotations.Nullable;
public class EmeraldIceBlock extends HalfTransparentBlock implements RenderLayerProvider, BlockModelProvider {
public EmeraldIceBlock() {
super(FabricBlockSettings.copyOf(Blocks.ICE));
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.TRANSLUCENT;
}
@Override
public void playerDestroy(
Level world,
Player player,
BlockPos pos,
BlockState state,
@Nullable BlockEntity blockEntity,
ItemStack stack
) {
super.playerDestroy(world, player, pos, state, blockEntity, stack);
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) == 0) {
if (world.dimensionType().ultraWarm()) {
world.removeBlock(pos, false);
return;
}
Material material = world.getBlockState(pos.below()).getMaterial();
if (material.blocksMotion() || material.isLiquid()) {
world.setBlockAndUpdate(pos, Blocks.WATER.defaultBlockState());
}
}
}
@Override
@SuppressWarnings("deprecation")
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (world.getBrightness(LightLayer.BLOCK, pos) > 11 - state.getLightBlock(world, pos)) {
this.melt(state, world, pos);
}
}
protected void melt(BlockState state, Level world, BlockPos pos) {
if (world.dimensionType().ultraWarm()) {
world.removeBlock(pos, false);
} else {
world.setBlockAndUpdate(pos, Blocks.WATER.defaultBlockState());
world.neighborChanged(pos, Blocks.WATER, pos);
}
}
@Override
@SuppressWarnings("deprecation")
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getOptionalParameter(LootContextParams.TOOL);
if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) != 0) {
return Collections.singletonList(new ItemStack(this));
} else {
return Collections.emptyList();
}
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) {
return getBlockModel(resourceLocation, defaultBlockState());
}
}

View file

@ -0,0 +1,131 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.betterend.registry.EndPortals;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
public class EndBlockProperties extends BlockProperties {
public static final EnumProperty<HydraluxShape> HYDRALUX_SHAPE = EnumProperty.create("shape", HydraluxShape.class);
public static final EnumProperty<PedestalState> PEDESTAL_STATE = EnumProperty.create("state", PedestalState.class);
public static final EnumProperty<CactusBottom> CACTUS_BOTTOM = EnumProperty.create("bottom", CactusBottom.class);
public static final IntegerProperty PORTAL = IntegerProperty.create("portal", 0, EndPortals.getCount());
public static final IntegerProperty PLANT_ID = IntegerProperty.create("plant_id", 0, 63);
public static final IntegerProperty SOIL_ID = IntegerProperty.create("soil_id", 0, 16);
public static final IntegerProperty POT_LIGHT = IntegerProperty.create("pot_light", 0, 3);
public static final BooleanProperty HAS_ITEM = BooleanProperty.create("has_item");
public enum PedestalState implements StringRepresentable {
PEDESTAL_TOP("pedestal_top"),
COLUMN_TOP("column_top"),
BOTTOM("bottom"),
PILLAR("pillar"),
COLUMN("column"),
DEFAULT("default");
private final String name;
PedestalState(String name) {
this.name = name;
}
@Override
public String getSerializedName() {
return this.name;
}
@Override
public String toString() {
return this.name;
}
}
public enum HydraluxShape implements StringRepresentable {
FLOWER_BIG_BOTTOM("flower_big_bottom", true),
FLOWER_BIG_TOP("flower_big_top", true),
FLOWER_SMALL_BOTTOM("flower_small_bottom", true),
FLOWER_SMALL_TOP("flower_small_top", true),
VINE("vine", false),
ROOTS("roots", false);
private final String name;
private final boolean glow;
HydraluxShape(String name, boolean glow) {
this.name = name;
this.glow = glow;
}
@Override
public String getSerializedName() {
return name;
}
@Override
public String toString() {
return name;
}
public boolean hasGlow() {
return glow;
}
}
public enum LumecornShape implements StringRepresentable {
LIGHT_TOP("light_top", 15),
LIGHT_TOP_MIDDLE("light_top_middle", 15),
LIGHT_MIDDLE("light_middle", 15),
LIGHT_BOTTOM("light_bottom", 15),
MIDDLE("middle", 0),
BOTTOM_BIG("bottom_big", 0),
BOTTOM_SMALL("bottom_small", 0);
private final String name;
private final int light;
LumecornShape(String name, int light) {
this.name = name;
this.light = light;
}
@Override
public String getSerializedName() {
return name;
}
@Override
public String toString() {
return name;
}
public int getLight() {
return light;
}
}
public enum CactusBottom implements StringRepresentable {
EMPTY("empty"),
SAND("sand"),
MOSS("moss");
private final String name;
CactusBottom(String name) {
this.name = name;
}
@Override
public String getSerializedName() {
return name;
}
@Override
public String toString() {
return name;
}
}
}

View file

@ -0,0 +1,125 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.interfaces.tools.AddMineableShears;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.blocks.basis.EndUnderwaterPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndItems;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.List;
public class EndLilyBlock extends EndUnderwaterPlantBlock implements AddMineableShears {
public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE;
private static final VoxelShape SHAPE_BOTTOM = Block.box(4, 0, 4, 12, 16, 12);
private static final VoxelShape SHAPE_TOP = Block.box(2, 0, 2, 14, 6, 14);
public EndLilyBlock() {
super(baseUnderwaterPlantSettings()
.lightLevel((state) -> state.getValue(SHAPE) == TripleShape.TOP ? 13 : 0)
);
}
@Override
public BlockState updateShape(
BlockState state,
Direction facing,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
if (!canSurvive(state, world, pos)) {
return state.getValue(SHAPE) == TripleShape.TOP
? Blocks.AIR.defaultBlockState()
: Blocks.WATER.defaultBlockState();
} else {
return state;
}
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
Vec3 vec3d = state.getOffset(view, pos);
VoxelShape shape = state.getValue(SHAPE) == TripleShape.TOP ? SHAPE_TOP : SHAPE_BOTTOM;
return shape.move(vec3d.x, vec3d.y, vec3d.z);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SHAPE);
}
@Override
public FluidState getFluidState(BlockState state) {
return state.getValue(SHAPE) == TripleShape.TOP ? Fluids.EMPTY.defaultFluidState() : Fluids.WATER.getSource(
false);
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
if (state.getValue(SHAPE) == TripleShape.TOP) {
return world.getBlockState(pos.below()).getBlock() == this;
} else if (state.getValue(SHAPE) == TripleShape.BOTTOM) {
return isTerrain(world.getBlockState(pos.below()));
} else {
BlockState up = world.getBlockState(pos.above());
BlockState down = world.getBlockState(pos.below());
return up.getBlock() == this && down.getBlock() == this;
}
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
if (state.getValue(SHAPE) == TripleShape.TOP) {
return Lists.newArrayList(
new ItemStack(EndItems.END_LILY_LEAF, MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE)),
new ItemStack(EndBlocks.END_LILY_SEED, MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE))
);
}
return Collections.emptyList();
}
@Override
@Environment(EnvType.CLIENT)
public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) {
return new ItemStack(EndBlocks.END_LILY_SEED);
}
@Override
public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) {
return false;
}
@Override
public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) {
return false;
}
}

View file

@ -0,0 +1,53 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.blocks.UnderwaterPlantWithAgeBlock;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluids;
public class EndLilySeedBlock extends UnderwaterPlantWithAgeBlock {
@Override
public void grow(WorldGenLevel world, RandomSource random, BlockPos pos) {
if (canGrow(world, pos)) {
BlocksHelper.setWithoutUpdate(
world,
pos,
EndBlocks.END_LILY.defaultBlockState().setValue(EndLilyBlock.SHAPE, TripleShape.BOTTOM)
);
BlockPos up = pos.above();
while (world.getFluidState(up).isSource()) {
BlocksHelper.setWithoutUpdate(
world,
up,
EndBlocks.END_LILY.defaultBlockState().setValue(EndLilyBlock.SHAPE, TripleShape.MIDDLE)
);
up = up.above();
}
BlocksHelper.setWithoutUpdate(
world,
up,
EndBlocks.END_LILY.defaultBlockState().setValue(EndLilyBlock.SHAPE, TripleShape.TOP)
);
}
}
private boolean canGrow(WorldGenLevel world, BlockPos pos) {
BlockPos up = pos.above();
while (world.getBlockState(up).getFluidState().getType().equals(Fluids.WATER.getSource())) {
up = up.above();
}
return world.isEmptyBlock(up);
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(CommonBlockTags.END_STONES);
}
}

View file

@ -0,0 +1,60 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.blocks.basis.EndPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import com.google.common.collect.Lists;
import java.util.List;
public class EndLotusFlowerBlock extends EndPlantBlock {
private static final VoxelShape SHAPE_OUTLINE = Block.box(2, 0, 2, 14, 14, 14);
private static final VoxelShape SHAPE_COLLISION = Block.box(0, 0, 0, 16, 2, 16);
public EndLotusFlowerBlock() {
//TODO: 1.19 Test if we can remove dynamic shape and offsetType
super(basePlantSettings(15).offsetType(BlockBehaviour.OffsetType.NONE));
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.END_LOTUS_STEM);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE_OUTLINE;
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE_COLLISION;
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
int count = MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE);
return Lists.newArrayList(new ItemStack(EndBlocks.END_LOTUS_SEED, count));
}
@Override
@Environment(EnvType.CLIENT)
public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) {
return new ItemStack(EndBlocks.END_LOTUS_SEED);
}
}

View file

@ -0,0 +1,82 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlockNotFull;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.WaterFluid;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class EndLotusLeafBlock extends BaseBlockNotFull implements RenderLayerProvider {
public static final EnumProperty<Direction> HORIZONTAL_FACING = BlockStateProperties.HORIZONTAL_FACING;
public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE;
private static final VoxelShape VSHAPE = Block.box(0, 0, 0, 16, 1, 16);
public EndLotusLeafBlock() {
super(FabricBlockSettings.of(Material.PLANT).noOcclusion().sound(SoundType.WET_GRASS));
}
@Override
@SuppressWarnings("deprecation")
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState down = world.getBlockState(pos.below());
return !down.getFluidState().isEmpty() && down.getFluidState().getType() instanceof WaterFluid;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(SHAPE, HORIZONTAL_FACING);
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return VSHAPE;
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, Rotation rotation) {
return BlocksHelper.rotateHorizontal(state, rotation, HORIZONTAL_FACING);
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, Mirror mirror) {
return BlocksHelper.mirrorHorizontal(state, mirror, HORIZONTAL_FACING);
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
@Environment(EnvType.CLIENT)
public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) {
return new ItemStack(EndBlocks.END_LOTUS_SEED);
}
}

View file

@ -0,0 +1,138 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.blocks.UnderwaterPlantWithAgeBlock;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluids;
public class EndLotusSeedBlock extends UnderwaterPlantWithAgeBlock {
@Override
public void grow(WorldGenLevel world, RandomSource random, BlockPos pos) {
if (canGrow(world, pos)) {
BlockState startLeaf = EndBlocks.END_LOTUS_STEM.defaultBlockState().setValue(EndLotusStemBlock.LEAF, true);
BlockState roots = EndBlocks.END_LOTUS_STEM.defaultBlockState()
.setValue(EndLotusStemBlock.SHAPE, TripleShape.BOTTOM)
.setValue(EndLotusStemBlock.WATERLOGGED, true);
BlockState stem = EndBlocks.END_LOTUS_STEM.defaultBlockState();
BlockState flower = EndBlocks.END_LOTUS_FLOWER.defaultBlockState();
BlocksHelper.setWithoutUpdate(world, pos, roots);
MutableBlockPos bpos = new MutableBlockPos().set(pos);
bpos.setY(bpos.getY() + 1);
while (world.getFluidState(bpos).isSource()) {
BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.WATERLOGGED, true));
bpos.setY(bpos.getY() + 1);
}
int height = random.nextBoolean() ? 0 : random.nextBoolean() ? 1 : random.nextBoolean() ? 1 : -1;
TripleShape shape = (height == 0) ? TripleShape.TOP : TripleShape.MIDDLE;
Direction dir = BlocksHelper.randomHorizontal(random);
BlockPos leafCenter = bpos.immutable().relative(dir);
if (hasLeaf(world, leafCenter)) {
generateLeaf(world, leafCenter);
BlocksHelper.setWithoutUpdate(
world,
bpos,
startLeaf.setValue(EndLotusStemBlock.SHAPE, shape).setValue(EndLotusStemBlock.FACING, dir)
);
} else {
BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.SHAPE, shape));
}
bpos.setY(bpos.getY() + 1);
for (int i = 1; i <= height; i++) {
if (!world.isEmptyBlock(bpos)) {
bpos.setY(bpos.getY() - 1);
BlocksHelper.setWithoutUpdate(world, bpos, flower);
bpos.setY(bpos.getY() - 1);
stem = world.getBlockState(bpos);
BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.SHAPE, TripleShape.TOP));
return;
}
BlocksHelper.setWithoutUpdate(world, bpos, stem);
bpos.setY(bpos.getY() + 1);
}
if (!world.isEmptyBlock(bpos) || height < 0) {
bpos.setY(bpos.getY() - 1);
}
BlocksHelper.setWithoutUpdate(world, bpos, flower);
bpos.setY(bpos.getY() - 1);
stem = world.getBlockState(bpos);
if (!stem.is(EndBlocks.END_LOTUS_STEM)) {
stem = EndBlocks.END_LOTUS_STEM.defaultBlockState();
if (!world.getBlockState(bpos.north()).getFluidState().isEmpty()) {
stem = stem.setValue(EndLotusStemBlock.WATERLOGGED, true);
}
}
if (world.getBlockState(bpos.relative(dir)).is(EndBlocks.END_LOTUS_LEAF)) {
stem = stem.setValue(EndLotusStemBlock.LEAF, true).setValue(EndLotusStemBlock.FACING, dir);
}
BlocksHelper.setWithoutUpdate(world, bpos, stem.setValue(EndLotusStemBlock.SHAPE, TripleShape.TOP));
}
}
private boolean canGrow(WorldGenLevel world, BlockPos pos) {
MutableBlockPos bpos = new MutableBlockPos();
bpos.set(pos);
while (world.getBlockState(bpos).getFluidState().getType().equals(Fluids.WATER.getSource())) {
bpos.setY(bpos.getY() + 1);
}
return world.isEmptyBlock(bpos) && world.isEmptyBlock(bpos.above());
}
private void generateLeaf(WorldGenLevel world, BlockPos pos) {
MutableBlockPos p = new MutableBlockPos();
BlockState leaf = EndBlocks.END_LOTUS_LEAF.defaultBlockState();
BlocksHelper.setWithoutUpdate(world, pos, leaf.setValue(EndLotusLeafBlock.SHAPE, TripleShape.BOTTOM));
for (Direction move : BlocksHelper.HORIZONTAL) {
BlocksHelper.setWithoutUpdate(
world,
p.set(pos).move(move),
leaf.setValue(EndLotusLeafBlock.HORIZONTAL_FACING, move)
.setValue(EndLotusLeafBlock.SHAPE, TripleShape.MIDDLE)
);
}
for (int i = 0; i < 4; i++) {
Direction d1 = BlocksHelper.HORIZONTAL[i];
Direction d2 = BlocksHelper.HORIZONTAL[(i + 1) & 3];
BlocksHelper.setWithoutUpdate(
world,
p.set(pos).move(d1).move(d2),
leaf.setValue(EndLotusLeafBlock.HORIZONTAL_FACING, d1)
.setValue(EndLotusLeafBlock.SHAPE, TripleShape.TOP)
);
}
}
private boolean hasLeaf(WorldGenLevel world, BlockPos pos) {
MutableBlockPos p = new MutableBlockPos();
p.setY(pos.getY());
int count = 0;
for (int x = -1; x < 2; x++) {
p.setX(pos.getX() + x);
for (int z = -1; z < 2; z++) {
p.setZ(pos.getZ() + z);
if (world.isEmptyBlock(p) && !world.getFluidState(p.below()).isEmpty()) count++;
}
}
return count == 9;
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(CommonBlockTags.END_STONES);
}
}

View file

@ -0,0 +1,112 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.util.BlocksHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import com.google.common.collect.Maps;
import java.util.Map;
public class EndLotusStemBlock extends BaseBlock implements SimpleWaterloggedBlock, RenderLayerProvider {
public static final EnumProperty<Direction> FACING = BlockStateProperties.FACING;
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
public static final BooleanProperty LEAF = BooleanProperty.create("leaf");
public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE;
private static final Map<Axis, VoxelShape> SHAPES = Maps.newEnumMap(Axis.class);
public EndLotusStemBlock() {
super(FabricBlockSettings.copyOf(Blocks.OAK_PLANKS));
this.registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)
.setValue(SHAPE, TripleShape.MIDDLE)
.setValue(LEAF, false)
.setValue(FACING, Direction.UP));
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return state.getValue(LEAF) ? SHAPES.get(Axis.Y) : SHAPES.get(state.getValue(FACING).getAxis());
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(FACING, WATERLOGGED, SHAPE, LEAF);
}
@Override
@SuppressWarnings("deprecation")
public FluidState getFluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
LevelAccessor worldAccess = ctx.getLevel();
BlockPos blockPos = ctx.getClickedPos();
return this.defaultBlockState()
.setValue(WATERLOGGED, worldAccess.getFluidState(blockPos).getType() == Fluids.WATER)
.setValue(FACING, ctx.getClickedFace());
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, Rotation rotation) {
return BlocksHelper.rotateHorizontal(state, rotation, FACING);
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, Mirror mirror) {
return BlocksHelper.mirrorHorizontal(state, mirror, FACING);
}
@Override
@SuppressWarnings("deprecation")
public BlockState updateShape(
BlockState state,
Direction direction,
BlockState newState,
LevelAccessor world,
BlockPos pos,
BlockPos posFrom
) {
if (state.getValue(WATERLOGGED)) {
world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
}
return state;
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
static {
SHAPES.put(Axis.X, Block.box(0, 6, 6, 16, 10, 10));
SHAPES.put(Axis.Y, Block.box(6, 0, 6, 10, 16, 10));
SHAPES.put(Axis.Z, Block.box(6, 6, 0, 10, 10, 16));
}
}

View file

@ -0,0 +1,32 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.BetterEnd;
import org.betterx.betterend.blocks.basis.PedestalBlock;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import com.google.common.collect.Maps;
import java.util.Map;
public class EndPedestal extends PedestalBlock {
public EndPedestal(Block parent) {
super(parent);
}
@Override
protected Map<String, String> createTexturesMap() {
ResourceLocation blockId = Registry.BLOCK.getKey(parent);
String name = blockId.getPath();
Map<String, String> textures = Maps.newHashMap();
textures.put("%mod%", BetterEnd.MOD_ID);
textures.put("%top%", name + "_polished");
textures.put("%base%", name + "_polished");
textures.put("%pillar%", name + "_pillar_side");
textures.put("%bottom%", name + "_polished");
return textures;
}
}

View file

@ -0,0 +1,228 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.CustomColorProvider;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.betterend.advancements.BECriteria;
import org.betterx.betterend.interfaces.TeleportingEntity;
import org.betterx.betterend.registry.EndParticles;
import org.betterx.betterend.registry.EndPortals;
import org.betterx.betterend.rituals.EternalRitual;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.NetherPortalBlock;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.dimension.DimensionType;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Objects;
import java.util.Optional;
public class EndPortalBlock extends NetherPortalBlock implements RenderLayerProvider, CustomColorProvider {
public static final IntegerProperty PORTAL = EndBlockProperties.PORTAL;
public EndPortalBlock() {
super(FabricBlockSettings.copyOf(Blocks.NETHER_PORTAL)
.resistance(Blocks.BEDROCK.getExplosionResistance())
.luminance(15));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(PORTAL);
}
@Override
@Environment(EnvType.CLIENT)
public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {
if (random.nextInt(100) == 0) {
world.playLocalSound(
pos.getX() + 0.5D,
pos.getY() + 0.5D,
pos.getZ() + 0.5D,
SoundEvents.PORTAL_AMBIENT,
SoundSource.BLOCKS,
0.5F,
random.nextFloat() * 0.4F + 0.8F,
false
);
}
double x = pos.getX() + random.nextDouble();
double y = pos.getY() + random.nextDouble();
double z = pos.getZ() + random.nextDouble();
int k = random.nextInt(2) * 2 - 1;
if (!world.getBlockState(pos.west()).is(this) && !world.getBlockState(pos.east()).is(this)) {
x = pos.getX() + 0.5D + 0.25D * k;
} else {
z = pos.getZ() + 0.5D + 0.25D * k;
}
world.addParticle(EndParticles.PORTAL_SPHERE, x, y, z, 0, 0, 0);
}
@Override
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
}
@Override
public BlockState updateShape(
BlockState state,
Direction direction,
BlockState newState,
LevelAccessor world,
BlockPos pos,
BlockPos posFrom
) {
return state;
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if (world.isClientSide || !validate(entity)) return;
entity.setPortalCooldown();
ServerLevel currentWorld = (ServerLevel) world;
MinecraftServer server = currentWorld.getServer();
ServerLevel targetWorld = EndPortals.getWorld(server, state.getValue(PORTAL));
boolean isInEnd = currentWorld.dimension().equals(Level.END);
ServerLevel destination = isInEnd ? targetWorld : server.getLevel(Level.END);
BlockPos exitPos = findExitPos(currentWorld, destination, pos, entity);
if (exitPos == null) return;
if (entity instanceof ServerPlayer sp && sp.isCreative()) {
((ServerPlayer) entity).teleportTo(
destination,
exitPos.getX() + 0.5,
exitPos.getY(),
exitPos.getZ() + 0.5,
entity.getYRot(),
entity.getXRot()
);
BECriteria.PORTAL_TRAVEL.trigger(sp);
} else {
if (entity instanceof ServerPlayer sp) {
BECriteria.PORTAL_TRAVEL.trigger(sp);
}
((TeleportingEntity) entity).be_setExitPos(exitPos);
Optional<Entity> teleported = Optional.ofNullable(entity.changeDimension(destination));
teleported.ifPresent(Entity::setPortalCooldown);
}
}
private boolean validate(Entity entity) {
return !entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions() && !entity.isOnPortalCooldown();
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.TRANSLUCENT;
}
private BlockPos findExitPos(
ServerLevel currentWorld,
ServerLevel targetWorld,
BlockPos currentPos,
Entity entity
) {
if (targetWorld == null) return null;
Registry<DimensionType> registry = targetWorld.registryAccess()
.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY);
ResourceLocation targetWorldId = targetWorld.dimension().location();
ResourceLocation currentWorldId = currentWorld.dimension().location();
double targetMultiplier = Objects.requireNonNull(registry.get(targetWorldId)).coordinateScale();
double currentMultiplier = Objects.requireNonNull(registry.get(currentWorldId)).coordinateScale();
double multiplier = targetMultiplier > currentMultiplier ? 1.0 / targetMultiplier : currentMultiplier;
MutableBlockPos basePos = currentPos.mutable()
.set(
currentPos.getX() * multiplier,
currentPos.getY(),
currentPos.getZ() * multiplier
);
MutableBlockPos checkPos = basePos.mutable();
BlockState currentState = currentWorld.getBlockState(currentPos);
int radius = (EternalRitual.SEARCH_RADIUS >> 4) + 1;
checkPos = EternalRitual.findBlockPos(
targetWorld,
checkPos,
radius,
this,
state -> state.is(this) && state.getValue(PORTAL).equals(currentState.getValue(PORTAL))
);
if (checkPos != null) {
BlockState checkState = targetWorld.getBlockState(checkPos);
Axis axis = checkState.getValue(AXIS);
checkPos = findCenter(targetWorld, checkPos, axis);
Direction frontDir = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE).getClockWise();
Direction entityDir = entity.getMotionDirection();
if (entityDir.getAxis().isVertical()) {
entityDir = frontDir;
}
if (frontDir != entityDir && frontDir.getOpposite() != entityDir) {
entity.rotate(Rotation.CLOCKWISE_90);
entityDir = entityDir.getClockWise();
}
return checkPos.relative(entityDir);
}
return null;
}
private MutableBlockPos findCenter(Level world, MutableBlockPos pos, Direction.Axis axis) {
return findCenter(world, pos, axis, 1);
}
private MutableBlockPos findCenter(Level world, MutableBlockPos pos, Direction.Axis axis, int step) {
if (step > 8) return pos;
BlockState right, left;
Direction rightDir, leftDir;
rightDir = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE);
leftDir = rightDir.getOpposite();
right = world.getBlockState(pos.relative(rightDir));
left = world.getBlockState(pos.relative(leftDir));
BlockState down = world.getBlockState(pos.below());
if (down.is(this)) {
return findCenter(world, pos.move(Direction.DOWN), axis, step);
} else if (right.is(this) && left.is(this)) {
return pos;
} else if (right.is(this)) {
return findCenter(world, pos.move(rightDir), axis, ++step);
} else if (left.is(this)) {
return findCenter(world, pos.move(leftDir), axis, ++step);
}
return pos;
}
@Override
public BlockColor getProvider() {
return (state, world, pos, tintIndex) -> EndPortals.getColor(state.getValue(PORTAL));
}
@Override
public ItemColor getItemProvider() {
return (stack, tintIndex) -> EndPortals.getColor(0);
}
}

View file

@ -0,0 +1,188 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlockWithEntity;
import org.betterx.bclib.interfaces.AlloyingRecipeWorkstation;
import org.betterx.betterend.blocks.entities.EndStoneSmelterBlockEntity;
import org.betterx.betterend.registry.EndBlockEntities;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.BlockHitResult;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import com.google.common.collect.Lists;
import java.util.List;
import org.jetbrains.annotations.Nullable;
public class EndStoneSmelter extends BaseBlockWithEntity implements AlloyingRecipeWorkstation {
public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
public static final BooleanProperty LIT = BlockStateProperties.LIT;
public static final String ID = "end_stone_smelter";
public EndStoneSmelter() {
super(FabricBlockSettings.of(Material.STONE, MaterialColor.COLOR_GRAY)
.luminance(state -> state.getValue(LIT) ? 15 : 0)
.hardness(4F)
.resistance(100F)
.requiresCorrectToolForDrops()
.sound(SoundType.STONE));
registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(LIT, false));
}
@SuppressWarnings("deprecation")
public InteractionResult use(
BlockState state,
Level world,
BlockPos pos,
Player player,
InteractionHand hand,
BlockHitResult hit
) {
if (world.isClientSide) {
return InteractionResult.SUCCESS;
} else {
this.openScreen(world, pos, player);
return InteractionResult.CONSUME;
}
}
private void openScreen(Level world, BlockPos pos, Player player) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof EndStoneSmelterBlockEntity) {
player.openMenu((EndStoneSmelterBlockEntity) blockEntity);
}
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
return defaultBlockState().setValue(FACING, ctx.getHorizontalDirection().getOpposite());
}
@Override
public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return new EndStoneSmelterBlockEntity(blockPos, blockState);
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
List<ItemStack> drop = Lists.newArrayList(new ItemStack(this));
BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY);
if (blockEntity instanceof EndStoneSmelterBlockEntity) {
EndStoneSmelterBlockEntity smelterBlockEntity = (EndStoneSmelterBlockEntity) blockEntity;
for (int i = 0; i < smelterBlockEntity.getContainerSize(); i++) {
ItemStack item = smelterBlockEntity.getItem(i);
if (!item.isEmpty()) {
drop.add(item);
}
}
}
return drop;
}
@Override
@SuppressWarnings("deprecation")
public boolean hasAnalogOutputSignal(BlockState state) {
return true;
}
@Override
@SuppressWarnings("deprecation")
public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) {
//TODO
return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(world.getBlockEntity(pos));
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
@Override
@SuppressWarnings("deprecation")
public BlockState rotate(BlockState state, Rotation rotation) {
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
}
@Override
@SuppressWarnings("deprecation")
public BlockState mirror(BlockState state, Mirror mirror) {
return state.rotate(mirror.getRotation(state.getValue(FACING)));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(FACING, LIT);
}
@Environment(EnvType.CLIENT)
public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {
if (state.getValue(LIT)) {
double x = pos.getX() + 0.5D;
double y = pos.getY();
double z = pos.getZ() + 0.5D;
if (random.nextDouble() < 0.1D) {
world.playLocalSound(
x,
y,
z,
SoundEvents.BLASTFURNACE_FIRE_CRACKLE,
SoundSource.BLOCKS,
1.0F,
1.0F,
false
);
}
Direction direction = state.getValue(FACING);
Direction.Axis axis = direction.getAxis();
double defOffset = random.nextDouble() * 0.6D - 0.3D;
double offX = axis == Direction.Axis.X ? direction.getStepX() * 0.52D : defOffset;
double offY = random.nextDouble() * 9.0D / 16.0D;
double offZ = axis == Direction.Axis.Z ? direction.getStepZ() * 0.52D : defOffset;
world.addParticle(ParticleTypes.SMOKE, x + offX, y + offY, z + offZ, 0.0D, 0.0D, 0.0D);
}
}
@Override
@Nullable
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(
Level level,
BlockState blockState,
BlockEntityType<T> blockEntityType
) {
return level.isClientSide() ? null : createTickerHelper(
blockEntityType,
EndBlockEntities.END_STONE_SMELTER,
EndStoneSmelterBlockEntity::tick
);
}
}

View file

@ -0,0 +1,30 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class EnderBlock extends BaseBlock {
public EnderBlock() {
super(FabricBlockSettings.of(Material.STONE, MaterialColor.WARPED_WART_BLOCK)
.hardness(5F)
.resistance(6F)
.requiresCorrectToolForDrops()
.sound(SoundType.STONE));
}
@Environment(EnvType.CLIENT)
public int getColor(BlockState state, BlockGetter world, BlockPos pos) {
return 0xFF005548;
}
}

View file

@ -0,0 +1,52 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.interfaces.TagProvider;
import org.betterx.bclib.interfaces.tools.AddMineableShovel;
import org.betterx.ui.ColorUtil;
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import net.minecraft.core.BlockPos;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.FallingBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Collections;
import java.util.List;
public class EndstoneDustBlock extends FallingBlock implements TagProvider, AddMineableShovel {
@Environment(EnvType.CLIENT)
private static final int COLOR = ColorUtil.color(226, 239, 168);
public EndstoneDustBlock() {
super(FabricBlockSettings
.copyOf(Blocks.SAND)
.mapColor(Blocks.END_STONE.defaultMaterialColor())
);
}
@Override
@SuppressWarnings("deprecation")
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
return Collections.singletonList(new ItemStack(this));
}
@Environment(EnvType.CLIENT)
public int getDustColor(BlockState state, BlockGetter world, BlockPos pos) {
return COLOR;
}
@Override
public void addTags(List<TagKey<Block>> blockTags, List<TagKey<Item>> itemTags) {
blockTags.add(CommonBlockTags.END_STONES);
}
}

View file

@ -0,0 +1,145 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.PedestalBlock;
import org.betterx.betterend.blocks.entities.EternalPedestalEntity;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndPortals;
import org.betterx.betterend.rituals.EternalRitual;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import com.google.common.collect.Lists;
import java.util.List;
public class EternalPedestal extends PedestalBlock {
public static final BooleanProperty ACTIVATED = EndBlockProperties.ACTIVE;
public EternalPedestal() {
super(EndBlocks.FLAVOLITE_RUNED_ETERNAL);
this.registerDefaultState(defaultBlockState().setValue(ACTIVATED, false));
}
@Override
public void checkRitual(Level world, Player player, BlockPos pos) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof EternalPedestalEntity) {
EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity;
BlockState updatedState = world.getBlockState(pos);
if (pedestal.isEmpty()) {
if (pedestal.hasRitual()) {
EternalRitual ritual = pedestal.getRitual();
if (ritual.isActive()) {
ResourceLocation targetWorld = ritual.getTargetWorldId();
int portalId;
if (targetWorld != null) {
portalId = EndPortals.getPortalIdByWorld(targetWorld);
} else {
portalId = EndPortals.getPortalIdByWorld(EndPortals.OVERWORLD_ID);
}
ritual.disablePortal(portalId);
}
}
world.setBlockAndUpdate(pos, updatedState.setValue(ACTIVATED, false).setValue(HAS_LIGHT, false));
} else {
ItemStack itemStack = pedestal.getItem(0);
ResourceLocation id = Registry.ITEM.getKey(itemStack.getItem());
if (EndPortals.isAvailableItem(id)) {
world.setBlockAndUpdate(pos, updatedState.setValue(ACTIVATED, true).setValue(HAS_LIGHT, true));
if (pedestal.hasRitual()) {
pedestal.getRitual().checkStructure(player);
} else {
EternalRitual ritual = new EternalRitual(world, pos);
ritual.checkStructure(player);
}
}
}
}
}
@Override
@Deprecated
public BlockState updateShape(
BlockState state,
Direction direction,
BlockState newState,
LevelAccessor world,
BlockPos pos,
BlockPos posFrom
) {
BlockState updated = super.updateShape(state, direction, newState, world, pos, posFrom);
if (!updated.is(this)) return updated;
if (!this.isPlaceable(updated)) {
return updated.setValue(ACTIVATED, false);
}
return updated;
}
@Override
@Deprecated
public float getDestroyProgress(BlockState state, Player player, BlockGetter world, BlockPos pos) {
return 0.0F;
}
@Override
public float getExplosionResistance() {
return Blocks.BEDROCK.getExplosionResistance();
}
@Override
public boolean dropFromExplosion(Explosion explosion) {
return false;
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
if (state.is(this)) {
EndBlockProperties.PedestalState currentState = state.getValue(EndBlockProperties.PEDESTAL_STATE);
if (currentState.equals(EndBlockProperties.PedestalState.BOTTOM) || currentState.equals(EndBlockProperties.PedestalState.PILLAR)) {
return Lists.newArrayList();
}
}
List<ItemStack> drop = Lists.newArrayList();
BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY);
if (blockEntity instanceof EternalPedestalEntity) {
EternalPedestalEntity pedestal = (EternalPedestalEntity) blockEntity;
if (!pedestal.isEmpty()) {
drop.add(pedestal.getItem(0));
}
}
return drop;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
super.createBlockStateDefinition(stateManager);
stateManager.add(ACTIVATED);
}
@Override
public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return new EternalPedestalEntity(blockPos, blockState);
}
@Override
public boolean hasUniqueEntity() {
return true;
}
}

View file

@ -0,0 +1,11 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseVineBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
public class FilaluxBlock extends BaseVineBlock {
public FilaluxBlock() {
super(15, true, p -> p.offsetType(BlockBehaviour.OffsetType.NONE));
}
}

View file

@ -0,0 +1,17 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.interfaces.tools.AddMineableAxe;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.material.Material;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class FilaluxLanternBlock extends BaseBlock implements AddMineableAxe {
public FilaluxLanternBlock() {
super(FabricBlockSettings.of(Material.WOOD)
.luminance(15)
.sound(SoundType.WOOD));
}
}

View file

@ -0,0 +1,52 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseAttachedBlock;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.interfaces.tools.AddMineableShears;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import com.google.common.collect.Maps;
import java.util.EnumMap;
public class FilaluxWingsBlock extends BaseAttachedBlock implements RenderLayerProvider, AddMineableShears {
private static final EnumMap<Direction, VoxelShape> BOUNDING_SHAPES = Maps.newEnumMap(Direction.class);
public FilaluxWingsBlock() {
super(FabricBlockSettings.of(Material.PLANT)
.sound(SoundType.WET_GRASS)
.noCollission());
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return BOUNDING_SHAPES.get(state.getValue(FACING));
}
static {
BOUNDING_SHAPES.put(Direction.UP, Shapes.box(0.0, 0.0, 0.0, 1.0, 0.5, 1.0));
BOUNDING_SHAPES.put(Direction.DOWN, Shapes.box(0.0, 0.5, 0.0, 1.0, 1.0, 1.0));
BOUNDING_SHAPES.put(Direction.NORTH, Shapes.box(0.0, 0.0, 0.5, 1.0, 1.0, 1.0));
BOUNDING_SHAPES.put(Direction.SOUTH, Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 0.5));
BOUNDING_SHAPES.put(Direction.WEST, Shapes.box(0.5, 0.0, 0.0, 1.0, 1.0, 1.0));
BOUNDING_SHAPES.put(Direction.EAST, Shapes.box(0.0, 0.0, 0.0, 0.5, 1.0, 1.0));
}
}

View file

@ -0,0 +1,62 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.interfaces.CustomItemProvider;
import org.betterx.bclib.interfaces.tools.AddMineableShears;
import org.betterx.betterend.blocks.basis.EndPlantBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.PlaceOnWaterBlockItem;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import com.google.common.collect.Lists;
import java.util.List;
public class FlamaeaBlock extends EndPlantBlock implements CustomItemProvider, AddMineableShears {
private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 1, 16);
public FlamaeaBlock() {
super(basePlantSettings()
.sound(SoundType.WET_GRASS)
.offsetType(BlockBehaviour.OffsetType.NONE)
);
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(Blocks.WATER);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE;
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
return Lists.newArrayList(new ItemStack(this));
}
@Override
public boolean canBePotted() {
return false;
}
@Override
public BlockItem getCustomItem(ResourceLocation resourceLocation, FabricItemSettings fabricItemSettings) {
return new PlaceOnWaterBlockItem(this, fabricItemSettings);
}
}

View file

@ -0,0 +1,44 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.client.models.ModelsHelper;
import org.betterx.betterend.blocks.basis.EndPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
public class FlammalixBlock extends EndPlantBlock {
private static final VoxelShape SHAPE = Block.box(2, 0, 2, 14, 14, 14);
public FlammalixBlock() {
super(basePlantSettings(12).offsetType(OffsetType.NONE));
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.PALLIDIUM_FULL) ||
state.is(EndBlocks.PALLIDIUM_HEAVY) ||
state.is(EndBlocks.PALLIDIUM_THIN) ||
state.is(EndBlocks.PALLIDIUM_TINY);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE;
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) {
return ModelsHelper.createItemModel(resourceLocation);
}
}

View file

@ -0,0 +1,460 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlockNotFull;
import org.betterx.bclib.client.models.BasePatterns;
import org.betterx.bclib.client.models.ModelsHelper;
import org.betterx.bclib.client.models.ModelsHelper.MultiPartBuilder;
import org.betterx.bclib.client.models.PatternsHelper;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.PostInitable;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.bclib.util.JsonFactory;
import org.betterx.betterend.BetterEnd;
import org.betterx.betterend.blocks.basis.PottableLeavesBlock;
import org.betterx.betterend.client.models.Patterns;
import org.betterx.betterend.config.Configs;
import org.betterx.betterend.interfaces.PottablePlant;
import org.betterx.betterend.interfaces.PottableTerrain;
import org.betterx.betterend.registry.EndBlocks;
import com.mojang.math.Transformation;
import com.mojang.math.Vector3f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SaplingBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.storage.loot.LootContext.Builder;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.loader.api.FabricLoader;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class FlowerPotBlock extends BaseBlockNotFull implements RenderLayerProvider, PostInitable {
private static final IntegerProperty PLANT_ID = EndBlockProperties.PLANT_ID;
private static final IntegerProperty SOIL_ID = EndBlockProperties.SOIL_ID;
private static final IntegerProperty POT_LIGHT = EndBlockProperties.POT_LIGHT;
private static final VoxelShape SHAPE_EMPTY;
private static final VoxelShape SHAPE_FULL;
private static Block[] plants;
private static Block[] soils;
public FlowerPotBlock(Block source) {
super(FabricBlockSettings.copyOf(source).luminance(state -> state.getValue(POT_LIGHT) * 5));
this.registerDefaultState(
this.defaultBlockState()
.setValue(PLANT_ID, 0)
.setValue(SOIL_ID, 0)
.setValue(POT_LIGHT, 0)
);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(PLANT_ID, SOIL_ID, POT_LIGHT);
}
@Override
public List<ItemStack> getDrops(BlockState state, Builder builder) {
List<ItemStack> drop = Lists.newArrayList(new ItemStack(this));
int id = state.getValue(SOIL_ID) - 1;
if (id >= 0 && id < soils.length && soils[id] != null) {
drop.add(new ItemStack(soils[id]));
}
id = state.getValue(PLANT_ID) - 1;
if (id >= 0 && id < plants.length && plants[id] != null) {
drop.add(new ItemStack(plants[id]));
}
return drop;
}
@Override
@SuppressWarnings("deprecation")
public BlockState updateShape(
BlockState state,
Direction facing,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
int plantID = state.getValue(PLANT_ID);
if (plantID < 1 || plantID > plants.length || plants[plantID - 1] == null) {
return state.getValue(POT_LIGHT) > 0 ? state.setValue(POT_LIGHT, 0) : state;
}
int light = plants[plantID - 1].defaultBlockState().getLightEmission() / 5;
if (state.getValue(POT_LIGHT) != light) {
state = state.setValue(POT_LIGHT, light);
}
return state;
}
@Override
public void postInit() {
if (FlowerPotBlock.plants != null) {
return;
}
Block[] plants = new Block[128];
Block[] soils = new Block[16];
Map<String, Integer> reservedPlantsIDs = Maps.newHashMap();
Map<String, Integer> reservedSoilIDs = Maps.newHashMap();
JsonObject obj = JsonFactory.getJsonObject(new File(
FabricLoader.getInstance().getConfigDir().toFile(),
BetterEnd.MOD_ID + "/blocks.json"
));
if (obj.get("flower_pots") != null) {
JsonElement plantsObj = obj.get("flower_pots").getAsJsonObject().get("plants");
JsonElement soilsObj = obj.get("flower_pots").getAsJsonObject().get("soils");
if (plantsObj != null) {
plantsObj.getAsJsonObject().entrySet().forEach(entry -> {
String name = entry.getKey().substring(0, entry.getKey().indexOf(' '));
reservedPlantsIDs.put(name, entry.getValue().getAsInt());
});
}
if (soilsObj != null) {
soilsObj.getAsJsonObject().entrySet().forEach(entry -> {
String name = entry.getKey().substring(0, entry.getKey().indexOf(' '));
reservedSoilIDs.put(name, entry.getValue().getAsInt());
});
}
}
EndBlocks.getModBlocks().forEach(block -> {
if (block instanceof PottablePlant && ((PottablePlant) block).canBePotted()) {
processBlock(plants, block, "flower_pots.plants", reservedPlantsIDs);
} else if (block instanceof PottableTerrain && ((PottableTerrain) block).canBePotted()) {
processBlock(soils, block, "flower_pots.soils", reservedSoilIDs);
}
});
Configs.BLOCK_CONFIG.saveChanges();
FlowerPotBlock.plants = new Block[maxNotNull(plants) + 1];
System.arraycopy(plants, 0, FlowerPotBlock.plants, 0, FlowerPotBlock.plants.length);
FlowerPotBlock.soils = new Block[maxNotNull(soils) + 1];
System.arraycopy(soils, 0, FlowerPotBlock.soils, 0, FlowerPotBlock.soils.length);
if (PLANT_ID.getValue(Integer.toString(FlowerPotBlock.plants.length)).isEmpty()) {
throw new RuntimeException("There are too much plant ID values!");
}
if (SOIL_ID.getValue(Integer.toString(FlowerPotBlock.soils.length)).isEmpty()) {
throw new RuntimeException("There are too much soil ID values!");
}
}
private int maxNotNull(Block[] array) {
int max = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] != null) {
max = i;
}
}
return max;
}
private void processBlock(Block[] target, Block block, String path, Map<String, Integer> idMap) {
ResourceLocation location = Registry.BLOCK.getKey(block);
if (idMap.containsKey(location.getPath())) {
target[idMap.get(location.getPath())] = block;
} else {
for (int i = 0; i < target.length; i++) {
if (!idMap.containsValue(i)) {
target[i] = block;
idMap.put(location.getPath(), i);
Configs.BLOCK_CONFIG.getInt(path, location.getPath(), i);
break;
}
}
}
}
@Override
@SuppressWarnings("deprecation")
public InteractionResult use(
BlockState state,
Level level,
BlockPos pos,
Player player,
InteractionHand hand,
BlockHitResult hit
) {
if (level.isClientSide) {
return InteractionResult.CONSUME;
}
ItemStack itemStack = player.getItemInHand(hand);
int soilID = state.getValue(SOIL_ID);
if (soilID == 0 || soilID > soils.length || soils[soilID - 1] == null) {
if (!(itemStack.getItem() instanceof BlockItem)) {
return InteractionResult.PASS;
}
Block block = ((BlockItem) itemStack.getItem()).getBlock();
for (int i = 0; i < soils.length; i++) {
if (block == soils[i]) {
BlocksHelper.setWithUpdate(level, pos, state.setValue(SOIL_ID, i + 1));
if (!player.isCreative()) {
itemStack.shrink(1);
}
level.playSound(
player,
pos.getX() + 0.5,
pos.getY() + 0.5,
pos.getZ() + 0.5,
SoundEvents.SOUL_SOIL_PLACE,
SoundSource.BLOCKS,
1,
1
);
return InteractionResult.SUCCESS;
}
}
return InteractionResult.PASS;
}
int plantID = state.getValue(PLANT_ID);
if (itemStack.isEmpty()) {
if (plantID > 0 && plantID <= plants.length && plants[plantID - 1] != null) {
BlocksHelper.setWithUpdate(level, pos, state.setValue(PLANT_ID, 0).setValue(POT_LIGHT, 0));
player.addItem(new ItemStack(plants[plantID - 1]));
return InteractionResult.SUCCESS;
}
if (soilID > 0 && soilID <= soils.length && soils[soilID - 1] != null) {
BlocksHelper.setWithUpdate(level, pos, state.setValue(SOIL_ID, 0));
player.addItem(new ItemStack(soils[soilID - 1]));
}
return InteractionResult.PASS;
}
if (!(itemStack.getItem() instanceof BlockItem)) {
return InteractionResult.PASS;
}
BlockItem item = (BlockItem) itemStack.getItem();
for (int i = 0; i < plants.length; i++) {
if (item.getBlock() == plants[i]) {
if (!((PottablePlant) plants[i]).canPlantOn(soils[soilID - 1])) {
return InteractionResult.PASS;
}
int light = plants[i].defaultBlockState().getLightEmission() / 5;
BlocksHelper.setWithUpdate(level, pos, state.setValue(PLANT_ID, i + 1).setValue(POT_LIGHT, light));
level.playSound(
player,
pos.getX() + 0.5,
pos.getY() + 0.5,
pos.getZ() + 0.5,
SoundEvents.HOE_TILL,
SoundSource.BLOCKS,
1,
1
);
if (!player.isCreative()) {
itemStack.shrink(1);
}
return InteractionResult.SUCCESS;
}
}
return InteractionResult.PASS;
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation blockId) {
Optional<String> pattern = PatternsHelper.createJson(Patterns.BLOCK_FLOWER_POT, blockId);
return ModelsHelper.fromPattern(pattern);
}
@Override
@Environment(EnvType.CLIENT)
public UnbakedModel getModelVariant(
ResourceLocation stateId,
BlockState blockState,
Map<ResourceLocation, UnbakedModel> modelCache
) {
MultiPartBuilder model = MultiPartBuilder.create(stateDefinition);
model.part(new ModelResourceLocation(stateId.getNamespace(), stateId.getPath(), "inventory")).add();
Transformation offset = new Transformation(new Vector3f(0, 7.5F / 16F, 0), null, null, null);
for (int i = 0; i < plants.length; i++) {
if (plants[i] == null) {
continue;
}
final int compareID = i + 1;
ResourceLocation modelPath = Registry.BLOCK.getKey(plants[i]);
ResourceLocation objSource = new ResourceLocation(
modelPath.getNamespace(),
"models/block/" + modelPath.getPath() + "_potted.json"
);
if (Minecraft.getInstance().getResourceManager().getResource(objSource).isPresent()) {
objSource = new ResourceLocation(modelPath.getNamespace(), "block/" + modelPath.getPath() + "_potted");
model.part(objSource)
.setTransformation(offset)
.setCondition(state -> state.getValue(PLANT_ID) == compareID)
.add();
continue;
} else if (plants[i] instanceof SaplingBlock) {
ResourceLocation loc = Registry.BLOCK.getKey(plants[i]);
modelPath = new ResourceLocation(loc.getNamespace(), "block/" + loc.getPath() + "_potted");
Map<String, String> textures = Maps.newHashMap();
textures.put("%modid%", loc.getNamespace());
textures.put("%texture%", loc.getPath());
Optional<String> pattern = Patterns.createJson(BasePatterns.BLOCK_CROSS, textures);
UnbakedModel unbakedModel = ModelsHelper.fromPattern(pattern);
modelCache.put(modelPath, unbakedModel);
model.part(modelPath)
.setTransformation(offset)
.setCondition(state -> state.getValue(PLANT_ID) == compareID)
.add();
continue;
} else if (plants[i] instanceof PottableLeavesBlock) {
ResourceLocation loc = Registry.BLOCK.getKey(plants[i]);
modelPath = new ResourceLocation(loc.getNamespace(), "block/" + loc.getPath() + "_potted");
Map<String, String> textures = Maps.newHashMap();
textures.put("%leaves%", loc.getPath().contains("lucernia") ? loc.getPath() + "_1" : loc.getPath());
textures.put("%stem%", loc.getPath().replace("_leaves", "_log_side"));
Optional<String> pattern = Patterns.createJson(Patterns.BLOCK_POTTED_LEAVES, textures);
UnbakedModel unbakedModel = ModelsHelper.fromPattern(pattern);
modelCache.put(modelPath, unbakedModel);
model.part(modelPath)
.setTransformation(offset)
.setCondition(state -> state.getValue(PLANT_ID) == compareID)
.add();
continue;
}
objSource = new ResourceLocation(modelPath.getNamespace(), "blockstates/" + modelPath.getPath() + ".json");
JsonObject obj = JsonFactory.getJsonObject(objSource);
if (obj != null) {
JsonElement variants = obj.get("variants");
JsonElement list = null;
String path = null;
if (variants == null) {
continue;
}
if (variants.isJsonArray()) {
list = variants.getAsJsonArray().get(0);
} else if (variants.isJsonObject()) {
list = variants.getAsJsonObject().get(((PottablePlant) plants[i]).getPottedState());
}
if (list == null) {
BetterEnd.LOGGER.warning("Incorrect json for pot plant " + objSource + ", no matching variants");
continue;
}
if (list.isJsonArray()) {
path = list.getAsJsonArray().get(0).getAsJsonObject().get("model").getAsString();
} else {
path = list.getAsJsonObject().get("model").getAsString();
}
if (path == null) {
BetterEnd.LOGGER.warning("Incorrect json for pot plant " + objSource + ", no matching variants");
continue;
}
model.part(new ResourceLocation(path))
.setTransformation(offset)
.setCondition(state -> state.getValue(PLANT_ID) == compareID)
.add();
} else {
ResourceLocation loc = Registry.BLOCK.getKey(plants[i]);
modelPath = new ResourceLocation(loc.getNamespace(), "block/" + loc.getPath() + "_potted");
Map<String, String> textures = Maps.newHashMap();
textures.put("%modid%", loc.getNamespace());
textures.put("%texture%", loc.getPath());
Optional<String> pattern = Patterns.createJson(BasePatterns.BLOCK_CROSS, textures);
UnbakedModel unbakedModel = ModelsHelper.fromPattern(pattern);
modelCache.put(modelPath, unbakedModel);
model.part(modelPath)
.setTransformation(offset)
.setCondition(state -> state.getValue(PLANT_ID) == compareID)
.add();
}
}
for (int i = 0; i < soils.length; i++) {
if (soils[i] == null) {
continue;
}
ResourceLocation soilLoc = BetterEnd.makeID("flower_pot_soil_" + i);
if (!modelCache.containsKey(soilLoc)) {
String texture = Registry.BLOCK.getKey(soils[i]).getPath() + "_top";
if (texture.contains("rutiscus")) {
texture += "_1";
}
Optional<String> pattern = Patterns.createJson(Patterns.BLOCK_FLOWER_POT_SOIL, texture);
UnbakedModel soil = ModelsHelper.fromPattern(pattern);
modelCache.put(soilLoc, soil);
}
final int compareID = i + 1;
model.part(soilLoc).setCondition(state -> state.getValue(SOIL_ID) == compareID).add();
}
UnbakedModel result = model.build();
modelCache.put(stateId, result);
return result;
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
int id = state.getValue(PLANT_ID);
return id > 0 && id <= plants.length ? SHAPE_FULL : SHAPE_EMPTY;
}
@Override
@SuppressWarnings("deprecation")
public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE_EMPTY;
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
static {
SHAPE_EMPTY = Shapes.or(Block.box(4, 1, 4, 12, 8, 12), Block.box(5, 0, 5, 11, 1, 11));
SHAPE_FULL = Shapes.or(SHAPE_EMPTY, Block.box(3, 8, 3, 13, 16, 13));
}
}

View file

@ -0,0 +1,17 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.interfaces.tools.AddMineableAxe;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.material.Material;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class GlowingHymenophoreBlock extends BaseBlock implements AddMineableAxe {
public GlowingHymenophoreBlock() {
super(FabricBlockSettings.of(Material.WOOD)
.luminance(15)
.sound(SoundType.WART_BLOCK));
}
}

View file

@ -1,12 +1,14 @@
package ru.betterend.blocks;
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.EndPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
import ru.betterend.blocks.basis.EndPlantBlock;
import ru.betterend.registry.EndBlocks;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
public class GlowingMossBlock extends EndPlantBlock {
public GlowingMossBlock(int light) {

View file

@ -0,0 +1,61 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.interfaces.tools.AddMineableShears;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class GlowingPillarLuminophorBlock extends BaseBlock implements AddMineableShears {
public static final BooleanProperty NATURAL = EndBlockProperties.NATURAL;
public GlowingPillarLuminophorBlock() {
super(FabricBlockSettings.of(Material.LEAVES)
.mapColor(MaterialColor.COLOR_ORANGE)
.strength(0.2F)
.luminance(15)
.sound(SoundType.GRASS));
this.registerDefaultState(this.stateDefinition.any().setValue(NATURAL, false));
}
@Override
@SuppressWarnings("deprecation")
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
return !state.getValue(NATURAL) || world.getBlockState(pos.below()).is(EndBlocks.GLOWING_PILLAR_ROOTS);
}
@Override
@SuppressWarnings("deprecation")
public BlockState updateShape(
BlockState state,
Direction facing,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
if (!canSurvive(state, world, pos)) {
return Blocks.AIR.defaultBlockState();
} else {
return state;
}
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(NATURAL);
}
}

View file

@ -0,0 +1,37 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.blocks.UpDownPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
public class GlowingPillarRootsBlock extends UpDownPlantBlock {
public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE;
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SHAPE);
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.AMBER_MOSS);
}
@Override
@Environment(EnvType.CLIENT)
public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) {
return new ItemStack(EndBlocks.GLOWING_PILLAR_SEED);
}
}

View file

@ -0,0 +1,82 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.interfaces.tools.AddMineableShears;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.material.Material;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class GlowingPillarSeedBlock extends EndPlantWithAgeBlock implements AddMineableShears {
public GlowingPillarSeedBlock() {
super(FabricBlockSettings.of(Material.PLANT)
.sound(SoundType.GRASS)
.lightLevel(state -> state.getValue(AGE) * 3 + 3)
.randomTicks()
.noCollission()
.offsetType(OffsetType.NONE));
}
@Override
public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) {
int height = MHelper.randRange(1, 2, random);
int h = BlocksHelper.upRay(world, pos, height + 2);
if (h < height) {
return;
}
MutableBlockPos mut = new MutableBlockPos().set(pos);
BlockState roots = EndBlocks.GLOWING_PILLAR_ROOTS.defaultBlockState();
if (height < 2) {
BlocksHelper.setWithUpdate(world, mut, roots.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE));
} else {
BlocksHelper.setWithUpdate(world, mut, roots.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM));
mut.move(Direction.UP);
BlocksHelper.setWithUpdate(world, mut, roots.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP));
}
mut.move(Direction.UP);
BlocksHelper.setWithUpdate(
world,
mut,
EndBlocks.GLOWING_PILLAR_LUMINOPHOR.defaultBlockState().setValue(BlueVineLanternBlock.NATURAL, true)
);
for (Direction dir : BlocksHelper.DIRECTIONS) {
pos = mut.relative(dir);
if (world.isEmptyBlock(pos)) {
BlocksHelper.setWithUpdate(
world,
pos,
EndBlocks.GLOWING_PILLAR_LEAVES.defaultBlockState().setValue(BlockStateProperties.FACING, dir)
);
}
}
mut.move(Direction.UP);
if (world.isEmptyBlock(mut)) {
BlocksHelper.setWithUpdate(
world,
mut,
EndBlocks.GLOWING_PILLAR_LEAVES.defaultBlockState()
.setValue(BlockStateProperties.FACING, Direction.UP)
);
}
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.AMBER_MOSS);
}
}

View file

@ -0,0 +1,84 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.blocks.BaseLeavesBlock;
import org.betterx.bclib.interfaces.CustomColorProvider;
import org.betterx.bclib.interfaces.tools.AddMineableShears;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.noise.OpenSimplexNoise;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.ui.ColorUtil;
import org.betterx.worlds.together.tag.v3.TagManager;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.level.storage.loot.LootContext;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.List;
public class HelixTreeLeavesBlock extends BaseBlock implements CustomColorProvider, AddMineableShears {
public static final IntegerProperty COLOR = EndBlockProperties.COLOR;
private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(0);
public HelixTreeLeavesBlock() {
super(FabricBlockSettings
.of(Material.LEAVES)
.mapColor(MaterialColor.COLOR_ORANGE)
.sound(SoundType.WART_BLOCK)
.sound(SoundType.GRASS)
.strength(0.2F)
);
TagManager.BLOCKS.add(BlockTags.LEAVES, this);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(COLOR);
}
@Override
public BlockColor getProvider() {
return (state, world, pos, tintIndex) -> {
return ColorUtil.color(237, getGreen(state.getValue(COLOR)), 20);
};
}
@Override
public ItemColor getItemProvider() {
return (stack, tintIndex) -> {
return ColorUtil.color(237, getGreen(4), 20);
};
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
double px = ctx.getClickedPos().getX() * 0.1;
double py = ctx.getClickedPos().getY() * 0.1;
double pz = ctx.getClickedPos().getZ() * 0.1;
return this.defaultBlockState().setValue(COLOR, MHelper.floor(NOISE.eval(px, py, pz) * 3.5 + 4));
}
private int getGreen(int color) {
float delta = color / 7F;
return (int) Mth.lerp(delta, 80, 158);
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
return BaseLeavesBlock.getLeaveDrops(this, EndBlocks.HELIX_TREE_SAPLING, builder, 16, 32);
}
}

View file

@ -0,0 +1,28 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.PottableFeatureSapling;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndFeatures;
import org.betterx.betterend.world.features.trees.HelixTreeFeature;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public class HelixTreeSaplingBlock extends PottableFeatureSapling<HelixTreeFeature, NoneFeatureConfiguration> {
public HelixTreeSaplingBlock() {
super((state) -> EndFeatures.HELIX_TREE.configuredFeature);
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
return world.getBlockState(pos.below()).is(EndBlocks.AMBER_MOSS);
}
@Override
public boolean canPlantOn(Block block) {
return block == EndBlocks.AMBER_MOSS;
}
}

View file

@ -0,0 +1,96 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.UnderwaterPlantBlock;
import org.betterx.bclib.interfaces.tools.AddMineableShears;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.blocks.EndBlockProperties.HydraluxShape;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndItems;
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.storage.loot.LootContext;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.List;
public class HydraluxBlock extends UnderwaterPlantBlock implements AddMineableShears {
public static final EnumProperty<HydraluxShape> SHAPE = EndBlockProperties.HYDRALUX_SHAPE;
public HydraluxBlock() {
super(baseUnderwaterPlantSettings()
.lightLevel((state) -> state.getValue(SHAPE).hasGlow() ? 15 : 0)
);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SHAPE);
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState down = world.getBlockState(pos.below());
HydraluxShape shape = state.getValue(SHAPE);
if (shape == HydraluxShape.FLOWER_BIG_TOP || shape == HydraluxShape.FLOWER_SMALL_TOP) {
return down.is(this);
} else if (shape == HydraluxShape.ROOTS) {
return down.is(EndBlocks.SULPHURIC_ROCK.stone) && world.getBlockState(pos.above()).is(this);
} else {
return down.is(this) && world.getBlockState(pos.above()).is(this);
}
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(CommonBlockTags.END_STONES);
}
@Override
public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) {
return false;
}
@Override
public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) {
return false;
}
@Override
@Environment(EnvType.CLIENT)
public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) {
return new ItemStack(EndBlocks.HYDRALUX_SAPLING);
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
HydraluxShape shape = state.getValue(SHAPE);
if (shape == HydraluxShape.FLOWER_BIG_BOTTOM || shape == HydraluxShape.FLOWER_SMALL_BOTTOM) {
return Lists.newArrayList(new ItemStack(
EndItems.HYDRALUX_PETAL,
MHelper.randRange(1, 4, MHelper.RANDOM_SOURCE)
));
} else if (shape == HydraluxShape.ROOTS) {
return Lists.newArrayList(new ItemStack(
EndBlocks.HYDRALUX_SAPLING,
MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE)
));
}
return Collections.emptyList();
}
}

View file

@ -0,0 +1,35 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.interfaces.tools.AddMineableAxe;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class HydraluxPetalBlock extends BaseBlock implements AddMineableAxe {
public HydraluxPetalBlock() {
this(
FabricBlockSettings
.of(Material.PLANT)
.hardness(1)
.resistance(1)
.mapColor(MaterialColor.PODZOL)
.sound(SoundType.WART_BLOCK)
);
}
public HydraluxPetalBlock(Properties settings) {
super(settings);
}
@Override
public void fallOn(Level level, BlockState blockState, BlockPos blockPos, Entity entity, float f) {
}
}

View file

@ -0,0 +1,43 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.client.models.ModelsHelper;
import org.betterx.bclib.interfaces.CustomColorProvider;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.betterend.client.models.Patterns;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.state.BlockState;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Optional;
import org.jetbrains.annotations.Nullable;
public class HydraluxPetalColoredBlock extends HydraluxPetalBlock implements CustomColorProvider {
public HydraluxPetalColoredBlock(FabricBlockSettings settings) {
super(settings);
}
@Override
public BlockColor getProvider() {
return (state, world, pos, tintIndex) -> BlocksHelper.getBlockColor(this);
}
@Override
public ItemColor getItemProvider() {
return (stack, tintIndex) -> BlocksHelper.getBlockColor(this);
}
@Override
@Environment(EnvType.CLIENT)
public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) {
String path = "betterend:block/block_petal_colored";
Optional<String> pattern = Patterns.createJson(Patterns.BLOCK_PETAL_COLORED, path, path);
return ModelsHelper.fromPattern(pattern);
}
}

View file

@ -0,0 +1,75 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.UnderwaterPlantWithAgeBlock;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
public class HydraluxSaplingBlock extends UnderwaterPlantWithAgeBlock {
@Override
public void grow(WorldGenLevel world, RandomSource random, BlockPos pos) {
int h = MHelper.randRange(4, 8, random);
MutableBlockPos mut = new MutableBlockPos().set(pos);
for (int i = 1; i < h; i++) {
mut.setY(pos.getY() + i);
if (!world.getBlockState(mut).is(Blocks.WATER)) {
return;
}
}
mut.setY(pos.getY());
BlockState state = EndBlocks.HYDRALUX.defaultBlockState();
BlocksHelper.setWithoutUpdate(
world,
pos,
state.setValue(EndBlockProperties.HYDRALUX_SHAPE, EndBlockProperties.HydraluxShape.ROOTS)
);
for (int i = 1; i < h - 2; i++) {
mut.setY(pos.getY() + i);
BlocksHelper.setWithoutUpdate(
world,
mut,
state.setValue(EndBlockProperties.HYDRALUX_SHAPE, EndBlockProperties.HydraluxShape.VINE)
);
}
mut.setY(mut.getY() + 1);
boolean big = random.nextBoolean();
BlocksHelper.setWithoutUpdate(
world,
mut,
state.setValue(
EndBlockProperties.HYDRALUX_SHAPE,
big
? EndBlockProperties.HydraluxShape.FLOWER_BIG_BOTTOM
: EndBlockProperties.HydraluxShape.FLOWER_SMALL_BOTTOM
)
);
mut.setY(mut.getY() + 1);
BlocksHelper.setWithoutUpdate(
world,
mut,
state.setValue(
EndBlockProperties.HYDRALUX_SHAPE,
big
? EndBlockProperties.HydraluxShape.FLOWER_BIG_TOP
: EndBlockProperties.HydraluxShape.FLOWER_SMALL_TOP
)
);
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.SULPHURIC_ROCK.stone);
}
}

View file

@ -0,0 +1,161 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlockNotFull;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.interfaces.tools.AddMineablePickaxe;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.betterend.blocks.entities.BlockEntityHydrothermalVent;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("deprecation")
public class HydrothermalVentBlock extends BaseBlockNotFull implements EntityBlock, LiquidBlockContainer, SimpleWaterloggedBlock, AddMineablePickaxe {
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
public static final BooleanProperty ACTIVATED = BlockProperties.ACTIVE;
private static final VoxelShape SHAPE = Block.box(1, 1, 1, 15, 16, 15);
public HydrothermalVentBlock() {
super(FabricBlockSettings.of(Material.STONE)
.sound(SoundType.STONE)
.noCollission()
.requiresCorrectToolForDrops());
this.registerDefaultState(defaultBlockState().setValue(WATERLOGGED, true).setValue(ACTIVATED, false));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(WATERLOGGED, ACTIVATED);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE;
}
@Override
public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) {
return false;
}
@Override
public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) {
return false;
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
state = world.getBlockState(pos.below());
return state.is(EndBlocks.SULPHURIC_ROCK.stone);
}
@Override
public BlockState updateShape(
BlockState state,
Direction facing,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
if (!canSurvive(state, world, pos)) {
return Blocks.WATER.defaultBlockState();
} else if (state.getValue(WATERLOGGED) && facing == Direction.UP && neighborState.is(Blocks.WATER)) {
world.scheduleTick(pos, this, 20);
}
return state;
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
LevelAccessor worldAccess = ctx.getLevel();
BlockPos blockPos = ctx.getClickedPos();
return this.defaultBlockState()
.setValue(WATERLOGGED, worldAccess.getFluidState(blockPos).getType() == Fluids.WATER);
}
@Override
public FluidState getFluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
}
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new BlockEntityHydrothermalVent(pos, state);
}
@Override
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
BlockPos up = pos.above();
if (world.getBlockState(up).is(Blocks.WATER)) {
BlocksHelper.setWithoutUpdate(world, up, EndBlocks.VENT_BUBBLE_COLUMN);
world.scheduleTick(up, EndBlocks.VENT_BUBBLE_COLUMN, 5);
}
}
@Override
public void setPlacedBy(
Level world,
BlockPos pos,
BlockState state,
@Nullable LivingEntity placer,
ItemStack itemStack
) {
if (world instanceof ServerLevel && state.getValue(WATERLOGGED) && world.getBlockState(pos.above())
.is(Blocks.WATER)) {
tick(state, (ServerLevel) world, pos, world.random);
}
}
@Environment(EnvType.CLIENT)
public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {
super.animateTick(state, world, pos, random);
if (!state.getValue(ACTIVATED) && random.nextBoolean()) {
double x = pos.getX() + random.nextDouble();
double y = pos.getY() + 0.9 + random.nextDouble() * 0.3;
double z = pos.getZ() + random.nextDouble();
world.addParticle(ParticleTypes.LARGE_SMOKE, x, y, z, 0, 0, 0);
}
}
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(
Level level,
BlockState blockState,
BlockEntityType<T> blockEntityType
) {
return BlockEntityHydrothermalVent::tick;
}
}

View file

@ -0,0 +1,103 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.PedestalBlock;
import org.betterx.betterend.blocks.entities.InfusionPedestalEntity;
import org.betterx.betterend.rituals.InfusionRitual;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("deprecation")
public class InfusionPedestal extends PedestalBlock {
private static final VoxelShape SHAPE_DEFAULT;
private static final VoxelShape SHAPE_PEDESTAL_TOP;
public InfusionPedestal() {
super(Blocks.OBSIDIAN);
this.height = 1.08F;
}
@Override
public void checkRitual(Level world, Player player, BlockPos pos) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof InfusionPedestalEntity) {
InfusionPedestalEntity pedestal = (InfusionPedestalEntity) blockEntity;
if (pedestal.hasRitual()) {
InfusionRitual ritual = pedestal.getRitual();
if (!ritual.isValid()) {
ritual.configure();
}
pedestal.getRitual().checkRecipe();
} else {
InfusionRitual ritual = pedestal.linkRitual(pedestal, world, pos);
ritual.checkRecipe();
}
}
}
@Override
public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return new InfusionPedestalEntity(blockPos, blockState);
}
@Override
public boolean hasUniqueEntity() {
return true;
}
@Override
@Deprecated
public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
if (state.is(this)) {
switch (state.getValue(STATE)) {
case PEDESTAL_TOP: {
return SHAPE_PEDESTAL_TOP;
}
case DEFAULT: {
return SHAPE_DEFAULT;
}
default: {
return super.getShape(state, world, pos, context);
}
}
}
return super.getShape(state, world, pos, context);
}
@Override
@Nullable
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(
Level level,
BlockState blockState,
BlockEntityType<T> blockEntityType
) {
return InfusionPedestalEntity::tickEnity;
}
static {
VoxelShape basinUp = Block.box(2, 3, 2, 14, 4, 14);
VoxelShape basinDown = Block.box(0, 0, 0, 16, 3, 16);
VoxelShape pedestalTop = Block.box(1, 9, 1, 15, 11, 15);
VoxelShape pedestalDefault = Block.box(1, 13, 1, 15, 15, 15);
VoxelShape pillar = Block.box(3, 0, 3, 13, 9, 13);
VoxelShape pillarDefault = Block.box(3, 4, 3, 13, 13, 13);
VoxelShape eyeDefault = Block.box(4, 15, 4, 12, 16, 12);
VoxelShape eyeTop = Block.box(4, 11, 4, 12, 12, 12);
VoxelShape basin = Shapes.or(basinDown, basinUp);
SHAPE_DEFAULT = Shapes.or(basin, pillarDefault, pedestalDefault, eyeDefault);
SHAPE_PEDESTAL_TOP = Shapes.or(pillar, pedestalTop, eyeTop);
}
}

View file

@ -0,0 +1,107 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.client.models.ModelsHelper;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.BlockModelProvider;
import org.betterx.bclib.interfaces.CustomColorProvider;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.client.models.Patterns;
import org.betterx.betterend.noise.OpenSimplexNoise;
import org.betterx.ui.ColorUtil;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.core.Vec3i;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SlimeBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.storage.loot.LootContext;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Optional;
import org.jetbrains.annotations.Nullable;
public class JellyshroomCapBlock extends SlimeBlock implements RenderLayerProvider, BlockModelProvider, CustomColorProvider {
public static final IntegerProperty COLOR = EndBlockProperties.COLOR;
private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(0);
private final Vec3i colorStart;
private final Vec3i colorEnd;
private final int coloritem;
public JellyshroomCapBlock(int r1, int g1, int b1, int r2, int g2, int b2) {
super(FabricBlockSettings.copyOf(Blocks.SLIME_BLOCK));
colorStart = new Vec3i(r1, g1, b1);
colorEnd = new Vec3i(r2, g2, b2);
coloritem = ColorUtil.color((r1 + r2) >> 1, (g1 + g2) >> 1, (b1 + b2) >> 1);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
double px = ctx.getClickedPos().getX() * 0.1;
double py = ctx.getClickedPos().getY() * 0.1;
double pz = ctx.getClickedPos().getZ() * 0.1;
return this.defaultBlockState().setValue(COLOR, MHelper.floor(NOISE.eval(px, py, pz) * 3.5 + 4));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(COLOR);
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.TRANSLUCENT;
}
@Override
@SuppressWarnings("deprecation")
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
return Lists.newArrayList(new ItemStack(this));
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) {
return getBlockModel(resourceLocation, defaultBlockState());
}
@Override
@Environment(EnvType.CLIENT)
public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) {
Optional<String> pattern = Patterns.createJson(Patterns.BLOCK_COLORED, "jellyshroom_cap");
return ModelsHelper.fromPattern(pattern);
}
@Override
public BlockColor getProvider() {
return (state, world, pos, tintIndex) -> {
float delta = (float) state.getValue(COLOR) / 7F;
int r = Mth.floor(Mth.lerp(delta, colorStart.getX() / 255F, colorEnd.getX() / 255F) * 255F);
int g = Mth.floor(Mth.lerp(delta, colorStart.getY() / 255F, colorEnd.getY() / 255F) * 255F);
int b = Mth.floor(Mth.lerp(delta, colorStart.getZ() / 255F, colorEnd.getZ() / 255F) * 255F);
return ColorUtil.color(r, g, b);
};
}
@Override
public ItemColor getItemProvider() {
return (stack, tintIndex) -> {
return coloritem;
};
}
}

View file

@ -0,0 +1,29 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.PottableFeatureSapling;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndFeatures;
import org.betterx.betterend.world.features.trees.LacugroveFeature;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public class LacugroveSaplingBlock extends PottableFeatureSapling<LacugroveFeature, NoneFeatureConfiguration> {
public LacugroveSaplingBlock() {
super((state) -> EndFeatures.LACUGROVE.configuredFeature);
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
return world.getBlockState(pos.below()).is(EndBlocks.END_MOSS) || world.getBlockState(pos.below())
.is(EndBlocks.ENDSTONE_DUST);
}
@Override
public boolean canPlantOn(Block block) {
return block == EndBlocks.END_MOSS;
}
}

View file

@ -0,0 +1,76 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.BlockProperties.PentaShape;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.blocks.basis.EndPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.storage.loot.LootContext;
import java.util.Collections;
import java.util.List;
public class LanceleafBlock extends EndPlantBlock {
public static final EnumProperty<PentaShape> SHAPE = BlockProperties.PENTA_SHAPE;
public static final IntegerProperty ROTATION = BlockProperties.ROTATION;
public LanceleafBlock() {
super();
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SHAPE, ROTATION);
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
PentaShape shape = state.getValue(SHAPE);
if (shape == PentaShape.TOP) {
return world.getBlockState(pos.below()).is(this);
} else if (shape == PentaShape.BOTTOM) {
return world.getBlockState(pos.below()).is(EndBlocks.AMBER_MOSS) && world.getBlockState(pos.above())
.is(this);
} else {
return world.getBlockState(pos.below()).is(this) && world.getBlockState(pos.above()).is(this);
}
}
@Override
public BlockState updateShape(
BlockState state,
Direction facing,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
if (!canSurvive(state, world, pos)) {
return Blocks.AIR.defaultBlockState();
} else {
return state;
}
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
if (state.getValue(SHAPE) == PentaShape.BOTTOM) {
return Collections.singletonList(new ItemStack(EndBlocks.LANCELEAF_SEED));
}
return MHelper.RANDOM.nextBoolean() ? Collections.emptyList() : Collections.singletonList(new ItemStack(
EndBlocks.LANCELEAF_SEED));
}
}

View file

@ -0,0 +1,61 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.BlockProperties.PentaShape;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.state.BlockState;
public class LanceleafSeedBlock extends EndPlantWithAgeBlock {
public LanceleafSeedBlock() {
super(basePlantSettings().offsetType(OffsetType.NONE));
}
@Override
public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) {
int height = MHelper.randRange(4, 6, random);
int h = BlocksHelper.upRay(world, pos, height + 2);
if (h < height + 1) {
return;
}
int rotation = random.nextInt(4);
MutableBlockPos mut = new MutableBlockPos().set(pos);
BlockState plant = EndBlocks.LANCELEAF.defaultBlockState().setValue(BlockProperties.ROTATION, rotation);
BlocksHelper.setWithoutUpdate(world, mut, plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.BOTTOM));
BlocksHelper.setWithoutUpdate(
world,
mut.move(Direction.UP),
plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.PRE_BOTTOM)
);
for (int i = 2; i < height - 2; i++) {
BlocksHelper.setWithoutUpdate(
world,
mut.move(Direction.UP),
plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.MIDDLE)
);
}
BlocksHelper.setWithoutUpdate(
world,
mut.move(Direction.UP),
plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.PRE_TOP)
);
BlocksHelper.setWithoutUpdate(
world,
mut.move(Direction.UP),
plant.setValue(BlockProperties.PENTA_SHAPE, PentaShape.TOP)
);
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.AMBER_MOSS);
}
}

View file

@ -0,0 +1,70 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.interfaces.tools.AddMineableShears;
import org.betterx.betterend.blocks.basis.EndPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
public class LargeAmaranitaBlock extends EndPlantBlock implements AddMineableShears {
public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE;
private static final VoxelShape SHAPE_BOTTOM = Block.box(4, 0, 4, 12, 14, 12);
private static final VoxelShape SHAPE_TOP = Shapes.or(Block.box(1, 3, 1, 15, 16, 15), SHAPE_BOTTOM);
public LargeAmaranitaBlock() {
super(basePlantSettings()
.lightLevel((state) -> (state.getValue(SHAPE) == TripleShape.TOP) ? 15 : 0)
.offsetType(OffsetType.NONE)
);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return state.getValue(SHAPE) == TripleShape.TOP ? SHAPE_TOP : SHAPE_BOTTOM;
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.SANGNUM) || state.is(EndBlocks.MOSSY_OBSIDIAN) || state.is(EndBlocks.MOSSY_DRAGON_BONE);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SHAPE);
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
TripleShape shape = state.getValue(SHAPE);
if (shape == TripleShape.BOTTOM) {
return isTerrain(world.getBlockState(pos.below())) && world.getBlockState(pos.above()).is(this);
} else if (shape == TripleShape.TOP) {
return world.getBlockState(pos.below()).is(this);
} else {
return world.getBlockState(pos.below()).is(this) && world.getBlockState(pos.above()).is(this);
}
}
@Override
public boolean isValidBonemealTarget(BlockGetter world, BlockPos pos, BlockState state, boolean isClient) {
return false;
}
@Override
public boolean isBonemealSuccess(Level world, RandomSource random, BlockPos pos, BlockState state) {
return false;
}
}

View file

@ -0,0 +1,28 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.PottableFeatureSapling;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndFeatures;
import org.betterx.betterend.world.features.trees.LucerniaFeature;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public class LucerniaSaplingBlock extends PottableFeatureSapling<LucerniaFeature, NoneFeatureConfiguration> {
public LucerniaSaplingBlock() {
super((state) -> EndFeatures.LUCERNIA.configuredFeature);
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
return world.getBlockState(pos.below()).is(EndBlocks.RUTISCUS);
}
@Override
public boolean canPlantOn(Block block) {
return block == EndBlocks.RUTISCUS;
}
}

View file

@ -0,0 +1,117 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlockNotFull;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.interfaces.tools.AddMineableAxe;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndItems;
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Collections;
import java.util.List;
@SuppressWarnings("deprecation")
public class LumecornBlock extends BaseBlockNotFull implements RenderLayerProvider, AddMineableAxe {
public static final EnumProperty<EndBlockProperties.LumecornShape> SHAPE = EnumProperty.create(
"shape",
EndBlockProperties.LumecornShape.class
);
private static final VoxelShape SHAPE_BOTTOM = Block.box(6, 0, 6, 10, 16, 10);
private static final VoxelShape SHAPE_TOP = Block.box(6, 0, 6, 10, 8, 10);
public LumecornBlock() {
super(FabricBlockSettings.of(Material.WOOD)
.hardness(0.5F)
.luminance(state -> state.getValue(SHAPE).getLight()));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SHAPE);
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return state.getValue(SHAPE) == EndBlockProperties.LumecornShape.LIGHT_TOP ? SHAPE_TOP : SHAPE_BOTTOM;
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
EndBlockProperties.LumecornShape shape = state.getValue(SHAPE);
if (shape == EndBlockProperties.LumecornShape.BOTTOM_BIG || shape == EndBlockProperties.LumecornShape.BOTTOM_SMALL) {
return world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES);
} else if (shape == EndBlockProperties.LumecornShape.LIGHT_TOP) {
return world.getBlockState(pos.below()).is(this);
} else {
return world.getBlockState(pos.below()).is(this) && world.getBlockState(pos.above()).is(this);
}
}
@Override
public BlockState updateShape(
BlockState state,
Direction facing,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
if (!canSurvive(state, world, pos)) {
return Blocks.AIR.defaultBlockState();
} else {
return state;
}
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
EndBlockProperties.LumecornShape shape = state.getValue(SHAPE);
if (shape == EndBlockProperties.LumecornShape.BOTTOM_BIG || shape == EndBlockProperties.LumecornShape.BOTTOM_SMALL || shape == EndBlockProperties.LumecornShape.MIDDLE) {
return Collections.singletonList(new ItemStack(
EndBlocks.LUMECORN_SEED,
MHelper.randRange(1, 2, MHelper.RANDOM_SOURCE)
));
}
return MHelper.RANDOM.nextBoolean()
? Collections.singletonList(new ItemStack(EndItems.LUMECORN_ROD))
: Collections
.emptyList();
}
@Override
@Environment(EnvType.CLIENT)
public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) {
EndBlockProperties.LumecornShape shape = state.getValue(SHAPE);
if (shape == EndBlockProperties.LumecornShape.BOTTOM_BIG || shape == EndBlockProperties.LumecornShape.BOTTOM_SMALL || shape == EndBlockProperties.LumecornShape.MIDDLE) {
return new ItemStack(EndBlocks.LUMECORN_SEED);
}
return new ItemStack(EndItems.LUMECORN_ROD);
}
}

View file

@ -0,0 +1,39 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndFeatures;
import net.minecraft.core.BlockPos;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import java.util.Optional;
public class LumecornSeedBlock extends EndPlantWithAgeBlock {
public LumecornSeedBlock() {
super(basePlantSettings().offsetType(OffsetType.NONE));
}
@Override
public void growAdult(WorldGenLevel world, RandomSource random, BlockPos pos) {
((Feature<NoneFeatureConfiguration>) (EndFeatures.LUMECORN.getFeature())).place(new FeaturePlaceContext<>(
Optional.empty(),
world,
null,
random,
pos,
null
));
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.END_MOSS);
}
}

View file

@ -0,0 +1,141 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlockNotFull;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.Tuple;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.BucketPickup;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import com.google.common.collect.Lists;
import java.util.Queue;
@SuppressWarnings("deprecation")
public class MengerSpongeBlock extends BaseBlockNotFull implements RenderLayerProvider {
private static final VoxelShape SHAPE;
public MengerSpongeBlock() {
super(FabricBlockSettings.copyOf(Blocks.SPONGE).noOcclusion());
}
@Override
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
if (absorbWater(world, pos)) {
world.setBlockAndUpdate(pos, EndBlocks.MENGER_SPONGE_WET.defaultBlockState());
}
}
@Override
public BlockState updateShape(
BlockState state,
Direction facing,
BlockState neighborState,
LevelAccessor world,
BlockPos pos,
BlockPos neighborPos
) {
if (absorbWater(world, pos)) {
return EndBlocks.MENGER_SPONGE_WET.defaultBlockState();
}
return state;
}
private boolean absorbWater(LevelAccessor world, BlockPos pos) {
Queue<Tuple<BlockPos, Integer>> queue = Lists.newLinkedList();
queue.add(new Tuple<>(pos, 0));
int i = 0;
while (!queue.isEmpty()) {
Tuple<BlockPos, Integer> pair = queue.poll();
BlockPos blockPos = pair.getA();
int j = pair.getB();
for (Direction direction : Direction.values()) {
BlockPos blockPos2 = blockPos.relative(direction);
BlockState blockState = world.getBlockState(blockPos2);
FluidState fluidState = world.getFluidState(blockPos2);
Material material = blockState.getMaterial();
if (fluidState.is(FluidTags.WATER)) {
if (blockState.getBlock() instanceof BucketPickup && !((BucketPickup) blockState.getBlock()).pickupBlock(
world,
blockPos2,
blockState
)
.isEmpty()) {
++i;
if (j < 6) {
queue.add(new Tuple<>(blockPos2, j + 1));
}
} else if (blockState.getBlock() instanceof LiquidBlock) {
world.setBlock(blockPos2, Blocks.AIR.defaultBlockState(), 3);
++i;
if (j < 6) {
queue.add(new Tuple<>(blockPos2, j + 1));
}
} else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) {
BlockEntity blockEntity = blockState.hasBlockEntity() ? world.getBlockEntity(blockPos2) : null;
dropResources(blockState, world, blockPos2, blockEntity);
world.setBlock(blockPos2, Blocks.AIR.defaultBlockState(), 3);
++i;
if (j < 6) {
queue.add(new Tuple<>(blockPos2, j + 1));
}
}
}
}
if (i > 64) {
break;
}
}
return i > 0;
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
public VoxelShape getShape(
BlockState blockState,
BlockGetter blockGetter,
BlockPos blockPos,
CollisionContext collisionContext
) {
return SHAPE;
}
static {
SHAPE = Shapes.or(
Shapes.or(box(0, 0, 0, 16, 6, 6), box(0, 0, 10, 16, 6, 16),
Shapes.or(box(0, 10, 0, 16, 16, 6), box(0, 10, 10, 16, 16, 16)),
Shapes.or(box(0, 0, 0, 6, 6, 16), box(10, 0, 0, 16, 6, 16)),
Shapes.or(box(0, 10, 0, 6, 16, 16), box(10, 10, 0, 16, 16, 16)),
Shapes.or(box(0, 0, 0, 6, 16, 6), box(10, 0, 0, 16, 16, 6)),
Shapes.or(box(0, 0, 10, 6, 16, 16), box(10, 0, 10, 16, 16, 16))
));
}
}

View file

@ -0,0 +1,130 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlockNotFull;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
@SuppressWarnings("deprecation")
public class MengerSpongeWetBlock extends BaseBlockNotFull implements RenderLayerProvider {
public MengerSpongeWetBlock() {
super(FabricBlockSettings.copyOf(Blocks.WET_SPONGE).noOcclusion());
}
@Override
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
if (world.dimensionType().ultraWarm()) {
world.setBlock(pos, EndBlocks.MENGER_SPONGE.defaultBlockState(), 3);
world.levelEvent(2009, pos, 0);
world.playSound(
null,
pos,
SoundEvents.FIRE_EXTINGUISH,
SoundSource.BLOCKS,
1.0F,
(1.0F + world.getRandom().nextFloat() * 0.2F) * 0.7F
);
}
}
@Override
@Environment(EnvType.CLIENT)
public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {
Direction direction = Direction.getRandom(random);
if (direction != Direction.UP) {
BlockPos blockPos = pos.relative(direction);
BlockState blockState = world.getBlockState(blockPos);
if (!state.canOcclude() || !blockState.isFaceSturdy(world, blockPos, direction.getOpposite())) {
double x = pos.getX();
double y = pos.getY();
double z = pos.getZ();
if (direction == Direction.DOWN) {
y -= 0.05;
x += random.nextDouble();
z += random.nextDouble();
} else {
y += random.nextDouble() * 0.8;
if (direction.getAxis() == Direction.Axis.X) {
z += random.nextDouble();
if (direction == Direction.EAST) {
++x;
} else {
x += 0.05;
}
} else {
x += random.nextDouble();
if (direction == Direction.SOUTH) {
++z;
} else {
z += 0.05;
}
}
}
world.addParticle(ParticleTypes.DRIPPING_WATER, x, y, z, 0, 0, 0);
}
}
}
@Override
public void playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) {
BlocksHelper.setWithUpdate(world, pos, Blocks.AIR);
if (!world.isClientSide()) {
world.levelEvent(2001, pos, getId(state));
}
if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) && (player == null || !player.isCreative())) {
ItemEntity drop = new ItemEntity(
world,
pos.getX() + 0.5,
pos.getY() + 0.5,
pos.getZ() + 0.5,
new ItemStack(this)
);
world.addFreshEntity(drop);
}
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
public FluidState getFluidState(BlockState state) {
return Fluids.WATER.getSource(false);
}
@Override
public VoxelShape getShape(
BlockState blockState,
BlockGetter blockGetter,
BlockPos blockPos,
CollisionContext collisionContext
) {
return EndBlocks.MENGER_SPONGE.getShape(blockState, blockGetter, blockPos, collisionContext);
}
}

View file

@ -0,0 +1,13 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import net.minecraft.world.level.block.Blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class MissingTileBlock extends BaseBlock {
public MissingTileBlock() {
super(FabricBlockSettings.copyOf(Blocks.END_STONE));
}
}

View file

@ -0,0 +1,69 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseRotatedPillarBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SnowLayerBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.lighting.LayerLightEngine;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Collections;
import java.util.List;
@SuppressWarnings("deprecation")
public class MossyDragonBoneBlock extends BaseRotatedPillarBlock {
public MossyDragonBoneBlock() {
super(FabricBlockSettings.copyOf(Blocks.BONE_BLOCK).hardness(0.5F).randomTicks());
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
return Collections.singletonList(new ItemStack(this));
}
return Collections.singletonList(new ItemStack(EndBlocks.DRAGON_BONE_BLOCK));
}
@Override
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (random.nextInt(16) == 0 && !canSurvive(state, world, pos)) {
world.setBlockAndUpdate(pos, Blocks.BONE_BLOCK.defaultBlockState().setValue(AXIS, state.getValue(AXIS)));
}
}
@Override
public boolean canSurvive(BlockState state, LevelReader worldView, BlockPos pos) {
BlockPos blockPos = pos.above();
BlockState blockState = worldView.getBlockState(blockPos);
if (blockState.is(Blocks.SNOW) && blockState.getValue(SnowLayerBlock.LAYERS) == 1) {
return true;
} else if (blockState.getFluidState().getAmount() == 8) {
return false;
} else {
int i = LayerLightEngine.getLightBlockInto(
worldView,
state,
pos,
blockState,
blockPos,
Direction.UP,
blockState.getLightBlock(worldView, blockPos)
);
return i < 5;
}
}
}

View file

@ -0,0 +1,47 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import org.betterx.bclib.interfaces.TagProvider;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.worlds.together.tag.v3.MineableTags;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.Material;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.List;
public class MossyGlowshroomCapBlock extends BaseBlock implements TagProvider {
public static final BooleanProperty TRANSITION = EndBlockProperties.TRANSITION;
public MossyGlowshroomCapBlock() {
super(FabricBlockSettings.of(Material.WOOD).sound(SoundType.WOOD));
this.registerDefaultState(this.stateDefinition.any().setValue(TRANSITION, false));
}
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
return this.defaultBlockState()
.setValue(
TRANSITION,
EndBlocks.MOSSY_GLOWSHROOM.isTreeLog(ctx.getLevel()
.getBlockState(ctx.getClickedPos().below()))
);
}
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(TRANSITION);
}
@Override
public void addTags(List<TagKey<Block>> blockTags, List<TagKey<Item>> itemTags) {
blockTags.add(MineableTags.AXE);
}
}

View file

@ -0,0 +1,29 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.PottableFeatureSapling;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.betterend.registry.EndFeatures;
import org.betterx.betterend.world.features.trees.MossyGlowshroomFeature;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
public class MossyGlowshroomSaplingBlock extends PottableFeatureSapling<MossyGlowshroomFeature, NoneFeatureConfiguration> {
public MossyGlowshroomSaplingBlock() {
super(7, (state) -> EndFeatures.MOSSY_GLOWSHROOM.configuredFeature);
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
return world.getBlockState(pos.below()).is(EndBlocks.END_MOSS) || world.getBlockState(pos.below())
.is(EndBlocks.END_MYCELIUM);
}
@Override
public boolean canPlantOn(Block block) {
return block == EndBlocks.END_MOSS || block == EndBlocks.END_MYCELIUM;
}
}

View file

@ -0,0 +1,68 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SnowLayerBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.lighting.LayerLightEngine;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import java.util.Collections;
import java.util.List;
public class MossyObsidian extends BaseBlock {
public MossyObsidian() {
super(FabricBlockSettings.copyOf(Blocks.OBSIDIAN).hardness(3).randomTicks());
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) > 0) {
return Collections.singletonList(new ItemStack(this));
}
return Collections.singletonList(new ItemStack(Blocks.OBSIDIAN));
}
@Override
@SuppressWarnings("deprecation")
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (random.nextInt(16) == 0 && !canSurvive(state, world, pos)) {
world.setBlockAndUpdate(pos, Blocks.OBSIDIAN.defaultBlockState());
}
}
@SuppressWarnings("deprecation")
public boolean canSurvive(BlockState state, LevelReader worldView, BlockPos pos) {
BlockPos blockPos = pos.above();
BlockState blockState = worldView.getBlockState(blockPos);
if (blockState.is(Blocks.SNOW) && blockState.getValue(SnowLayerBlock.LAYERS) == 1) {
return true;
} else if (blockState.getFluidState().getAmount() == 8) {
return false;
} else {
int i = LayerLightEngine.getLightBlockInto(
worldView,
state,
pos,
blockState,
blockPos,
Direction.UP,
blockState.getLightBlock(worldView, blockPos)
);
return i < 5;
}
}
}

View file

@ -0,0 +1,50 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.EndPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.util.RandomSource;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
public class MurkweedBlock extends EndPlantBlock {
@Override
@Environment(EnvType.CLIENT)
public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {
double x = pos.getX() + random.nextDouble();
double y = pos.getY() + random.nextDouble() * 0.5 + 0.5;
double z = pos.getZ() + random.nextDouble();
double v = random.nextDouble() * 0.1;
world.addParticle(ParticleTypes.ENTITY_EFFECT, x, y, z, v, v, v);
}
@Override
@SuppressWarnings("deprecation")
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if (entity instanceof LivingEntity && !((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS)) {
((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 50));
}
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.SHADOW_GRASS);
}
@Override
@SuppressWarnings("deprecation")
public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) {
return false;
}
}

View file

@ -0,0 +1,59 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.items.tool.BaseShearsItem;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.blocks.basis.EndPlantBlock;
import org.betterx.betterend.registry.EndBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import com.google.common.collect.Lists;
import java.util.List;
public class NeedlegrassBlock extends EndPlantBlock {
@Override
@SuppressWarnings("deprecation")
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if (entity instanceof LivingEntity) {
entity.hurt(DamageSource.CACTUS, 0.1F);
}
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null && BaseShearsItem.isShear(tool) || EnchantmentHelper.getItemEnchantmentLevel(
Enchantments.SILK_TOUCH,
tool
) > 0) {
return Lists.newArrayList(new ItemStack(this));
} else {
return Lists.newArrayList(new ItemStack(Items.STICK, MHelper.randRange(0, 2, MHelper.RANDOM_SOURCE)));
}
}
@Override
protected boolean isTerrain(BlockState state) {
return state.is(EndBlocks.SHADOW_GRASS);
}
@Override
@SuppressWarnings("deprecation")
public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) {
return false;
}
}

View file

@ -0,0 +1,13 @@
package org.betterx.betterend.blocks;
import org.betterx.betterend.blocks.basis.LitPillarBlock;
import net.minecraft.world.level.block.Blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class NeonCactusBlock extends LitPillarBlock {
public NeonCactusBlock() {
super(FabricBlockSettings.copyOf(Blocks.CACTUS).luminance(15));
}
}

View file

@ -0,0 +1,438 @@
package org.betterx.betterend.blocks;
import org.betterx.bclib.blocks.BaseBlockNotFull;
import org.betterx.bclib.blocks.BlockProperties;
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
import org.betterx.bclib.client.render.BCLRenderLayer;
import org.betterx.bclib.interfaces.RenderLayerProvider;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.bclib.util.MHelper;
import org.betterx.betterend.blocks.EndBlockProperties.CactusBottom;
import org.betterx.betterend.interfaces.PottablePlant;
import org.betterx.betterend.registry.EndBlocks;
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.*;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.EnumMap;
import java.util.List;
@SuppressWarnings("deprecation")
public class NeonCactusPlantBlock extends BaseBlockNotFull implements SimpleWaterloggedBlock, RenderLayerProvider, PottablePlant {
public static final EnumProperty<TripleShape> SHAPE = BlockProperties.TRIPLE_SHAPE;
public static final EnumProperty<CactusBottom> CACTUS_BOTTOM = EndBlockProperties.CACTUS_BOTTOM;
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
public static final DirectionProperty FACING = BlockStateProperties.FACING;
private static final EnumMap<Direction, VoxelShape> BIG_SHAPES_OPEN = Maps.newEnumMap(Direction.class);
private static final EnumMap<Direction, VoxelShape> MEDIUM_SHAPES_OPEN = Maps.newEnumMap(Direction.class);
private static final EnumMap<Direction, VoxelShape> SMALL_SHAPES_OPEN = Maps.newEnumMap(Direction.class);
private static final EnumMap<Axis, VoxelShape> BIG_SHAPES = Maps.newEnumMap(Axis.class);
private static final EnumMap<Axis, VoxelShape> MEDIUM_SHAPES = Maps.newEnumMap(Axis.class);
private static final EnumMap<Axis, VoxelShape> SMALL_SHAPES = Maps.newEnumMap(Axis.class);
private static final int MAX_LENGTH = 12;
public NeonCactusPlantBlock() {
super(FabricBlockSettings.copyOf(Blocks.CACTUS).luminance(15).randomTicks());
registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)
.setValue(FACING, Direction.UP)
.setValue(SHAPE, TripleShape.TOP));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> stateManager) {
stateManager.add(SHAPE, CACTUS_BOTTOM, WATERLOGGED, FACING);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
LevelAccessor world = ctx.getLevel();
BlockPos pos = ctx.getClickedPos();
Direction dir = ctx.getClickedFace();
BlockState down = world.getBlockState(pos.relative(dir.getOpposite()));
BlockState state = this.defaultBlockState()
.setValue(WATERLOGGED, world.getFluidState(pos).getType() == Fluids.WATER)
.setValue(FACING, ctx.getClickedFace());
if (down.is(Blocks.END_STONE) || down.is(EndBlocks.ENDSTONE_DUST)) {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND);
} else if (down.is(EndBlocks.END_MOSS)) {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS);
} else {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY);
}
return state;
}
@Override
public BlockState rotate(BlockState state, Rotation rotation) {
return BlocksHelper.rotateHorizontal(state, rotation, FACING);
}
@Override
public BlockState mirror(BlockState state, Mirror mirror) {
return BlocksHelper.mirrorHorizontal(state, mirror, FACING);
}
@Override
public FluidState getFluidState(BlockState state) {
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
}
@Override
public BlockState updateShape(
BlockState state,
Direction direction,
BlockState newState,
LevelAccessor world,
BlockPos pos,
BlockPos posFrom
) {
world.scheduleTick(pos, this, 2);
if (state.getValue(WATERLOGGED)) {
world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
}
Direction dir = state.getValue(FACING);
BlockState downState = world.getBlockState(pos.relative(dir.getOpposite()));
if (downState.is(Blocks.END_STONE) || downState.is(EndBlocks.ENDSTONE_DUST)) {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND);
} else if (downState.is(EndBlocks.END_MOSS)) {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS);
} else {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY);
}
return state;
}
@Override
public void tick(BlockState blockState, ServerLevel serverLevel, BlockPos blockPos, RandomSource random) {
if (!blockState.canSurvive(serverLevel, blockPos)) {
serverLevel.destroyBlock(blockPos, true, null, 1);
}
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
TripleShape shape = state.getValue(SHAPE);
Direction dir = state.getValue(FACING);
BlockState next = view.getBlockState(pos.relative(dir));
if (next.is(this)) {
Axis axis = dir.getAxis();
if (shape == TripleShape.BOTTOM) {
return BIG_SHAPES.get(axis);
}
return shape == TripleShape.MIDDLE ? MEDIUM_SHAPES.get(axis) : SMALL_SHAPES.get(axis);
} else {
if (shape == TripleShape.BOTTOM) {
return BIG_SHAPES_OPEN.get(dir);
}
return shape == TripleShape.MIDDLE ? MEDIUM_SHAPES_OPEN.get(dir) : SMALL_SHAPES_OPEN.get(dir);
}
}
@Override
public boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
Direction dir = state.getValue(FACING);
BlockPos supportPos = pos.relative(dir.getOpposite());
BlockState support = level.getBlockState(supportPos);
return support.is(this) || support.isFaceSturdy(level, supportPos, dir);
}
@Override
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (!this.canSurvive(state, world, pos) || random.nextInt(8) > 0) {
return;
}
Direction dir = state.getValue(FACING);
if (!world.isEmptyBlock(pos.relative(dir))) {
return;
}
int length = getLength(state, world, pos, MAX_LENGTH);
if (length < 0 || length > MAX_LENGTH - 1) {
return;
}
if (dir.getAxis().isHorizontal()) {
int horizontal = getHorizontal(state, world, pos, 2);
if (horizontal > random.nextInt(2)) {
dir = Direction.UP;
if (!world.getBlockState(pos.above()).isAir()) {
return;
}
}
} else if (length > 1 && world.getBlockState(pos.relative(dir.getOpposite())).is(this)) {
Direction side = getSideDirection(world, pos, state, dir, random);
BlockPos sidePos = pos.relative(side);
if (world.isEmptyBlock(sidePos)) {
BlockState placement = state.setValue(SHAPE, TripleShape.TOP)
.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY)
.setValue(WATERLOGGED, false)
.setValue(FACING, side);
BlocksHelper.setWithoutUpdate(world, sidePos, placement);
}
}
BlockState placement = state.setValue(SHAPE, TripleShape.TOP)
.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY)
.setValue(WATERLOGGED, false)
.setValue(FACING, dir);
BlocksHelper.setWithoutUpdate(world, pos.relative(dir), placement);
mutateStem(placement, world, pos, MAX_LENGTH);
}
public void growPlant(WorldGenLevel world, BlockPos pos, RandomSource random) {
growPlant(world, pos, random, MHelper.randRange(MAX_LENGTH >> 1, MAX_LENGTH, random));
}
public void growPlant(WorldGenLevel world, BlockPos pos, RandomSource random, int iterations) {
BlockState state = defaultBlockState();
BlockState downState = world.getBlockState(pos.below());
if (downState.is(Blocks.END_STONE) || downState.is(EndBlocks.ENDSTONE_DUST)) {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.SAND);
} else if (downState.is(EndBlocks.END_MOSS)) {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.MOSS);
} else {
state = state.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY);
}
BlocksHelper.setWithoutUpdate(world, pos, state);
List<MutableBlockPos> ends = Lists.newArrayList(pos.mutable());
for (int i = 0; i < iterations; i++) {
int count = ends.size();
for (int n = 0; n < count; n++) {
if (!growIteration(world, ends.get(n), random, ends, i)) {
ends.remove(n);
count--;
n--;
}
}
}
}
private boolean growIteration(
WorldGenLevel world,
MutableBlockPos pos,
RandomSource random,
List<MutableBlockPos> ends,
int length
) {
BlockState state = world.getBlockState(pos);
if (!state.is(this)) {
return false;
}
Direction dir = state.getValue(FACING);
if (!world.isEmptyBlock(pos.relative(dir))) {
return false;
}
if (dir.getAxis().isHorizontal()) {
int horizontal = getHorizontal(state, world, pos, 2);
if (horizontal > random.nextInt(2)) {
dir = Direction.UP;
if (!world.getBlockState(pos.above()).isAir()) {
return false;
}
}
} else if (length > 1 && world.getBlockState(pos.below()).is(this)) {
Direction side = getSideDirection(world, pos, state, dir, random);
BlockPos sidePos = pos.relative(side);
if (world.isEmptyBlock(sidePos)) {
BlockState placement = state.setValue(SHAPE, TripleShape.TOP)
.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY)
.setValue(WATERLOGGED, false)
.setValue(FACING, side);
BlocksHelper.setWithoutUpdate(world, sidePos, placement);
ends.add(sidePos.mutable());
}
}
BlockState placement = state.setValue(SHAPE, TripleShape.TOP)
.setValue(CACTUS_BOTTOM, CactusBottom.EMPTY)
.setValue(WATERLOGGED, false)
.setValue(FACING, dir);
BlocksHelper.setWithoutUpdate(world, pos.relative(dir), placement);
mutateStem(placement, world, pos, MAX_LENGTH);
pos.move(dir);
return true;
}
private Direction getSideDirection(
WorldGenLevel world,
BlockPos pos,
BlockState iterState,
Direction dir,
RandomSource random
) {
MutableBlockPos iterPos = pos.mutable();
Direction startDir = dir;
Direction lastDir = null;
while (iterState.is(this) && startDir.getAxis().isVertical()) {
startDir = iterState.getValue(FACING);
if (lastDir == null) {
for (Direction side : BlocksHelper.HORIZONTAL) {
BlockState sideState = world.getBlockState(iterPos.relative(side));
if (sideState.is(this)) {
Direction sideDir = sideState.getValue(FACING);
if (sideDir != side) {
continue;
}
lastDir = sideDir;
}
}
}
iterPos.move(dir);
iterState = world.getBlockState(iterPos);
}
Direction side = lastDir == null ? BlocksHelper.randomHorizontal(random) : lastDir.getClockWise();
if (side.getOpposite() == startDir) {
side = side.getOpposite();
}
return side;
}
@Override
public boolean isPathfindable(
BlockState blockState,
BlockGetter blockGetter,
BlockPos blockPos,
PathComputationType pathComputationType
) {
return false;
}
@Override
public void entityInside(BlockState blockState, Level level, BlockPos blockPos, Entity entity) {
entity.hurt(DamageSource.CACTUS, 1.0F);
}
private int getLength(BlockState state, ServerLevel world, BlockPos pos, int max) {
int length = 0;
Direction dir = state.getValue(FACING).getOpposite();
MutableBlockPos mut = new MutableBlockPos().set(pos);
for (int i = 0; i < max; i++) {
mut.move(dir);
state = world.getBlockState(mut);
if (!state.is(this)) {
if (!state.is(CommonBlockTags.END_STONES)) {
length = -1;
}
break;
}
dir = state.getValue(FACING).getOpposite();
length++;
}
return length;
}
private int getHorizontal(BlockState state, WorldGenLevel world, BlockPos pos, int max) {
int count = 0;
Direction dir = state.getValue(FACING).getOpposite();
MutableBlockPos mut = new MutableBlockPos().set(pos);
for (int i = 0; i < max; i++) {
mut.move(dir);
state = world.getBlockState(mut);
if (!state.is(this)) {
break;
}
dir = state.getValue(FACING).getOpposite();
if (dir.getStepY() != 0) {
break;
}
count++;
}
return count;
}
private void mutateStem(BlockState state, WorldGenLevel world, BlockPos pos, int max) {
Direction dir = state.getValue(FACING).getOpposite();
MutableBlockPos mut = new MutableBlockPos().set(pos);
for (int i = 0; i < max; i++) {
mut.move(dir);
state = world.getBlockState(mut);
if (!state.is(this)) {
return;
}
int size = (i + 2) * 3 / max;
int src = state.getValue(SHAPE).getIndex();
dir = state.getValue(FACING).getOpposite();
if (src < size) {
TripleShape shape = TripleShape.fromIndex(size);
BlocksHelper.setWithoutUpdate(world, mut, state.setValue(SHAPE, shape));
}
}
}
static {
BIG_SHAPES.put(Axis.X, Block.box(0, 2, 2, 16, 14, 14));
BIG_SHAPES.put(Axis.Y, Block.box(2, 0, 2, 14, 16, 14));
BIG_SHAPES.put(Axis.Z, Block.box(2, 2, 0, 14, 14, 16));
MEDIUM_SHAPES.put(Axis.X, Block.box(0, 3, 3, 16, 13, 13));
MEDIUM_SHAPES.put(Axis.Y, Block.box(3, 0, 3, 13, 16, 13));
MEDIUM_SHAPES.put(Axis.Z, Block.box(3, 3, 0, 13, 13, 16));
SMALL_SHAPES.put(Axis.X, Block.box(0, 4, 4, 16, 12, 12));
SMALL_SHAPES.put(Axis.Y, Block.box(4, 0, 4, 12, 16, 12));
SMALL_SHAPES.put(Axis.Z, Block.box(4, 4, 0, 12, 12, 16));
BIG_SHAPES_OPEN.put(Direction.UP, Block.box(2, 0, 2, 14, 14, 14));
BIG_SHAPES_OPEN.put(Direction.DOWN, Block.box(2, 2, 2, 14, 16, 14));
BIG_SHAPES_OPEN.put(Direction.NORTH, Block.box(2, 2, 2, 14, 14, 16));
BIG_SHAPES_OPEN.put(Direction.SOUTH, Block.box(2, 2, 0, 14, 14, 14));
BIG_SHAPES_OPEN.put(Direction.WEST, Block.box(2, 2, 2, 16, 14, 14));
BIG_SHAPES_OPEN.put(Direction.EAST, Block.box(0, 2, 2, 14, 14, 14));
MEDIUM_SHAPES_OPEN.put(Direction.UP, Block.box(3, 0, 3, 13, 13, 13));
MEDIUM_SHAPES_OPEN.put(Direction.DOWN, Block.box(3, 3, 3, 13, 16, 13));
MEDIUM_SHAPES_OPEN.put(Direction.NORTH, Block.box(3, 3, 3, 13, 13, 16));
MEDIUM_SHAPES_OPEN.put(Direction.SOUTH, Block.box(3, 3, 0, 13, 13, 13));
MEDIUM_SHAPES_OPEN.put(Direction.WEST, Block.box(3, 3, 3, 16, 13, 13));
MEDIUM_SHAPES_OPEN.put(Direction.EAST, Block.box(0, 3, 3, 13, 13, 13));
SMALL_SHAPES_OPEN.put(Direction.UP, Block.box(4, 0, 4, 12, 12, 12));
SMALL_SHAPES_OPEN.put(Direction.DOWN, Block.box(4, 4, 4, 12, 16, 12));
SMALL_SHAPES_OPEN.put(Direction.NORTH, Block.box(4, 4, 4, 12, 12, 16));
SMALL_SHAPES_OPEN.put(Direction.SOUTH, Block.box(4, 4, 0, 12, 12, 12));
SMALL_SHAPES_OPEN.put(Direction.WEST, Block.box(4, 4, 4, 16, 12, 12));
SMALL_SHAPES_OPEN.put(Direction.EAST, Block.box(0, 4, 4, 12, 12, 12));
}
@Override
public boolean canPlantOn(Block block) {
return true;
}
@Override
@Environment(EnvType.CLIENT)
public String getPottedState() {
return "bottom=moss,shape=top,facing=up";
}
}

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