Compare commits

...

203 Commits

Author SHA1 Message Date
dfsek 33ef6a1ded create DimensionConfig 2021-05-29 00:39:32 -07:00
dfsek 94d7f783c4 improve fabric/forge getHeight impl 2021-05-29 00:22:41 -07:00
dfsek 5fbcdea9e7 override entity spawning stuff 2021-05-29 00:19:04 -07:00
dfsek fa164e5281 Merge pull request #199 from PolyhedralDev/dev/forge-tweaks
Forge Tweaks
2021-05-22 21:48:12 -07:00
dfsek ec3b0e5d04 implement vanilla mob override 2021-05-22 21:37:16 -07:00
dfsek 4c63c2681f implement ForgeChunkGeneratorWrapper#getBaseColumn 2021-05-22 21:34:28 -07:00
dfsek dd661feaf1 implement dimension type injection/caching 2021-05-22 21:24:25 -07:00
dfsek 1f17bfff1b delegate strongholds to vanilla if vanilla structures are enabled 2021-05-22 21:12:44 -07:00
dfsek 809a0b375d implement identifier loader 2021-05-22 21:11:52 -07:00
dfsek d55b3415ac implement structure locate override on Forge 2021-05-22 21:08:51 -07:00
dfsek edcb818842 basic compatibility stuff on Forge 2021-05-22 18:03:34 -07:00
dfsek 1e429e1bb3 create forge compatibility configs 2021-05-22 17:11:50 -07:00
dfsek 3472859afb remove unused event handlers 2021-05-22 17:10:50 -07:00
dfsek 26025ec276 remove unused class 2021-05-22 00:19:38 -07:00
dfsek 3b3905b513 mixin injection on client in forge 2021-05-21 23:36:20 -07:00
dfsek ce3d09cf2e add background to pack selection GUI 2021-05-19 09:23:20 -07:00
dfsek 5dd00db8d2 Merge pull request #191 from PolyhedralDev/dev/fabric-compat
Options for mod compatibility on Fabric
2021-05-18 20:07:24 -07:00
dfsek 2dc7b50141 implement getColumnSample 2021-05-18 19:50:05 -07:00
dfsek b2ebcc63aa Merge remote-tracking branch 'origin/dev/fabric-compat' into dev/fabric-compat 2021-05-18 18:26:34 -07:00
dfsek f45bc0a0cc Merge remote-tracking branch 'origin/dev/fabric-compat' into dev/fabric-compat 2021-05-18 18:25:46 -07:00
dfsek bbe53cbca3 fix height again 2021-05-18 18:25:31 -07:00
dfsek 7354155c52 bump version 2021-05-18 18:19:25 -07:00
dfsek c1acfee910 Merge pull request #189 from Shadowhackercz/master
Creating new locale for Czech
2021-05-18 17:56:31 -07:00
dfsek 5287323865 only inject carvers if vanilla.caves is enabled 2021-05-18 09:24:20 -07:00
dfsek b09d0e42aa fix biome specific exclusions 2021-05-18 09:06:43 -07:00
dfsek a3f14061dd fix structure location 2021-05-17 23:04:21 -07:00
dfsek 557098de17 use debug logger for feature info 2021-05-17 22:48:03 -07:00
dfsek 2fdb96a850 cleanup and add per-biome exclusions 2021-05-17 22:45:39 -07:00
dfsek d93d064d97 fix getHeight 2021-05-17 20:50:27 -07:00
dfsek ae76fb7dc4 use dimensiontype to get world 2021-05-17 20:16:32 -07:00
dfsek 2626afd066 override entity generation 2021-05-17 19:41:45 -07:00
dfsek c0042cfb6b switch to DimensionType map 2021-05-17 19:39:46 -07:00
dfsek a549d2ef34 move client init code to MinecraftClientMixin 2021-05-17 19:26:25 -07:00
dfsek 4aa20c32b8 fix fabric debuglogger 2021-05-17 17:35:56 -07:00
dfsek ce7033b4ca filter out non-Terra biomes in TerraBiomeSource 2021-05-17 10:07:22 -07:00
dfsek 41a54f4b25 vanilla structures 2021-05-17 10:07:06 -07:00
dfsek f96740f1fa refactor util classes 2021-05-17 08:38:03 -07:00
Shadowhacker 8844cd5069 Creating new locale for Czech
I've created a new localization file for Czech language
2021-05-17 03:53:07 +02:00
dfsek 800d846af4 carver and structure compatibility options 2021-05-16 16:47:17 -07:00
dfsek 95d50a0391 resolve merge conflicts 2021-05-16 00:42:29 -07:00
dfsek 5a83eab1fe Merge remote-tracking branch 'origin/master' into dev/fabric-compat
# Conflicts:
#	platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java
#	platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java
2021-05-16 00:34:42 -07:00
dfsek bac026a1f4 Merge pull request #187 from PolyhedralDev/dev/fabric-no-api
Remove dependency on Fabric API
2021-05-15 21:18:27 -07:00
dfsek 65482c493a remove dependency on Fabric API 2021-05-15 20:30:06 -07:00
dfsek a05f837ca2 Merge pull request #183 from PolyhedralDev/dev/cleanup/gradleproperties
Update mod description and use Gradle properties so we dont forget some platforms if we change things in the future
2021-05-15 14:20:44 -07:00
dfsek 6fbb5d712e add license, wiki, source and issue URLs to properties 2021-05-14 23:30:36 -07:00
dfsek 2c9d195474 remove unused command from bukkit manifest 2021-05-14 23:09:21 -07:00
dfsek b663d34320 add DESCRIPTION to processResources 2021-05-14 23:09:08 -07:00
dfsek 43095d0df1 add version stuff to plugin/mod manifests 2021-05-14 23:05:22 -07:00
dfsek 47e0dc862c add Terra description and mod ID to gradle.properties 2021-05-14 23:02:14 -07:00
dfsek 460b11b9c8 Merge pull request #182 from PolyhedralDev/dev/forge-mixins
Mixinify Forge implementation and fix several issues on Forge
2021-05-14 22:40:05 -07:00
dfsek d974a72cb9 fix commands on forge 2021-05-14 22:36:55 -07:00
dfsek e86f37fdfb Forge build hacks 2021-05-14 22:30:27 -07:00
dfsek 2ed120dc4c forge cleanup 2021-05-14 19:15:13 -07:00
dfsek 973ae785f4 Forge server fixes 2021-05-14 18:40:03 -07:00
dfsek 4835813e2e fix chunk generator reset on forge 2021-05-14 18:25:28 -07:00
dfsek 632409050b Merge remote-tracking branch 'origin/master' into dev/forge-mixins
# Conflicts:
#	gradle.properties
2021-05-14 17:47:50 -07:00
dfsek 9d991dbb97 Merge pull request #181 from PolyhedralDev/dev/fabric-worldedit
Implement WorldEdit integration for structure exporting on Fabric
2021-05-14 09:38:13 -07:00
dfsek cddf7c20e4 bump version 2021-05-13 22:10:35 -07:00
dfsek 5fd2fc59f4 worldedit integration on Fabric 2021-05-13 21:28:49 -07:00
dfsek 97d7ccacbf add worldedit dependency 2021-05-13 18:15:07 -07:00
dfsek 242e56b1d8 conditional biome injection 2021-05-12 09:27:20 -07:00
dfsek 4c7aa11353 clean up TerraFabricPlugin 2021-05-12 08:39:43 -07:00
dfsek cac84ffe03 fix typo 2021-05-12 00:55:14 -07:00
dfsek cf66e1e226 registry injection 2021-05-12 00:53:25 -07:00
dfsek fa647e1e2c make loadConfig less jank 2021-05-12 00:48:38 -07:00
dfsek 4203121d40 basic feature loading implementation 2021-05-12 00:33:00 -07:00
dfsek 82fe6d5aa4 add api to load custom values from pack manifest. 2021-05-12 00:09:21 -07:00
dfsek 32db83f091 remove NotNullValidator 2021-05-11 23:56:08 -07:00
dfsek 0ab949174a Update README.md 2021-05-11 16:06:37 -07:00
dfsek 2bfaa95a81 add forge disclaimer to README 2021-05-11 16:03:32 -07:00
dfsek 96de1554f1 disable configureondemand 2021-05-11 15:56:53 -07:00
dfsek f83dcd802c Merge remote-tracking branch 'origin/master' 2021-05-11 09:03:14 -07:00
dfsek 808aa50f5f update config.yml 2021-05-11 09:02:59 -07:00
dfsek e00271e493 Merge pull request #162 from PolyhedralDev/dev/fabric-late-init
initialize later
2021-05-10 23:14:57 -07:00
dfsek 76bf245e16 type check ChunkGenerator in PopulatorFeature 2021-05-10 22:52:34 -07:00
dfsek 37e441206a fix getHandle overwrite conflicts and annotate getHandle methods as @Intrinsic. 2021-05-10 01:11:22 -07:00
dfsek 5376f7e22e fix server init 2021-05-10 01:03:13 -07:00
dfsek 1186fc6624 bump version 2021-05-05 15:24:55 -07:00
dfsek a1b3680643 initialize later 2021-05-05 15:22:02 -07:00
dfsek 501399919f implement vanilla carver/structure options on Fabric & Forge (we will still yell at you if you use them) 2021-05-04 22:40:37 -07:00
dfsek 725d57d967 rename mixins for mojmap 2021-05-04 22:35:30 -07:00
dfsek a821501392 refactor forge stuff 2021-05-04 22:09:50 -07:00
dfsek d3458148bd default disable forge registry dump 2021-05-04 21:38:44 -07:00
dfsek df4da810ec fix forge mixin issues 2021-05-04 21:37:36 -07:00
dfsek 8f47c84c8e fix forge builds 2021-05-04 21:29:07 -07:00
dfsek f61a544a57 account for null ignored in StructureLocateEvent 2021-05-04 20:32:22 -07:00
dfsek 3217d66c69 forge mixins (probably dont work yet) 2021-05-04 19:22:10 -07:00
dfsek fd48f5f110 Merge pull request #158 from PolyhedralDev/dev/fabric-locate
Override structure location on Fabric
2021-05-04 16:45:25 -07:00
dfsek 77a4c95c4a override structure location on Fabric 2021-05-04 16:44:43 -07:00
dfsek dbc60b1d82 Merge pull request #153 from PolyhedralDev/dev/fabric-mixins
Implement Terra interfaces directly in Minecraft classes using Mixin.
2021-05-04 16:16:31 -07:00
dfsek ed942bb997 update README.md 2021-05-04 16:13:05 -07:00
dfsek 6866084872 SignBlockEntityMixin cleanup 2021-05-04 16:10:37 -07:00
dfsek 4c77419dcd fix sign getText on server 2021-05-04 15:04:53 -07:00
dfsek ecba6e0843 Merge remote-tracking branch 'origin/dev/fabric-mixins' into dev/fabric-mixins 2021-05-04 09:21:21 -07:00
dfsek 86dcb476f1 update README with modern build instructions and Forge download links 2021-05-04 09:21:12 -07:00
dfsek 13e0857882 merge FabricEnumAdapter into FabricAdapter 2021-05-03 22:49:21 -07:00
dfsek bf93a9239c bump version 2021-05-03 22:28:01 -07:00
dfsek 2d18aab709 fix funky yaml formatting 2021-05-03 22:13:42 -07:00
dfsek a1359da374 terrascript trig functions 2021-05-03 22:13:32 -07:00
dfsek f7bda835f9 fix itemmeta application 2021-05-03 20:52:03 -07:00
dfsek 7595896831 fix refmap issues 2021-05-03 20:40:56 -07:00
dfsek 6614d19845 suppress warnings 2021-05-03 20:14:06 -07:00
dfsek 6209b86560 mixin maintenance 2021-05-03 20:12:48 -07:00
dfsek a30859a3d4 dont try to remap Terra interfaces 2021-05-03 20:08:13 -07:00
dfsek ddbb46289b add package-info.java to implementation mixin package. 2021-05-03 20:03:25 -07:00
dfsek 64c35a9609 refactor Fabric project 2021-05-03 20:02:08 -07:00
dfsek f21069ab2e fix cache misses 2021-05-03 19:43:52 -07:00
dfsek 457729b832 replace most access wideners with mixins 2021-05-03 19:33:57 -07:00
dfsek 756f04a0b3 implement LockableContainerBlockEntityMixin 2021-05-03 18:38:40 -07:00
dfsek 5ee32cc3ba add ConfiguredFeatureMixin 2021-05-03 17:35:43 -07:00
dfsek 955558bc21 implement BlockMixin 2021-05-03 11:37:54 -07:00
dfsek c43a872c23 finish blockstate mixins 2021-05-03 11:27:36 -07:00
dfsek de41b92d5d add SignBlockEntityMixin 2021-05-03 10:27:40 -07:00
dfsek 03091230ed refactor mixins 2021-05-03 10:09:21 -07:00
dfsek a8c88915ea override chunkregion hashcode 2021-05-02 23:39:40 -07:00
dfsek 4cd4720101 fix loot NPE 2021-05-02 23:08:54 -07:00
dfsek 3b9280b19c start work on state mixins 2021-05-02 23:00:21 -07:00
dfsek 2d27e07441 implement BiomeMixin 2021-05-02 22:49:57 -07:00
dfsek 20a5762d2e refactor mixins 2021-05-02 22:48:21 -07:00
dfsek 146f71f704 finish World mixins 2021-05-02 22:45:34 -07:00
dfsek 1d4b0bc100 cleanup 2021-05-02 22:26:23 -07:00
dfsek 138ee0a448 refactor fabric handles 2021-05-02 22:22:32 -07:00
dfsek 2c8cae9d45 create ChunkGeneratorMixin 2021-05-02 22:21:50 -07:00
dfsek 061d2b6493 implement EntityTypeMixin 2021-05-02 21:48:06 -07:00
dfsek e71df936ab EnchantmentMixin 2021-05-02 21:35:39 -07:00
dfsek f4253acb78 item mixins 2021-05-02 21:27:25 -07:00
dfsek c12518fa49 delete FabricItem.java 2021-05-02 21:11:09 -07:00
dfsek 4704b2ebf7 implement ItemMixin 2021-05-02 21:10:48 -07:00
dfsek 89fdfdfb34 suppress warnings 2021-05-02 20:42:54 -07:00
dfsek 35d85f2aa3 PlayerEntityMixin and EntityMixin 2021-05-02 20:38:25 -07:00
dfsek c0368f1c6d implement ServerCommandSourceMixin 2021-05-02 20:17:59 -07:00
dfsek abc069046c add ProtoChunkMixin and WorldChunkMixin 2021-05-02 20:13:24 -07:00
dfsek 46d0b08068 implement ChunkRegionMixin 2021-05-02 19:49:59 -07:00
dfsek a7e3a0286e add -forge and -fabric to Modrinth version numbers. 2021-05-02 17:46:55 -07:00
dfsek 6da8924868 Merge pull request #145 from PolyhedralDev/dev/forge
Forge implementation
2021-05-02 17:38:56 -07:00
dfsek d9dd6afe4b Merge pull request #143 from solonovamax/improvement/better-gradle-performance
Improve gradle performance significantly
2021-05-02 17:37:36 -07:00
dfsek dfec26f789 fix forge modrinth task 2021-05-02 17:21:05 -07:00
dfsek d13be5e159 add Forge modrinth publish task 2021-05-02 17:16:03 -07:00
dfsek 51c5f70d64 forge jarfile nightmare "solution" 2021-05-02 17:08:59 -07:00
dfsek 05b1902c06 Merge pull request #151 from DJtheRedstoner/patch-mixin-ap
Fix mixin annotation processor issues
2021-05-02 15:47:32 -07:00
dfsek f4ae2cac68 add MixinGeneratorOptions 2021-05-02 15:46:03 -07:00
dfsek ea3995afce fix refmap name 2021-05-02 15:44:30 -07:00
dfsek c41d60c38f remove manual refmap 2021-05-02 15:43:12 -07:00
DJtheRedstoner 19edcbddd5 Fix mixin annotation processor issues
These issues were caused by CompilationConfig.configureCompilation()
overwriting JavaCompile's options.compilerArgs list which removed any
previously added arguments, including those added by fabric-loom and
mixingradle.
2021-05-02 18:17:18 -04:00
dfsek 4f65555e82 remove mixins until annotation processor gets fixed. 2021-05-02 14:37:34 -07:00
dfsek 9956cab507 dont use vanilla registries 2021-05-01 22:21:27 -07:00
dfsek fddf0c51b7 cleanup PopulationManager 2021-05-01 20:27:59 -07:00
dfsek e2a52afb67 remove methods only used for cursed Bukkit stuff from common World interface. 2021-05-01 19:07:19 -07:00
dfsek c8c3a33912 fix loot table issue 2021-05-01 18:40:31 -07:00
dfsek b178f69e47 Merge remote-tracking branch 'origin/dev/forge' into dev/forge 2021-05-01 18:20:23 -07:00
dfsek 049a56fcb0 Mixin on Forge 2021-05-01 18:20:11 -07:00
solonovamax 2d41dd8f08 Don't use all cores processors for tests
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2021-05-01 16:53:45 -04:00
solonovamax aa9e33af1d Remove old and deprecated compile configuration + some minor refactoring
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2021-05-01 16:53:45 -04:00
dfsek 02870805c7 hoist calculations in chunk generator 2021-04-30 09:35:15 -07:00
dfsek e493825ab7 bump version 2021-04-30 09:25:56 -07:00
dfsek 762b248641 update to latest Tectonic 2021-04-29 23:42:56 -07:00
dfsek f81ccee020 cleanup 2021-04-29 23:31:03 -07:00
dfsek 3561e5f30f commands on Forge 2021-04-29 23:19:49 -07:00
dfsek c67817b9d2 fix structure issues 2021-04-29 22:00:40 -07:00
dfsek 756619edb6 Forge actually loads to worlds now 2021-04-29 21:48:32 -07:00
dfsek ee1c889d54 world screen type 2021-04-29 21:11:26 -07:00
dfsek 9f3dcf07b6 Pack loading on Forge 2021-04-29 20:30:48 -07:00
dfsek 93a2f103f7 add pack.mcmeta 2021-04-29 16:41:14 -07:00
dfsek 3ea12ceeab start implementing terraplugin 2021-04-29 12:30:17 -07:00
dfsek ce8ec51ae4 forge actually loads now 2021-04-29 12:24:29 -07:00
dfsek 54bb4ef109 sort of working Forge project 2021-04-29 01:55:24 -07:00
dfsek 59b655ce5d working forge buildscript 2021-04-29 01:27:28 -07:00
solonovamax 4c1e1bb7d5 Improve gradle performance significantly
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
2021-04-28 20:43:53 -04:00
dfsek eee54f507e Merge pull request #138 from PolyhedralDev/dev/profilerimpl
Fancy stack-based profiler
2021-04-26 21:32:42 -07:00
dfsek 6f1b1611ab fix dumb gradle issue 2021-04-26 21:26:44 -07:00
dfsek 205499220d profile more things 2021-04-26 20:59:21 -07:00
dfsek a0c5631eba bump version 2021-04-26 20:46:36 -07:00
dfsek 9323abc788 document Profiler 2021-04-26 19:04:20 -07:00
dfsek 632f898dc8 implement Profiler#reset 2021-04-26 19:01:53 -07:00
dfsek 8737b0d984 resolve merge conflict 2021-04-25 17:12:42 -07:00
dfsek bcb68853d5 @SuppressWarnings go brrr 2021-04-25 17:11:50 -07:00
dfsek 8823d6d65e fix stack size assumption at profiler start 2021-04-25 17:11:50 -07:00
dfsek 5d3a2b6e84 profile more things 2021-04-25 17:11:50 -07:00
dfsek 23fb7753ab fancy unicode symbols B) 2021-04-25 17:11:50 -07:00
dfsek f8e7e343cb fix % parent issue 2021-04-25 17:11:50 -07:00
dfsek e5f4c5dc8d implement terrascript profiling 2021-04-25 17:11:49 -07:00
dfsek 8a10867e5f implement new profiler 2021-04-25 17:11:04 -07:00
dfsek da366a75e8 add autocloseable option 2021-04-25 17:09:08 -07:00
dfsek eb4bf74cc6 implement TerraPlugin#getProfier 2021-04-25 17:09:08 -07:00
dfsek 168c0ced13 improve performance in deep operations 2021-04-25 17:09:07 -07:00
dfsek 5d4bdb431b improve data output 2021-04-25 17:09:07 -07:00
dfsek 40188c671f basic profiler implementation 2021-04-25 17:09:07 -07:00
dfsek f396e0e5eb Merge pull request #133 from PolyhedralDev/ver/5.1.4
Fix minor Fabric issues
2021-04-16 09:01:29 -07:00
dfsek 942a8c9c8b Merge pull request #131 from xieve/fix-disable-config
Fixed populator disable config (#130)
2021-04-15 10:29:20 -07:00
dfsek 414dcdae3e use vanilla delegate spawn rules 2021-04-15 10:20:14 -07:00
dfsek 1195a6676f implement getHeight on Fabric 2021-04-15 10:00:22 -07:00
dfsek 5501f53056 implement TerraFabricPlugin#getWorld(long) 2021-04-15 09:59:13 -07:00
xieve 41d6e1c648 Fixed populator disable config (#130) 2021-04-15 18:18:27 +02:00
dfsek 5ac7257517 Merge pull request #119 from PolyhedralDev/ver/5.1.3
Fix Fabric Physics, add "dead" entry checking to registries.
2021-04-11 18:56:25 -07:00
dfsek 9f4f9702a6 bump version 2021-04-11 17:54:07 -07:00
dfsek 01d169256e properly relocate dependencies 2021-04-11 17:49:39 -07:00
dfsek 7a703ad091 add publication config to Fabric 2021-04-11 14:15:13 -07:00
dfsek ce9273c7e8 proper fluid updating on Fabric 2021-04-11 00:45:53 -07:00
dfsek 653a414ac1 should(tm) fix fabric physics 2021-04-10 23:49:02 -07:00
dfsek 2080db21ca warn about dead registry entries when debug mode is enabled 2021-04-10 19:22:41 -07:00
dfsek 8a933609ee Merge pull request #107 from PolyhedralDev/ver/5.1.2
5.1.2 LootPopulateEvent patch
2021-04-01 15:14:14 -07:00
dfsek f8e8ce8bc2 Bump version 2021-03-31 20:50:17 -07:00
dfsek 0013d4e682 Merge pull request #106 from PolyhedralDev/ver/5.1.2
Add LootPopulateEvent and EntitySpawnEvent
2021-03-31 20:49:44 -07:00
237 changed files with 6506 additions and 2675 deletions
+1 -1
View File
@@ -342,6 +342,6 @@ ij_json_wrap_long_lines = false
indent_size = 2
ij_yaml_keep_indents_on_empty_lines = true
ij_yaml_keep_line_breaks = true
ij_yaml_space_before_colon = true
ij_yaml_space_before_colon = false
ij_yaml_spaces_within_braces = true
ij_yaml_spaces_within_brackets = true
+26 -10
View File
@@ -7,24 +7,40 @@ to your specifications, with no knowledge of Java required.
* Paper+ servers (Paper, Tuinity, Purpur, etc): [SpigotMC](https://www.spigotmc.org/resources/85151/)
* Fabric: [Modrinth](https://modrinth.com/mod/terra) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/terra-world-generator)
* Forge **(ALPHA - NOT PRODUCTION-READY)**: [Modrinth](https://modrinth.com/mod/terra) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/terra-world-generator)
## Building and running Terra
## Building and Running Terra
To build, simply run `./gradlew build` (`gradlew.bat build` on Windows). This will produce a jar in `build/libs`
called `Terra-[CURRENT VERSION].jar`. You can put this right into your plugins dir, along with the correct Gaea version.
To build, simply run `./gradlew build` (`gradlew.bat build` on Windows). This will build all platforms, and
produce JARs in `platforms/<platform>/build/libs`
If you would like to test it with a default server config, just run `./gradlew setupServer` or
`./gradlew.bat setupServer` to set up the server, then `./gradlew testWithPaper` or `gradlew.bat testWithPaper` to run the server. If you
want a clean installation of the server, re-run the `setupServer` task. This will download a default server config
from [here](https://github.com/PolyhedralDev/WorldGenTestServer)
and install the server in the `target/server` directory, along with all the needed plugins.
### Production JARs:
* Bukkit: `Terra-<version>-shaded.jar`
* Fabric: `Terra-<version>-shaded-mapped.jar`
* Forge: `Terra-<version>-shaded.jar`
**Note: You will need to adjust the `NAME` variable `bukkit.yml` of the test server if you are not using the default Terra config.**
### Building a Specific Platform
To build a specific platform, run `gradlew :platforms:<platform>:build`.
JARs are produced in `platforms/<platform>/build/libs`.
### Running Minecraft in the IDE
To run Minecraft with Terra in the IDE (for testing) use the following tasks:
* Bukkit
* `installPaper` - Install a [Paper](https://github.com/PaperMC/Paper) test server. (Only needs to be run once).
* `installPurpur` - Install a [Purpur](https://github.com/pl3xgaming/Purpur) test server. (Only needs to be run once).
* `runPaper` - Run the Paper test server with Terra (`installPaper` must have been run previously).
* `runPurpur` - Run the Purpur test server with Terra (`installPurpur` must have been run previously).
* Fabric
* `runClient` - Run a Minecraft Fabric client with Terra installed.
* `runServer` - Run a Minecraft Fabric server with Terra installed.
* Forge
* `runClient` - Run a Minecraft Forge client with Terra installed.
* `runServer` - Run a Minecraft Forge server with Terra installed.
## Contributing
Contributions are welcome! If you want to see a feature in Terra, please, open an issue, or implement it yourself and
submit a PR!
Join the discord [here](https://discord.gg/PXUEbbF) if you would like to talk more about the project!
## Beta
Terra is still in beta! While it is stable, it is not feature-complete. There is a lot to be added!
Terra is still in beta! While it is stable, it is not feature-complete. There is a lot to be added!
+19 -2
View File
@@ -1,10 +1,27 @@
import com.dfsek.terra.getGitHash
val versionObj = Version("5", "1", "1", true)
val versionObj = Version("5", "3", "3", true)
allprojects {
version = versionObj
group = "com.dfsek.terra"
tasks.withType<JavaCompile>().configureEach {
options.isFork = true
options.isIncremental = true
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
maxHeapSize = "2G"
ignoreFailures = false
failFast = true
maxParallelForks = (Runtime.getRuntime().availableProcessors() - 1).takeIf { it > 0 } ?: 1
reports.html.isEnabled = false
reports.junitXml.isEnabled = false
}
}
/**
* Version class that does version stuff.
@@ -18,4 +35,4 @@ class Version(val major: String, val minor: String, val revision: String, val pr
else //Only use git hash if it's a prerelease.
"$major.$minor.$revision-BETA+${getGitHash()}"
}
}
}
@@ -7,26 +7,11 @@ import org.gradle.kotlin.dsl.withType
import java.io.ByteArrayOutputStream
fun Project.configureCommon() {
apply(plugin = "java-library")
apply(plugin = "maven-publish")
apply(plugin = "idea")
configureDependencies()
configureCompilation()
configureDistribution()
version = rootProject.version
tasks.withType<Test>().configureEach {
useJUnitPlatform()
maxHeapSize = "2G"
ignoreFailures = false
failFast = true
maxParallelForks = 12
}
}
fun Project.getGitHash(): String {
@@ -3,14 +3,16 @@ package com.dfsek.terra
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.filter
import org.gradle.kotlin.dsl.withType
import org.gradle.kotlin.dsl.*
import org.gradle.language.jvm.tasks.ProcessResources
fun Project.configureCompilation() {
apply(plugin = "maven-publish")
apply(plugin = "idea")
configure<JavaPluginConvention> {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
@@ -19,7 +21,7 @@ fun Project.configureCompilation() {
tasks.withType<JavaCompile> {
options.encoding = "UTF-8"
doFirst {
options.compilerArgs = mutableListOf("-Xlint:all")
options.compilerArgs.add("-Xlint:all")
}
}
@@ -27,7 +29,12 @@ fun Project.configureCompilation() {
include("**/*.*")
filter<org.apache.tools.ant.filters.ReplaceTokens>(
"tokens" to mapOf(
"VERSION" to project.version.toString()
"VERSION" to project.version.toString(),
"DESCRIPTION" to project.properties["terra.description"],
"WIKI" to project.properties["terra.wiki"],
"SOURCE" to project.properties["terra.source"],
"ISSUES" to project.properties["terra.issues"],
"LICENSE" to project.properties["terra.license"]
)
)
}
@@ -35,4 +42,19 @@ fun Project.configureCompilation() {
tasks.withType<Javadoc> {
options.encoding = "UTF-8"
}
tasks.withType<Jar> {
archiveBaseName.set("Terra-${archiveBaseName.get()}")
from("../LICENSE", "../../LICENSE")
}
tasks.register<Jar>("sourcesJar") {
archiveClassifier.set("sources")
}
tasks.register<Jar>("javadocJar") {
dependsOn("javadoc")
archiveClassifier.set("javadoc")
from(tasks.getByName<Javadoc>("javadoc").destinationDir)
}
}
@@ -1,13 +1,27 @@
package com.dfsek.terra
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.invoke
import org.gradle.kotlin.dsl.repositories
fun Project.configureDependencies() {
apply(plugin = "java")
apply(plugin = "java-library")
configurations {
val shaded = create("shaded")
val shadedApi = create("shadedApi")
shaded.extendsFrom(shadedApi)
getByName("api").extendsFrom(shadedApi)
val shadedImplementation = create("shadedImplementation")
shaded.extendsFrom(shadedImplementation)
getByName("implementation").extendsFrom(shadedImplementation)
}
repositories {
maven { url = uri("http://maven.enginehub.org/repo/") }
maven { url = uri("https://maven.enginehub.org/repo/") }
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
maven { url = uri("https://maven.fabricmc.net/") }
@@ -18,9 +32,7 @@ fun Project.configureDependencies() {
dependencies {
"testImplementation"("org.junit.jupiter:junit-jupiter-api:5.7.0")
"testImplementation"("org.yaml:snakeyaml:1.27")
"testImplementation"("com.googlecode.json-simple:json-simple:1.1.1")
"testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.7.0")
"compileOnly"("org.jetbrains:annotations:20.1.0")
"testImplementation"("org.junit.jupiter:junit-jupiter-engine:5.7.0")
"api"("org.jetbrains:annotations:20.1.0")
}
}
@@ -14,17 +14,6 @@ fun Project.configureDistribution() {
apply(plugin = "java-library")
apply(plugin = "com.github.johnrengelman.shadow")
configurations {
val shaded = create("shaded")
getByName("compile").extendsFrom(shaded)
val shadedApi = create("shadedApi")
shaded.extendsFrom(shadedApi)
getByName("api").extendsFrom(shadedApi)
val shadedImplementation = create("shadedImplementation")
shaded.extendsFrom(shadedImplementation)
getByName("implementation").extendsFrom(shadedImplementation)
}
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
group = "terra"
doFirst {
@@ -38,21 +27,6 @@ fun Project.configureDistribution() {
}
tasks["processResources"].dependsOn(downloadDefaultPacks)
tasks.withType<Jar> {
archiveBaseName.set("Terra-${archiveBaseName.get()}")
from("../LICENSE", "../../LICENSE")
}
tasks.register<Jar>("sourcesJar") {
archiveClassifier.set("sources")
}
tasks.register<Jar>("javadocJar") {
dependsOn("javadoc")
archiveClassifier.set("javadoc")
from(tasks.getByName<Javadoc>("javadoc").destinationDir)
}
tasks.named<ShadowJar>("shadowJar") {
// Tell shadow to download the packs
dependsOn(downloadDefaultPacks)
@@ -62,8 +36,14 @@ fun Project.configureDistribution() {
archiveClassifier.set("shaded")
setVersion(project.version)
relocate("org.apache.commons", "com.dfsek.terra.lib.commons")
relocate("parsii", "com.dfsek.terra.lib.parsii")
relocate("net.jafama", "com.dfsek.terra.lib.jafama")
relocate("org.objectweb.asm", "com.dfsek.terra.lib.asm")
relocate("com.google.errorprone", "com.dfsek.terra.lib.google.errorprone")
relocate("com.google.j2objc", "com.dfsek.terra.lib.google.j2objc")
relocate("org.checkerframework", "com.dfsek.terra.lib.checkerframework")
relocate("org.javax.annotation", "com.dfsek.terra.lib.javax.annotation")
relocate("org.json", "com.dfsek.terra.lib.json")
relocate("org.yaml", "com.dfsek.terra.lib.yaml")
minimize()
}
convention.getPlugin<BasePluginConvention>().archivesBaseName = project.name
+8 -4
View File
@@ -1,11 +1,14 @@
import com.dfsek.terra.configureCommon
import com.dfsek.terra.configureCompilation
import com.dfsek.terra.configureDependencies
plugins {
`java-library`
`maven-publish`
idea
}
configureCommon()
configureCompilation()
configureDependencies()
group = "com.dfsek.terra.common"
@@ -14,13 +17,14 @@ dependencies {
"shadedApi"("commons-io:commons-io:2.4")
"shadedApi"("com.dfsek:Paralithic:0.3.2")
"shadedApi"("com.dfsek:Tectonic:1.2.3")
"shadedApi"("com.dfsek:Tectonic:1.3.1")
"shadedApi"("net.jafama:jafama:2.3.2")
"shadedApi"("org.yaml:snakeyaml:1.27")
"shadedApi"("org.ow2.asm:asm:9.0")
"shadedApi"("commons-io:commons-io:2.6")
"compileOnly"("com.googlecode.json-simple:json-simple:1.1")
"shadedApi"("com.googlecode.json-simple:json-simple:1.1.1")
"shadedApi"("org.yaml:snakeyaml:1.27")
"compileOnly"("com.google.guava:guava:30.0-jre")
@@ -7,14 +7,19 @@ import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.LockedRegistry;
import com.dfsek.terra.api.util.JarUtil;
import com.dfsek.terra.api.util.logging.DebugLogger;
import com.dfsek.terra.api.util.logging.Logger;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.profiler.Profiler;
import com.dfsek.terra.world.TerraWorld;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.jar.JarFile;
/**
* Represents a Terra mod/plugin instance.
@@ -64,4 +69,10 @@ public interface TerraPlugin extends LoaderRegistrar {
default void runPossiblyUnsafeTask(Runnable task) {
task.run();
}
Profiler getProfiler();
default JarFile getModJar() throws URISyntaxException, IOException {
return JarUtil.getJarFile();
}
}
@@ -65,7 +65,7 @@ public class TerraCommandManager implements CommandManager {
return;
}
if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player) || !TerraWorld.isTerraWorld(((Player) sender).getWorld()))) {
if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player) || !(((Player) sender).getWorld()).isTerraWorld())) {
sender.sendMessage("Command must be executed in a Terra world.");
return;
}
@@ -1,5 +1,7 @@
package com.dfsek.terra.api.event.events.config;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.terra.api.event.events.PackEvent;
import com.dfsek.terra.config.pack.ConfigPack;
@@ -8,13 +10,28 @@ import com.dfsek.terra.config.pack.ConfigPack;
*/
public abstract class ConfigPackLoadEvent implements PackEvent {
private final ConfigPack pack;
private final ExceptionalConsumer<ConfigTemplate> configLoader;
public ConfigPackLoadEvent(ConfigPack pack) {
public ConfigPackLoadEvent(ConfigPack pack, ExceptionalConsumer<ConfigTemplate> configLoader) {
this.pack = pack;
this.configLoader = configLoader;
}
@Override
public ConfigPack getPack() {
return pack;
}
/**
* Load a custom {@link ConfigTemplate} using the pack manifest.
*
* @param template Template to register.
*/
public void loadTemplate(ConfigTemplate template) throws ConfigException {
configLoader.accept(template);
}
public interface ExceptionalConsumer<T extends ConfigTemplate> {
void accept(T value) throws ConfigException;
}
}
@@ -1,12 +1,13 @@
package com.dfsek.terra.api.event.events.config;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.config.pack.ConfigPack;
/**
* Called when a config pack has finished loading.
*/
public class ConfigPackPostLoadEvent extends ConfigPackLoadEvent {
public ConfigPackPostLoadEvent(ConfigPack pack) {
super(pack);
public ConfigPackPostLoadEvent(ConfigPack pack, ExceptionalConsumer<ConfigTemplate> loader) {
super(pack, loader);
}
}
@@ -1,12 +1,14 @@
package com.dfsek.terra.api.event.events.config;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.terra.config.pack.ConfigPack;
/**
* Called before a config pack's registries are filled. At this point, the pack manifest has been loaded, and all registries are empty.
*/
public class ConfigPackPreLoadEvent extends ConfigPackLoadEvent {
public ConfigPackPreLoadEvent(ConfigPack pack) {
super(pack);
public ConfigPackPreLoadEvent(ConfigPack pack, ExceptionalConsumer<ConfigTemplate> configLoader) {
super(pack, configLoader);
}
}
@@ -1,6 +1,7 @@
package com.dfsek.terra.api.platform.inventory;
import com.dfsek.terra.api.platform.Handle;
import com.dfsek.terra.api.platform.inventory.item.Damageable;
import com.dfsek.terra.api.platform.inventory.item.ItemMeta;
public interface ItemStack extends Handle {
@@ -13,4 +14,8 @@ public interface ItemStack extends Handle {
ItemMeta getItemMeta();
void setItemMeta(ItemMeta meta);
default boolean isDamageable() {
return getItemMeta() instanceof Damageable;
}
}
@@ -6,6 +6,8 @@ import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import java.io.File;
import java.util.UUID;
@@ -17,20 +19,12 @@ public interface World extends Handle {
ChunkGenerator getGenerator();
String getName();
UUID getUID();
boolean isChunkGenerated(int x, int z);
Chunk getChunkAt(int x, int z);
default Chunk getChunkAt(Location location) {
return getChunkAt(location.getBlockX() >> 4, location.getBlockZ() >> 4);
}
File getWorldFolder();
Block getBlockAt(int x, int y, int z);
default Block getBlockAt(Location l) {
@@ -40,4 +34,12 @@ public interface World extends Handle {
Entity spawnEntity(Location location, EntityType entityType);
int getMinHeight();
default boolean isTerraWorld() {
return getGenerator().getHandle() instanceof GeneratorWrapper;
}
default TerraChunkGenerator getTerraGenerator() {
return ((GeneratorWrapper) getGenerator().getHandle()).getHandle();
}
}
@@ -34,8 +34,8 @@ public class DamageFunction implements LootFunction {
@Override
public ItemStack apply(ItemStack original, Random r) {
if(original == null) return null;
if(!original.isDamageable()) return original;
ItemMeta meta = original.getItemMeta();
if(!(meta instanceof Damageable)) return original;
double itemDurability = (r.nextDouble() * (max - min)) + min;
Damageable damage = (Damageable) meta;
damage.setDamage((int) (original.getType().getMaxDurability() - (itemDurability / 100) * original.getType().getMaxDurability()));
@@ -29,6 +29,7 @@ import com.dfsek.terra.api.structures.structure.Rotation;
import com.dfsek.terra.api.structures.structure.buffer.Buffer;
import com.dfsek.terra.api.structures.structure.buffer.DirectBuffer;
import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer;
import com.dfsek.terra.profiler.ProfileFrame;
import com.dfsek.terra.registry.config.FunctionRegistry;
import com.dfsek.terra.registry.config.LootRegistry;
import com.dfsek.terra.registry.config.ScriptRegistry;
@@ -39,6 +40,7 @@ import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Random;
import java.util.concurrent.ExecutionException;
@@ -52,7 +54,7 @@ public class StructureScript {
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, FunctionRegistry functionRegistry) throws ParseException {
Parser parser;
try {
parser = new Parser(IOUtils.toString(inputStream));
parser = new Parser(IOUtils.toString(inputStream, Charset.defaultCharset()));
} catch(IOException e) {
throw new RuntimeException(e);
}
@@ -87,6 +89,12 @@ public class StructureScript {
.registerFunction("ceil", new UnaryNumberFunctionBuilder(number -> FastMath.ceil(number.doubleValue())))
.registerFunction("log", new UnaryNumberFunctionBuilder(number -> FastMath.log(number.doubleValue())))
.registerFunction("round", new UnaryNumberFunctionBuilder(number -> FastMath.round(number.doubleValue())))
.registerFunction("sin", new UnaryNumberFunctionBuilder(number -> FastMath.sin(number.doubleValue())))
.registerFunction("cos", new UnaryNumberFunctionBuilder(number -> FastMath.cos(number.doubleValue())))
.registerFunction("tan", new UnaryNumberFunctionBuilder(number -> FastMath.tan(number.doubleValue())))
.registerFunction("asin", new UnaryNumberFunctionBuilder(number -> FastMath.asin(number.doubleValue())))
.registerFunction("acos", new UnaryNumberFunctionBuilder(number -> FastMath.acos(number.doubleValue())))
.registerFunction("atan", new UnaryNumberFunctionBuilder(number -> FastMath.atan(number.doubleValue())))
.registerFunction("max", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue())))
.registerFunction("min", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue())));
@@ -104,22 +112,31 @@ public class StructureScript {
* @param rotation Rotation of structure
* @return Whether generation was successful
*/
@SuppressWarnings("try")
public boolean execute(Location location, Random random, Rotation rotation) {
StructureBuffer buffer = new StructureBuffer(location);
boolean level = applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0));
buffer.paste();
return level;
try(ProfileFrame ignore = main.getProfiler().profile("terrascript:" + id)) {
StructureBuffer buffer = new StructureBuffer(location);
boolean level = applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0));
buffer.paste();
return level;
}
}
@SuppressWarnings("try")
public boolean execute(Location location, Chunk chunk, Random random, Rotation rotation) {
StructureBuffer buffer = computeBuffer(location, random, rotation);
buffer.paste(chunk);
return buffer.succeeded();
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_chunk:" + id)) {
StructureBuffer buffer = computeBuffer(location, random, rotation);
buffer.paste(chunk);
return buffer.succeeded();
}
}
@SuppressWarnings("try")
public boolean test(Location location, Random random, Rotation rotation) {
StructureBuffer buffer = computeBuffer(location, random, rotation);
return buffer.succeeded();
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_test:" + id)) {
StructureBuffer buffer = computeBuffer(location, random, rotation);
return buffer.succeeded();
}
}
private StructureBuffer computeBuffer(Location location, Random random, Rotation rotation) {
@@ -134,13 +151,19 @@ public class StructureScript {
}
}
@SuppressWarnings("try")
public boolean executeInBuffer(Buffer buffer, Random random, Rotation rotation, int recursions) {
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, recursions));
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_recursive:" + id)) {
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, recursions));
}
}
@SuppressWarnings("try")
public boolean executeDirect(Location location, Random random, Rotation rotation) {
DirectBuffer buffer = new DirectBuffer(location);
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0));
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_direct:" + id)) {
DirectBuffer buffer = new DirectBuffer(location);
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0));
}
}
public String getId() {
@@ -19,6 +19,6 @@ public class BufferedEntity implements BufferedItem {
@Override
public void paste(Location origin) {
Entity entity = origin.clone().add(0.5, 0, 0.5).getWorld().spawnEntity(origin, type);
main.getEventManager().callEvent(new EntitySpawnEvent(main.getWorld(entity.getWorld()).getGenerator().getConfigPack(), entity, entity.getLocation()));
main.getEventManager().callEvent(new EntitySpawnEvent(entity.getWorld().getTerraGenerator().getConfigPack(), entity, entity.getLocation()));
}
}
@@ -32,7 +32,7 @@ public class BufferedLootApplication implements BufferedItem {
}
Container container = (Container) data;
LootPopulateEvent event = new LootPopulateEvent(block, container, table, main.getWorld(block.getLocation().getWorld()).getGenerator().getConfigPack(), structure);
LootPopulateEvent event = new LootPopulateEvent(block, container, table, block.getLocation().getWorld().getTerraGenerator().getConfigPack(), structure);
main.getEventManager().callEvent(event);
if(event.isCancelled()) return;
@@ -40,7 +40,7 @@ public class BufferedLootApplication implements BufferedItem {
data.update(false);
} catch(Exception e) {
main.logger().warning("Could not apply loot at " + origin + ": " + e.getMessage());
main.getDebugLogger().stack(e);
e.printStackTrace();
}
}
}
@@ -21,7 +21,7 @@ public class BufferedStateManipulator implements BufferedItem {
state.update(false);
} catch(Exception e) {
main.logger().warning("Could not apply BlockState at " + origin + ": " + e.getMessage());
main.getDebugLogger().stack(e);
e.printStackTrace();
}
}
}
@@ -1,8 +0,0 @@
package com.dfsek.terra.api.transform;
public class NotNullValidator<T> implements Validator<T> {
@Override
public boolean validate(T value) {
return !(value == null);
}
}
@@ -53,6 +53,7 @@ public class Transformer<F, T> {
private final LinkedHashMap<Transform<F, T>, List<Validator<T>>> transforms = new LinkedHashMap<>();
@SafeVarargs
@SuppressWarnings("varargs")
public final Builder<F, T> addTransform(Transform<F, T> transform, Validator<T>... validators) {
transforms.put(transform, Arrays.asList(validators));
return this;
@@ -1,6 +1,12 @@
package com.dfsek.terra.api.transform;
import java.util.Objects;
public interface Validator<T> {
boolean validate(T value) throws TransformException;
static <T> Validator<T> notNull() {
return Objects::nonNull;
}
}
@@ -1,9 +1,13 @@
package com.dfsek.terra.api.util;
import com.dfsek.terra.api.TerraPlugin;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -32,4 +36,12 @@ public class JarUtil {
}
}
}
public static JarFile getJarFile() throws URISyntaxException, IOException {
return new JarFile(new File(getJarURL().toURI()));
}
public static URL getJarURL() {
return TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation();
}
}
@@ -4,16 +4,10 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.command.CommandTemplate;
import com.dfsek.terra.api.command.annotation.Command;
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.platform.entity.Player;
import com.dfsek.terra.world.TerraWorld;
@Command
@WorldCommand
@PlayerCommand
@DebugCommand
public class ProfileQueryCommand implements CommandTemplate {
@Inject
@@ -21,8 +15,9 @@ public class ProfileQueryCommand implements CommandTemplate {
@Override
public void execute(CommandSender sender) {
Player player = (Player) sender;
TerraWorld world = main.getWorld(player.getWorld());
player.sendMessage(world.getProfiler().getResultsFormatted());
StringBuilder data = new StringBuilder("Terra Profiler data dump: \n");
main.getProfiler().getTimings().forEach((id, timings) -> data.append(id).append(": ").append(timings.toString()).append('\n'));
main.logger().info(data.toString());
sender.sendMessage("Profiler data dumped to console.");
}
}
@@ -4,16 +4,10 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.command.CommandTemplate;
import com.dfsek.terra.api.command.annotation.Command;
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.platform.entity.Player;
import com.dfsek.terra.world.TerraWorld;
@Command
@WorldCommand
@PlayerCommand
@DebugCommand
public class ProfileResetCommand implements CommandTemplate {
@Inject
@@ -21,9 +15,7 @@ public class ProfileResetCommand implements CommandTemplate {
@Override
public void execute(CommandSender sender) {
Player player = (Player) sender;
TerraWorld world = main.getWorld(player.getWorld());
world.getProfiler().reset();
player.sendMessage("Profiler reset.");
main.getProfiler().reset();
sender.sendMessage("Profiler reset.");
}
}
@@ -4,16 +4,10 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.command.CommandTemplate;
import com.dfsek.terra.api.command.annotation.Command;
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.platform.entity.Player;
import com.dfsek.terra.world.TerraWorld;
@Command
@WorldCommand
@PlayerCommand
@DebugCommand
public class ProfileStartCommand implements CommandTemplate {
@Inject
@@ -21,9 +15,7 @@ public class ProfileStartCommand implements CommandTemplate {
@Override
public void execute(CommandSender sender) {
Player player = (Player) sender;
TerraWorld world = main.getWorld(player.getWorld());
world.getProfiler().setProfiling(true);
player.sendMessage("Profiling enabled.");
main.getProfiler().start();
sender.sendMessage("Profiling enabled.");
}
}
@@ -4,16 +4,10 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.command.CommandTemplate;
import com.dfsek.terra.api.command.annotation.Command;
import com.dfsek.terra.api.command.annotation.type.DebugCommand;
import com.dfsek.terra.api.command.annotation.type.PlayerCommand;
import com.dfsek.terra.api.command.annotation.type.WorldCommand;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.platform.entity.Player;
import com.dfsek.terra.world.TerraWorld;
@Command
@WorldCommand
@PlayerCommand
@DebugCommand
public class ProfileStopCommand implements CommandTemplate {
@Inject
@@ -21,9 +15,7 @@ public class ProfileStopCommand implements CommandTemplate {
@Override
public void execute(CommandSender sender) {
Player player = (Player) sender;
TerraWorld world = main.getWorld(player.getWorld());
world.getProfiler().setProfiling(false);
player.sendMessage("Profiling disabled.");
main.getProfiler().stop();
sender.sendMessage("Profiling disabled.");
}
}
@@ -69,12 +69,12 @@ public class PluginConfig implements ConfigTemplate {
ConfigLoader loader = new ConfigLoader();
loader.load(this, file);
if(dumpDefaultConfig) { // Don't dump default config if already loaded.
try(JarFile jar = new JarFile(new File(TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) {
try(JarFile jar = main.getModJar()) {
JarUtil.copyResourcesToDirectory(jar, "packs", new File(main.getDataFolder(), "packs").toString());
} catch(IOException | URISyntaxException e) {
main.getDebugLogger().error("Failed to dump default config files!");
e.printStackTrace();
main.getDebugLogger().error("Report this to Terra!");
main.getDebugLogger().error("Either you're on Forge, or this is a bug. If it's the latter, report this to Terra!");
}
}
} catch(ConfigException | IOException e) {
@@ -1,147 +0,0 @@
package com.dfsek.terra.config.builder;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.ExpressionSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.world.generation.WorldGenerator;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class GeneratorBuilder {
private final Map<Long, WorldGenerator> gens = Collections.synchronizedMap(new HashMap<>());
private String noiseEquation;
private String elevationEquation;
private String carvingEquation;
private Scope varScope;
private Map<String, NoiseSeeded> noiseBuilderMap;
private Map<String, FunctionTemplate> functionTemplateMap;
private PaletteHolder palettes;
private PaletteHolder slantPalettes;
private boolean preventInterpolation;
private boolean interpolateElevation;
private NoiseSeeded biomeNoise;
private double elevationWeight;
private int blendDistance;
private int blendStep;
private double blendWeight;
public WorldGenerator build(long seed) {
synchronized(gens) {
return gens.computeIfAbsent(seed, k -> {
NoiseSampler noise;
NoiseSampler elevation;
NoiseSampler carving;
try {
noise = new ExpressionSampler(noiseEquation, varScope, seed, noiseBuilderMap, functionTemplateMap);
elevation = elevationEquation == null ? new ConstantSampler(0) : new ExpressionSampler(elevationEquation, varScope, seed, noiseBuilderMap, functionTemplateMap);
carving = new ExpressionSampler(carvingEquation, varScope, seed, noiseBuilderMap, functionTemplateMap);
} catch(ParseException e) {
throw new RuntimeException(e);
}
return new WorldGenerator(palettes, slantPalettes, noise, elevation, carving, biomeNoise.apply(seed), elevationWeight, blendDistance, blendStep, blendWeight);
});
}
}
public void setBlendWeight(double blendWeight) {
this.blendWeight = blendWeight;
}
public void setFunctionTemplateMap(Map<String, FunctionTemplate> functionTemplateMap) {
this.functionTemplateMap = functionTemplateMap;
}
public void setBlendStep(int blendStep) {
this.blendStep = blendStep;
}
public void setBlendDistance(int blendDistance) {
this.blendDistance = blendDistance;
}
public void setBiomeNoise(NoiseSeeded biomeNoise) {
this.biomeNoise = biomeNoise;
}
public void setElevationWeight(double elevationWeight) {
this.elevationWeight = elevationWeight;
}
public void setNoiseEquation(String noiseEquation) {
this.noiseEquation = noiseEquation;
}
public void setElevationEquation(String elevationEquation) {
this.elevationEquation = elevationEquation;
}
public void setCarvingEquation(String carvingEquation) {
this.carvingEquation = carvingEquation;
}
public Scope getVarScope() {
return varScope;
}
public void setVarScope(Scope varScope) {
this.varScope = varScope;
}
public void setNoiseBuilderMap(Map<String, NoiseSeeded> noiseBuilderMap) {
this.noiseBuilderMap = noiseBuilderMap;
}
public PaletteHolder getPalettes() {
return palettes;
}
public void setPalettes(PaletteHolder palettes) {
this.palettes = palettes;
}
public PaletteHolder getSlantPalettes() {
return slantPalettes;
}
public void setSlantPalettes(PaletteHolder slantPalettes) {
this.slantPalettes = slantPalettes;
}
public boolean isPreventInterpolation() {
return preventInterpolation;
}
public void setPreventInterpolation(boolean preventInterpolation) {
this.preventInterpolation = preventInterpolation;
}
public void setInterpolateElevation(boolean interpolateElevation) {
this.interpolateElevation = interpolateElevation;
}
public boolean interpolateElevation() {
return interpolateElevation;
}
}
@@ -9,9 +9,6 @@ import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import java.io.File;
import java.util.UUID;
public class DummyWorld implements World {
@Override
public Object getHandle() {
@@ -33,31 +30,11 @@ public class DummyWorld implements World {
return () -> (GeneratorWrapper) () -> null;
}
@Override
public String getName() {
return "DUMMY";
}
@Override
public UUID getUID() {
return UUID.randomUUID();
}
@Override
public boolean isChunkGenerated(int x, int z) {
return false;
}
@Override
public Chunk getChunkAt(int x, int z) {
throw new UnsupportedOperationException("Cannot get chunk in DummyWorld");
}
@Override
public File getWorldFolder() {
throw new UnsupportedOperationException("Cannot get folder of DummyWorld");
}
@Override
public Block getBlockAt(int x, int y, int z) {
throw new UnsupportedOperationException("Cannot get block in DummyWorld");
@@ -1,5 +1,6 @@
package com.dfsek.terra.config.fileloaders;
import com.dfsek.tectonic.config.Configuration;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.terra.api.util.GlueList;
@@ -18,8 +19,12 @@ public abstract class Loader {
*
* @param consumer Something to do with the streams.
*/
public Loader then(ExceptionalConsumer<List<InputStream>> consumer) throws ConfigException {
consumer.accept(new GlueList<>(streams.values()));
public Loader then(ExceptionalConsumer<List<Configuration>> consumer) throws ConfigException {
List<Configuration> list = new GlueList<>();
streams.forEach((id, stream) -> {
list.add(new Configuration(stream, id));
});
consumer.accept(list);
return this;
}
@@ -17,7 +17,7 @@ public final class LangUtil {
public static void load(String langID, TerraPlugin main) {
Logger logger = main.logger();
File file = new File(main.getDataFolder(), "lang");
try(JarFile jar = new JarFile(new File(TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) {
try(JarFile jar = main.getModJar()) {
copyResourcesToDirectory(jar, "lang", file.toString());
} catch(IOException | URISyntaxException e) {
main.getDebugLogger().error("Failed to dump language files!");
@@ -18,7 +18,7 @@ public class OreHolderLoader implements TypeLoader<OreHolder> {
Map<String, Object> map = (Map<String, Object>) o;
for(Map.Entry<String, Object> entry : map.entrySet()) {
holder.add(configLoader.loadClass(Ore.class, entry.getKey()), (OreConfig) configLoader.loadType(OreConfig.class, entry.getValue()));
holder.add(configLoader.loadClass(Ore.class, entry.getKey()), configLoader.loadClass(OreConfig.class, entry.getValue()), entry.getKey());
}
return holder;
@@ -2,6 +2,7 @@ package com.dfsek.terra.config.pack;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.tectonic.abstraction.AbstractConfigLoader;
import com.dfsek.tectonic.config.Configuration;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
@@ -110,6 +111,8 @@ public class ConfigPack implements LoaderRegistrar {
private final TerraPlugin main;
private final Loader loader;
private final Configuration configuration;
private final BiomeProvider.BiomeProviderBuilder biomeProviderBuilder;
@@ -130,15 +133,20 @@ public class ConfigPack implements LoaderRegistrar {
File pack = new File(folder, "pack.yml");
try {
selfLoader.load(template, new FileInputStream(pack));
configuration = new Configuration(new FileInputStream(pack));
selfLoader.load(template, configuration);
main.logger().info("Loading config pack \"" + template.getID() + "\"");
main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, configuration)));
load(l, main);
ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate();
selfLoader.load(packPostTemplate, new FileInputStream(pack));
biomeProviderBuilder = packPostTemplate.getProviderBuilder();
biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time.
checkDeadEntries(main);
} catch(FileNotFoundException e) {
throw new LoadException("No pack.yml file found in " + folder.getAbsolutePath(), e);
}
@@ -173,9 +181,12 @@ public class ConfigPack implements LoaderRegistrar {
if(pack == null) throw new LoadException("No pack.yml file found in " + file.getName());
selfLoader.load(template, file.getInputStream(pack));
configuration = new Configuration(file.getInputStream(pack));
selfLoader.load(template, configuration);
main.logger().info("Loading config pack \"" + template.getID() + "\"");
main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, configuration)));
load(l, main);
ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate();
@@ -183,6 +194,7 @@ public class ConfigPack implements LoaderRegistrar {
selfLoader.load(packPostTemplate, file.getInputStream(pack));
biomeProviderBuilder = packPostTemplate.getProviderBuilder();
biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time.
checkDeadEntries(main);
} catch(IOException e) {
throw new LoadException("Unable to load pack.yml from ZIP file", e);
}
@@ -198,9 +210,17 @@ public class ConfigPack implements LoaderRegistrar {
for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main));
}
private void load(long start, TerraPlugin main) throws ConfigException {
main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this));
private void checkDeadEntries(TerraPlugin main) {
biomeRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in biome registry: '" + id + "'"));
paletteRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in palette registry: '" + id + "'"));
floraRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in flora registry: '" + id + "'"));
carverRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in carver registry: '" + id + "'"));
treeRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in tree registry: '" + id + "'"));
oreRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in ore registry: '" + id + "'"));
}
private void load(long start, TerraPlugin main) throws ConfigException {
for(Map.Entry<String, Double> var : template.getVariables().entrySet()) {
varScope.create(var.getKey(), var.getValue());
}
@@ -225,15 +245,15 @@ public class ConfigPack implements LoaderRegistrar {
}).close();
loader
.open("carving", ".yml").then(streams -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.load(streams, CarverTemplate::new), main)).close()
.open("palettes", ".yml").then(streams -> buildAll(new PaletteFactory(), paletteRegistry, abstractConfigLoader.load(streams, PaletteTemplate::new), main)).close()
.open("ores", ".yml").then(streams -> buildAll(new OreFactory(), oreRegistry, abstractConfigLoader.load(streams, OreTemplate::new), main)).close()
.open("structures/trees", ".yml").then(streams -> buildAll(new TreeFactory(), treeRegistry, abstractConfigLoader.load(streams, TreeTemplate::new), main)).close()
.open("structures/structures", ".yml").then(streams -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.load(streams, StructureTemplate::new), main)).close()
.open("flora", ".yml").then(streams -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.load(streams, FloraTemplate::new), main)).close()
.open("biomes", ".yml").then(streams -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.load(streams, () -> new BiomeTemplate(this, main)), main)).close();
.open("carving", ".yml").then(configs -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.loadConfigs(configs, CarverTemplate::new), main)).close()
.open("palettes", ".yml").then(configs -> buildAll(new PaletteFactory(), paletteRegistry, abstractConfigLoader.loadConfigs(configs, PaletteTemplate::new), main)).close()
.open("ores", ".yml").then(configs -> buildAll(new OreFactory(), oreRegistry, abstractConfigLoader.loadConfigs(configs, OreTemplate::new), main)).close()
.open("structures/trees", ".yml").then(configs -> buildAll(new TreeFactory(), treeRegistry, abstractConfigLoader.loadConfigs(configs, TreeTemplate::new), main)).close()
.open("structures/structures", ".yml").then(configs -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.loadConfigs(configs, StructureTemplate::new), main)).close()
.open("flora", ".yml").then(configs -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.loadConfigs(configs, FloraTemplate::new), main)).close()
.open("biomes", ".yml").then(configs -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.loadConfigs(configs, () -> new BiomeTemplate(this, main)), main)).close();
main.getEventManager().callEvent(new ConfigPackPostLoadEvent(this));
main.getEventManager().callEvent(new ConfigPackPostLoadEvent(this, template -> selfLoader.load(template, configuration)));
main.logger().info("Loaded config pack \"" + template.getID() + "\" v" + template.getVersion() + " by " + template.getAuthor() + " in " + (System.nanoTime() - start) / 1000000D + "ms.");
}
@@ -1,36 +0,0 @@
package com.dfsek.terra.profiler;
/**
* Class to hold a profiler data value. Contains formatting method to highlight value based on desired range.
*/
public class DataHolder {
private final long desired;
private final DataType type;
private final double desiredRangePercent;
/**
* Constructs a DataHolder with a DataType and a desired value, including a percentage around the desired value considered acceptable
*
* @param type The type of data held in this instance.
* @param desired The desired value. This should be the average value of whatever is being measured.
* @param desiredRangePercent The percentage around the desired value to be considered acceptable.
*/
public DataHolder(DataType type, long desired, double desiredRangePercent) {
this.desired = desired;
this.type = type;
this.desiredRangePercent = desiredRangePercent;
}
/**
* Returns a String, formatted with Bungee ChatColors.<br>
* GREEN if the value is better than desired and outside of acceptable range.<br>
* YELLOW if the value is better or worse than desired, and within acceptable range.<br>
* RED if the value is worse than desired and outside of acceptable range.<br>
*
* @param data The data to format.
* @return String - The formatted data.
*/
public String getFormattedData(long data) {
return type.getFormatted(data);
}
}
@@ -1,24 +0,0 @@
package com.dfsek.terra.profiler;
import net.jafama.FastMath;
public enum DataType {
PERIOD_MILLISECONDS(Desire.LOW, 1000000, "ms"), PERIOD_NANOSECONDS(Desire.LOW, 1, "ns");
private final Desire desire;
private final long divisor;
private final String unit;
DataType(Desire d, long divisor, String unit) {
this.desire = d;
this.divisor = divisor;
this.unit = unit;
}
public String getFormatted(long value) {
return (double) FastMath.round(((double) value / divisor) * 100D) / 100D + unit;
}
public Desire getDesire() {
return desire;
}
}
@@ -1,10 +0,0 @@
package com.dfsek.terra.profiler;
/**
* Enum to represent the "goal" of a value, whether it is desirable for the value to be high (e.g. Frequency), or low (e.g. Period)
*/
public enum Desire {
LOW, HIGH
}
@@ -0,0 +1,24 @@
package com.dfsek.terra.profiler;
public class Frame {
private final String id;
private final long start;
public Frame(String id) {
this.id = id;
this.start = System.nanoTime();
}
public String getId() {
return id;
}
public long getStart() {
return start;
}
@Override
public String toString() {
return id;
}
}
@@ -1,87 +0,0 @@
package com.dfsek.terra.profiler;
import com.dfsek.terra.api.math.MathUtil;
import com.dfsek.terra.api.util.GlueList;
import net.jafama.FastMath;
import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
/**
* Class to record and hold all data for a single type of measurement performed by the profiler.
*/
public class Measurement {
private final List<Long> measurements = new LinkedList<>();
private final long desirable;
private final DataType type;
private long min = Long.MAX_VALUE;
private long max = Long.MIN_VALUE;
/**
* Constructs a new Measurement with a desired value and DataType.
*
* @param desirable The desired value of the measurement.
* @param type The type of data the measurement is holding.
*/
public Measurement(long desirable, DataType type) {
this.desirable = desirable;
this.type = type;
}
public void record(long value) {
max = FastMath.max(value, max);
min = FastMath.min(value, min);
measurements.add(value);
}
public int size() {
return measurements.size();
}
public ProfileFuture beginMeasurement() {
ProfileFuture future = new ProfileFuture();
long current = System.nanoTime();
future.thenRun(() -> record(System.nanoTime() - current));
return future;
}
public void reset() {
min = Long.MAX_VALUE;
max = Long.MIN_VALUE;
measurements.clear();
}
public DataHolder getDataHolder() {
return new DataHolder(type, desirable, 0.25);
}
public long getMin() {
if(min == Long.MAX_VALUE) return 0;
return min;
}
public long getMax() {
if(max == Long.MIN_VALUE) return 0;
return max;
}
public long average() {
BigInteger running = BigInteger.valueOf(0);
List<Long> mTemp = new GlueList<>(measurements);
for(Long l : mTemp) {
running = running.add(BigInteger.valueOf(l));
}
if(measurements.size() == 0) return 0;
return running.divide(BigInteger.valueOf(measurements.size())).longValue();
}
public double getStdDev() {
return MathUtil.standardDeviation(new GlueList<>(measurements));
}
public int entries() {
return measurements.size();
}
}
@@ -0,0 +1,14 @@
package com.dfsek.terra.profiler;
public class ProfileFrame implements AutoCloseable {
private final Runnable action;
public ProfileFrame(Runnable action) {
this.action = action;
}
@Override
public void close() {
action.run();
}
}
@@ -1,18 +0,0 @@
package com.dfsek.terra.profiler;
import java.util.concurrent.CompletableFuture;
public class ProfileFuture extends CompletableFuture<Boolean> implements AutoCloseable {
public ProfileFuture() {
super();
}
public boolean complete() {
return super.complete(true);
}
@Override
public void close() {
this.complete();
}
}
@@ -0,0 +1,56 @@
package com.dfsek.terra.profiler;
import java.util.Map;
public interface Profiler {
/**
* Push a frame to this profiler.
*
* @param frame ID of frame.
*/
void push(String frame);
/**
* Pop a frame from this profiler.
*
* @param frame ID of frame. Must match ID
* at the top of the profiler stack.
*/
void pop(String frame);
/**
* Start profiling.
*/
void start();
/**
* Stop profiling.
*/
void stop();
/**
* Get the profiler data.
*
* @return Profiler data.
*/
Map<String, Timings> getTimings();
/**
* Return a {@link AutoCloseable} implementation that
* may be used in a try-with-resources statement for
* more intuitive profiling, with auto-push/pop.
*
* @param frame ID of frame.
* @return {@link AutoCloseable} implementation for use
* in try-with-resources.
*/
default ProfileFrame profile(String frame) {
push(frame);
return new ProfileFrame(() -> pop(frame));
}
/**
* Clear the profiler data.
*/
void reset();
}
@@ -0,0 +1,91 @@
package com.dfsek.terra.profiler;
import com.dfsek.terra.api.util.mutable.MutableInteger;
import com.dfsek.terra.profiler.exception.MalformedStackException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
public class ProfilerImpl implements Profiler {
private static final ThreadLocal<Stack<Frame>> THREAD_STACK = ThreadLocal.withInitial(Stack::new);
private static final ThreadLocal<Map<String, List<Long>>> TIMINGS = ThreadLocal.withInitial(HashMap::new);
private final List<Map<String, List<Long>>> accessibleThreadMaps = new ArrayList<>();
private volatile boolean running = false;
private static boolean instantiated = false;
private static final ThreadLocal<Boolean> SAFE = ThreadLocal.withInitial(() -> false);
private static final ThreadLocal<MutableInteger> STACK_SIZE = ThreadLocal.withInitial(() -> new MutableInteger(0));
public ProfilerImpl() {
if(instantiated) throw new IllegalStateException("Only one instance of Profiler may exist!");
instantiated = true;
}
@Override
public void push(String frame) {
STACK_SIZE.get().increment();
if(running && SAFE.get()) {
Stack<Frame> stack = THREAD_STACK.get();
stack.push(new Frame(stack.isEmpty() ? frame : stack.peek().getId() + "." + frame));
} else SAFE.set(false);
}
@Override
public void pop(String frame) {
MutableInteger size = STACK_SIZE.get();
size.decrement();
if(running && SAFE.get()) {
long time = System.nanoTime();
Stack<Frame> stack = THREAD_STACK.get();
Map<String, List<Long>> timingsMap = TIMINGS.get();
if(timingsMap.size() == 0) {
synchronized(accessibleThreadMaps) {
accessibleThreadMaps.add(timingsMap);
}
}
Frame top = stack.pop();
if((stack.size() != 0 && !top.getId().endsWith("." + frame)) || (stack.size() == 0 && !top.getId().equals(frame)))
throw new MalformedStackException("Expected " + frame + ", found " + top);
List<Long> timings = timingsMap.computeIfAbsent(top.getId(), id -> new ArrayList<>());
timings.add(time - top.getStart());
}
if(size.get() == 0) SAFE.set(true);
}
@Override
public void start() {
running = true;
}
@Override
public void stop() {
running = false;
}
@Override
public Map<String, Timings> getTimings() {
Map<String, Timings> map = new HashMap<>();
accessibleThreadMaps.forEach(smap -> smap.forEach((key, list) -> {
String[] keys = key.split("\\.");
Timings timings = map.computeIfAbsent(keys[0], id -> new Timings());
for(int i = 1; i < keys.length; i++) {
timings = timings.getSubItem(keys[i]);
}
list.forEach(timings::addTime);
}));
return map;
}
@Override
public void reset() {
accessibleThreadMaps.forEach(Map::clear);
}
}
@@ -0,0 +1,73 @@
package com.dfsek.terra.profiler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Timings {
private final Map<String, Timings> subItems = new HashMap<>();
private final List<Long> timings = new ArrayList<>();
public void addTime(long time) {
timings.add(time);
}
public List<Long> getTimings() {
return timings;
}
public double average() {
return (double) timings.stream().reduce(0L, Long::sum) / timings.size();
}
public long max() {
return timings.stream().mapToLong(Long::longValue).max().orElse(0L);
}
public long min() {
return timings.stream().mapToLong(Long::longValue).min().orElse(0L);
}
public double sum() {
return timings.stream().mapToDouble(Long::doubleValue).sum();
}
public Timings getSubItem(String id) {
return subItems.computeIfAbsent(id, s -> new Timings());
}
public String toString(int indent, Timings parent, Set<Integer> branches) {
StringBuilder builder = new StringBuilder();
builder.append((double) min() / 1000000).append("ms min / ").append(average() / 1000000).append("ms avg / ")
.append((double) max() / 1000000).append("ms max (").append(timings.size()).append(" samples, ")
.append((sum() / parent.sum()) * 100).append("% of parent)");
List<String> frames = new ArrayList<>();
Set<Integer> newBranches = new HashSet<>(branches);
newBranches.add(indent);
subItems.forEach((id, timings) -> frames.add(id + ": " + timings.toString(indent + 1, this, newBranches)));
for(int i = 0; i < frames.size(); i++) {
builder.append('\n');
for(int j = 0; j < indent; j++) {
if(branches.contains(j)) builder.append("");
else builder.append(" ");
}
if(i == frames.size() - 1 && !frames.get(i).contains("\n")) builder.append("└───");
else builder.append("├───");
builder.append(frames.get(i));
}
return builder.toString();
}
@Override
public String toString() {
return toString(1, this, Collections.emptySet());
}
}
@@ -1,85 +0,0 @@
package com.dfsek.terra.profiler;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.world.TerraWorld;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import net.jafama.FastMath;
import java.util.Map;
public class WorldProfiler {
private final BiMap<String, Measurement> measures = HashBiMap.create();
private final World world;
private boolean isProfiling;
public WorldProfiler(World w) {
if(!TerraWorld.isTerraWorld(w))
throw new IllegalArgumentException("Attempted to instantiate profiler on non-Terra managed world!");
this.addMeasurement(new Measurement(2500000, DataType.PERIOD_MILLISECONDS), "TotalChunkGenTime")
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "FloraTime")
.addMeasurement(new Measurement(10000000, DataType.PERIOD_MILLISECONDS), "TreeTime")
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime")
.addMeasurement(new Measurement(5000000, DataType.PERIOD_MILLISECONDS), "CaveTime")
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime");
isProfiling = false;
this.world = w;
}
public String getResultsFormatted() {
if(! isProfiling) return "Profiler is not currently running.";
StringBuilder result = new StringBuilder("Gaea World Profiler Results (Min / Avg / Max / Std Dev): \n");
for(Map.Entry<String, Measurement> e : measures.entrySet()) {
result
.append(e.getKey())
.append(": ")
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().getMin()))
.append(" / ")
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().average()))
.append(" / ")
.append(e.getValue().getDataHolder().getFormattedData(e.getValue().getMax()))
.append(" / ")
.append((double) FastMath.round((e.getValue().getStdDev() / 1000000) * 100D) / 100D)
.append("ms")
.append(" (x").append(e.getValue().size()).append(")\n");
}
return result.toString();
}
public void reset() {
for(Map.Entry<String, Measurement> e : measures.entrySet()) {
e.getValue().reset();
}
}
public com.dfsek.terra.profiler.WorldProfiler addMeasurement(Measurement m, String name) {
measures.put(name, m);
return this;
}
public void setMeasurement(String id, long value) {
if(isProfiling) measures.get(id).record(value);
}
public ProfileFuture measure(String id) {
if(isProfiling) return measures.get(id).beginMeasurement();
else return null;
}
public String getID(Measurement m) {
return measures.inverse().get(m);
}
public boolean isProfiling() {
return isProfiling;
}
public void setProfiling(boolean enabled) {
this.isProfiling = enabled;
}
public World getWorld() {
return world;
}
}
@@ -0,0 +1,17 @@
package com.dfsek.terra.profiler.exception;
public class MalformedStackException extends ProfilerException {
private static final long serialVersionUID = -3009539681021691054L;
public MalformedStackException(String message) {
super(message);
}
public MalformedStackException(String message, Throwable cause) {
super(message, cause);
}
public MalformedStackException(Throwable cause) {
super(cause);
}
}
@@ -0,0 +1,17 @@
package com.dfsek.terra.profiler.exception;
public class ProfilerException extends RuntimeException {
private static final long serialVersionUID = 8206737998791649002L;
public ProfilerException(String message) {
super(message);
}
public ProfilerException(String message, Throwable cause) {
super(message, cause);
}
public ProfilerException(Throwable cause) {
super(cause);
}
}
@@ -7,18 +7,19 @@ import com.dfsek.terra.registry.exception.DuplicateEntryException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* Registry implementation with read/write access. For internal use only.
* @param <T>
*/
public class OpenRegistry<T> implements Registry<T> {
private final Map<String, T> objects = new HashMap<>();
private final Map<String, Entry<T>> objects = new HashMap<>();
@Override
public T load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
@@ -35,6 +36,10 @@ public class OpenRegistry<T> implements Registry<T> {
* @param value Value to add.
*/
public boolean add(String identifier, T value) {
return add(identifier, new Entry<>(value));
}
protected boolean add(String identifier, Entry<T> value) {
boolean exists = objects.containsKey(identifier);
objects.put(identifier, value);
return exists;
@@ -60,22 +65,24 @@ public class OpenRegistry<T> implements Registry<T> {
@Override
public T get(String identifier) {
return objects.get(identifier);
Entry<T> entry = objects.get(identifier);
if(entry == null) return null;
return entry.getValue();
}
@Override
public void forEach(Consumer<T> consumer) {
objects.forEach((id, obj) -> consumer.accept(obj));
objects.forEach((id, obj) -> consumer.accept(obj.getRaw()));
}
@Override
public void forEach(BiConsumer<String, T> consumer) {
objects.forEach(consumer);
objects.forEach((id, entry) -> consumer.accept(id, entry.getRaw()));
}
@Override
public Set<T> entries() {
return new HashSet<>(objects.values());
return objects.values().stream().map(Entry::getRaw).collect(Collectors.toSet());
}
@Override
@@ -83,10 +90,41 @@ public class OpenRegistry<T> implements Registry<T> {
return objects.keySet();
}
public Map<String, T> getDeadEntries() {
Map<String, T> dead = new HashMap<>();
objects.forEach((id, entry) -> {
if(entry.dead()) dead.put(id, entry.value); // dont increment value here.
});
return dead;
}
/**
* Clears all entries from the registry.
*/
public void clear() {
objects.clear();
}
protected static final class Entry<T> {
private final T value;
private final AtomicInteger access = new AtomicInteger(0);
public Entry(T value) {
this.value = value;
}
public T getValue() {
access.incrementAndGet();
return value;
}
private T getRaw() {
return value;
}
public boolean dead() {
return access.get() == 0;
}
}
}
@@ -57,7 +57,9 @@ public class FloraRegistry extends OpenRegistry<Flora> {
private void addItem(String id, Callable<ConstantFlora> flora) {
try {
add(id, flora.call());
Entry<Flora> entry = new Entry<>(flora.call());
entry.getValue(); // Mark as not dead.
add(id, entry);
} catch(Exception e) {
main.logger().warning("Failed to load Flora item: " + id + ": " + e.getMessage());
}
@@ -66,10 +68,4 @@ public class FloraRegistry extends OpenRegistry<Flora> {
private BlockData data(String s) {
return main.getWorldHandle().createBlockData(s);
}
@Override
public Flora get(String identifier) {
return super.get(identifier);
}
}
@@ -13,7 +13,6 @@ import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.profiler.WorldProfiler;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import net.jafama.FastMath;
@@ -21,33 +20,25 @@ public class TerraWorld {
private final BiomeProvider provider;
private final WorldConfig config;
private final boolean safe;
private final WorldProfiler profiler;
private final World world;
private final BlockData air;
public TerraWorld(World w, ConfigPack c, TerraPlugin main) {
if(!isTerraWorld(w)) throw new IllegalArgumentException("World " + w + " is not a Terra World!");
if(!w.isTerraWorld()) throw new IllegalArgumentException("World " + w + " is not a Terra World!");
this.world = w;
config = c.toWorldConfig(this);
this.provider = config.getProvider();
profiler = new WorldProfiler(w);
air = main.getWorldHandle().createBlockData("minecraft:air");
main.getEventManager().callEvent(new TerraWorldLoadEvent(this, c));
safe = true;
}
public static boolean isTerraWorld(World w) {
return w.getGenerator().getHandle() instanceof GeneratorWrapper;
}
public World getWorld() {
return world;
}
public TerraChunkGenerator getGenerator() {
return ((GeneratorWrapper) world.getGenerator().getHandle()).getHandle();
}
public BiomeProvider getBiomeProvider() {
return provider;
@@ -61,9 +52,6 @@ public class TerraWorld {
return safe;
}
public WorldProfiler getProfiler() {
return profiler;
}
/**
* Get a block at an ungenerated location
@@ -82,7 +70,7 @@ public class TerraWorld {
double noise = sampler.sample(fdX, y, fdZ);
if(noise > 0) {
int level = 0;
for(int yi = world.getMaxHeight(); yi > y; yi--) {
for(int yi = world.getMaxHeight()-1; yi > y; yi--) {
if(sampler.sample(fdX, yi, fdZ) > 0) level++;
else level = 0;
}
@@ -15,7 +15,7 @@ import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.profiler.ProfileFrame;
import com.dfsek.terra.world.Carver;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.carving.NoiseCarver;
@@ -94,7 +94,7 @@ public class DefaultChunkGenerator2D implements TerraChunkGenerator {
public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) {
TerraWorld tw = main.getWorld(world);
BiomeProvider grid = tw.getBiomeProvider();
try(ProfileFuture ignore = tw.getProfiler().measure("TotalChunkGenTime")) {
try(ProfileFrame ignore = main.getProfiler().profile("chunk_base_2d")) {
if(!tw.isSafe()) return chunk;
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
@@ -23,7 +23,7 @@ import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.palette.SinglePalette;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.profiler.ProfileFrame;
import com.dfsek.terra.world.Carver;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.carving.NoiseCarver;
@@ -50,7 +50,6 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
private final Carver carver;
public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) {
this.configPack = c;
this.main = main;
@@ -104,9 +103,10 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
@Override
@SuppressWarnings({"try"})
public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) {
TerraWorld tw = main.getWorld(world);
BiomeProvider grid = tw.getBiomeProvider();
try(ProfileFuture ignore = tw.getProfiler().measure("TotalChunkGenTime")) {
try(ProfileFrame ignore = main.getProfiler().profile("chunk_base_3d")) {
TerraWorld tw = main.getWorld(world);
BiomeProvider grid = tw.getBiomeProvider();
if(!tw.isSafe()) return chunk;
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
@@ -120,7 +120,7 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
int cx = xOrig + x;
int cz = zOrig + z;
TerraBiome b = grid.getBiome(xOrig + x, zOrig + z);
TerraBiome b = grid.getBiome(cx, cz);
BiomeTemplate c = ((UserDefinedBiome) b).getConfig();
int sea = c.getSeaLevel();
@@ -227,17 +227,20 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
return false;
}
@SuppressWarnings({"try"})
static void biomes(@NotNull World world, int chunkX, int chunkZ, @NotNull BiomeGrid biome, TerraPlugin main) {
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
BiomeProvider grid = main.getWorld(world).getBiomeProvider();
for(int x = 0; x < 4; x++) {
for(int z = 0; z < 4; z++) {
int cx = xOrig + (x << 2);
int cz = zOrig + (z << 2);
TerraBiome b = grid.getBiome(cx, cz);
try(ProfileFrame ignore = main.getProfiler().profile("biomes")) {
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
BiomeProvider grid = main.getWorld(world).getBiomeProvider();
for(int x = 0; x < 4; x++) {
for(int z = 0; z < 4; z++) {
int cx = xOrig + (x << 2);
int cz = zOrig + (z << 2);
TerraBiome b = grid.getBiome(cx, cz);
biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz));
biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz));
}
}
}
}
@@ -25,7 +25,7 @@ public class SamplerCache {
public Sampler load(@NotNull Long key) {
int cx = (int) (key >> 32);
int cz = (int) key.longValue();
return world.getGenerator().createSampler(cx, cz, world.getBiomeProvider(), world.getWorld(), world.getConfig().getTemplate().getElevationBlend());
return world.getWorld().getTerraGenerator().createSampler(cx, cz, world.getBiomeProvider(), world.getWorld(), world.getConfig().getTemplate().getElevationBlend());
}
});
}
@@ -14,7 +14,7 @@ import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.config.templates.CarverTemplate;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.profiler.ProfileFrame;
import com.dfsek.terra.world.TerraWorld;
import org.jetbrains.annotations.NotNull;
@@ -38,7 +38,7 @@ public class CavePopulator implements TerraBlockPopulator, Chunkified {
TerraWorld tw = main.getWorld(world);
WorldHandle handle = main.getWorldHandle();
BlockData AIR = handle.createBlockData("minecraft:air");
try(ProfileFuture ignored = tw.getProfiler().measure("CaveTime")) {
try(ProfileFrame ignore = main.getProfiler().profile("carving")) {
Random random = PopulationUtil.getRandom(chunk);
if(!tw.isSafe()) return;
WorldConfig config = tw.getConfig();
@@ -49,38 +49,40 @@ public class CavePopulator implements TerraBlockPopulator, Chunkified {
Map<Location, BlockData> shiftCandidate = new HashMap<>();
Set<Block> updateNeeded = new HashSet<>();
c.carve(chunk.getX(), chunk.getZ(), world, (v, type) -> {
Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ());
BlockData m = b.getBlockData();
BlockType re = m.getBlockType();
switch(type) {
case CENTER:
if(template.getInner().canReplace(re)) {
b.setBlockData(template.getInner().get(v.getBlockY()).get(random), false);
if(template.getUpdate().contains(re)) updateNeeded.add(b);
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
}
break;
case WALL:
if(template.getOuter().canReplace(re)) {
b.setBlockData(template.getOuter().get(v.getBlockY()).get(random), false);
if(template.getUpdate().contains(re)) updateNeeded.add(b);
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
}
break;
case TOP:
if(template.getTop().canReplace(re)) {
b.setBlockData(template.getTop().get(v.getBlockY()).get(random), false);
if(template.getUpdate().contains(re)) updateNeeded.add(b);
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
}
break;
case BOTTOM:
if(template.getBottom().canReplace(re)) {
b.setBlockData(template.getBottom().get(v.getBlockY()).get(random), false);
if(template.getUpdate().contains(re)) updateNeeded.add(b);
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
}
break;
try(ProfileFrame ignored = main.getProfiler().profile("carving:" + c.getConfig().getID())) {
Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ());
BlockData m = b.getBlockData();
BlockType re = m.getBlockType();
switch(type) {
case CENTER:
if(template.getInner().canReplace(re)) {
b.setBlockData(template.getInner().get(v.getBlockY()).get(random), false);
if(template.getUpdate().contains(re)) updateNeeded.add(b);
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
}
break;
case WALL:
if(template.getOuter().canReplace(re)) {
b.setBlockData(template.getOuter().get(v.getBlockY()).get(random), false);
if(template.getUpdate().contains(re)) updateNeeded.add(b);
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
}
break;
case TOP:
if(template.getTop().canReplace(re)) {
b.setBlockData(template.getTop().get(v.getBlockY()).get(random), false);
if(template.getUpdate().contains(re)) updateNeeded.add(b);
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
}
break;
case BOTTOM:
if(template.getBottom().canReplace(re)) {
b.setBlockData(template.getBottom().get(v.getBlockY()).get(random), false);
if(template.getUpdate().contains(re)) updateNeeded.add(b);
if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m);
}
break;
}
}
});
for(Map.Entry<Location, BlockData> entry : shiftCandidate.entrySet()) {
@@ -93,7 +95,7 @@ public class CavePopulator implements TerraBlockPopulator, Chunkified {
if(template.getShift().get(entry.getValue().getBlockType()).contains(mut.getBlock().getBlockData().getBlockType())) {
mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(entry.getValue().getBlockType(), BlockType::getDefaultData), false);
}
} catch(NullPointerException ignore) {
} catch(NullPointerException ignored) {
}
}
for(Block b : updateNeeded) {
@@ -8,7 +8,7 @@ import com.dfsek.terra.api.util.world.PopulationUtil;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.profiler.ProfileFrame;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.population.items.flora.FloraLayer;
import org.jetbrains.annotations.NotNull;
@@ -32,8 +32,8 @@ public class FloraPopulator implements TerraBlockPopulator {
@Override
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("FloraTime")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
try(ProfileFrame ignore = main.getProfiler().profile("flora")) {
if(tw.getConfig().getTemplate().disableFlora()) return;
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
@@ -10,7 +10,7 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.profiler.ProfileFrame;
import com.dfsek.terra.world.TerraWorld;
import org.jetbrains.annotations.NotNull;
@@ -27,8 +27,8 @@ public class OrePopulator implements TerraBlockPopulator {
@Override
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("OreTime")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
try(ProfileFrame ignore = main.getProfiler().profile("ore")) {
if(tw.getConfig().getTemplate().disableOres()) return;
if(!tw.isSafe()) return;
for(int cx = -1; cx <= 1; cx++) {
@@ -40,11 +40,13 @@ public class OrePopulator implements TerraBlockPopulator {
BiomeTemplate config = ((UserDefinedBiome) b).getConfig();
int finalCx = cx;
int finalCz = cz;
config.getOreHolder().forEach((ore, oreConfig) -> {
int amount = oreConfig.getAmount().get(random);
for(int i = 0; i < amount; i++) {
Vector3 location = new Vector3(random.nextInt(16) + 16 * finalCx, oreConfig.getHeight().get(random), random.nextInt(16) + 16 * finalCz);
ore.generate(location, chunk, random);
config.getOreHolder().forEach((id, orePair) -> {
try(ProfileFrame ignored = main.getProfiler().profile("ore:" + id)) {
int amount = orePair.getRight().getAmount().get(random);
for(int i = 0; i < amount; i++) {
Vector3 location = new Vector3(random.nextInt(16) + 16 * finalCx, orePair.getRight().getHeight().get(random), random.nextInt(16) + 16 * finalCz);
orePair.getLeft().generate(location, chunk, random);
}
}
});
}
@@ -11,9 +11,8 @@ import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.Chunkified;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.profiler.ProfileFrame;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.population.items.TerraStructure;
import net.jafama.FastMath;
@@ -32,8 +31,8 @@ public class StructurePopulator implements TerraBlockPopulator, Chunkified {
@Override
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("StructureTime")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
try(ProfileFrame ignore = main.getProfiler().profile("structure")) {
if(tw.getConfig().getTemplate().disableStructures()) return;
int cx = (chunk.getX() << 4);
int cz = (chunk.getZ() << 4);
@@ -8,7 +8,7 @@ import com.dfsek.terra.api.util.world.PopulationUtil;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.profiler.ProfileFrame;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.population.items.tree.TreeLayer;
import net.jafama.FastMath;
@@ -32,8 +32,8 @@ public class TreePopulator implements TerraBlockPopulator {
@SuppressWarnings("try")
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("TreeTime")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
try(ProfileFrame ignore = main.getProfiler().profile("tree")) {
if(tw.getConfig().getTemplate().disableTrees()) return;
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
@@ -42,8 +42,9 @@ public class TreePopulator implements TerraBlockPopulator {
for(int z = 0; z < 16; z += 2) {
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z);
for(TreeLayer layer : biome.getConfig().getTrees()) {
if(layer.getDensity() >= random.nextDouble() * 100)
if(layer.getDensity() >= random.nextDouble() * 100) {
layer.place(chunk, new Vector2(offset(random, x), offset(random, z)));
}
}
}
}
@@ -16,7 +16,6 @@ public abstract class Ore {
protected TerraPlugin main;
public Ore(BlockData material, MaterialSet replaceable, boolean applyGravity, TerraPlugin main) {
this.material = material;
this.replaceable = replaceable;
this.applyGravity = applyGravity;
@@ -1,6 +1,7 @@
package com.dfsek.terra.world.population.items.ores;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.util.generic.pair.ImmutablePair;
import java.util.List;
import java.util.function.BiConsumer;
@@ -11,22 +12,24 @@ import java.util.function.BiConsumer;
public class OreHolder {
private final List<Entry> entries = new GlueList<>();
public void forEach(BiConsumer<Ore, OreConfig> consumer) {
entries.forEach(entry -> consumer.accept(entry.getOre(), entry.getConfig()));
public void forEach(BiConsumer<String, ImmutablePair<Ore, OreConfig>> consumer) {
entries.forEach(entry -> consumer.accept(entry.getId(), ImmutablePair.of(entry.getOre(), entry.getConfig())));
}
public OreHolder add(Ore ore, OreConfig config) {
entries.add(new Entry(ore, config));
public OreHolder add(Ore ore, OreConfig config, String id) {
entries.add(new Entry(ore, config, id));
return this;
}
private static final class Entry {
private final Ore ore;
private final OreConfig config;
private final String id;
private Entry(Ore ore, OreConfig config) {
private Entry(Ore ore, OreConfig config, String id) {
this.ore = ore;
this.config = config;
this.id = id;
}
public OreConfig getConfig() {
@@ -36,5 +39,9 @@ public class OreHolder {
public Ore getOre() {
return ore;
}
public String getId() {
return id;
}
}
}
+1 -2
View File
@@ -7,7 +7,6 @@ cache:
carver: 512
structure: 32
sampler: 128
master-disable:
caves: false
biome-provider: 32
script:
max-recursion: 1000
+122
View File
@@ -0,0 +1,122 @@
enable:
- "Pokud se vám líbí Terra, můžete nás podpořit na Patreon!"
- "Získáte přístup k experimentálním funkcím, než budou vydány!"
- "Podpořit projekt můžete zde: https://www.patreon.com/dfsek"
disable:
- "Děkujeme, že používáte Terra!"
command:
debug-only: "Tento příkaz musí být použit se zapnutým debug modem!"
player-only: "Tento příkaz je pouze pro hráče!"
invalid: "Neznámý příkaz. (Očekáváno %1$s argumentů, nalezeno %2$s)."
players-only: "Příkaz je pouze pro použití hráčem."
world: "Tento příkaz musí být použit v Terra světě!"
reload: "Obnoven Terra konfig."
reload-error: "Nastaly chyby při obnově Terra konfigurace. Podívejte se do logů pro více informací."
version: "Na tomto serveru běží Terra verze \"%1$s\", na platformě \"%2$s\""
main-menu:
- "--------------------Terra--------------------"
- "reload - Obnoví konfigurační data"
- "biome - Ukáže aktuální biom"
- "ore - Generuje žílu rud v lokaci, ve směru kam se koukáte (Pro debugging)"
- "save-data - Uložit populační data"
- "structure - Nahrát a exportovat struktury"
- "profile - Profiler možnosti"
- "image - Obrázek/GUI možnosti"
biome:
biome-found: "Lokalizován biom na (%1$s, %2$s)"
unable-to-locate: "Nelze lokalizovat biom."
invalid-radius: "Nesprávný radius: \"%s\""
invalid: "Nesprávné ID bomu: \"%s\""
in: "Jste v \"%s\""
packs:
main: "Aktuální instalované konfigurační balíčky:"
pack: " - %1$s v%3$s od %2$s"
none: "Žádné konfigurační balíčky nejsou nainstalovány."
ore:
main-menu:
- "---------------Terra/ore---------------"
- "Generuje žílu rud na bloku, na který koukáte."
out-of-range: "Blok mimo dosah"
invalid-ore: "Nelze nalézt Rudu \"%s\""
geometry:
main-menu:
- "---------------Terra/geometry----------------"
- "Různé voxel geometrické debugging příkazy"
- "sphere - Generuje kouli"
- "deformsphere - Generuje deformovanou kouli"
- "tube - Generuje válec"
deform:
invalid-radius: "Nesprávný radius: \"%s\""
invalid-deform: "Nesprávná deformace: \"%s\""
invalid-frequency: "Nesprávná frekvence: \"%s\""
sphere:
invalid-radius: "Nesprávný radius: \"%s\""
tube:
invalid-radius: "Nesprávný radius: \"%s\""
image:
main-menu:
- "---------------Terra/image---------------"
- "render - Vykreslí obrázek s danou šířkou a výškou, který může být později importován jako svět."
- "gui - Otevřít debug GUI (Musí být zapnuto v konfigu)"
gui:
main-menu:
- "-------------Terra/image/gui-------------"
- "raw - Otevře GUI s raw Biom daty"
- "step - Znovu vykreslí data k lepšímu zobrazení borderu"
debug: "Debug mod musí být zapnutý pro použití této možnosti! Debug GUI NENÍ PRODUKČNĚ BEZPEČNÉ!"
render:
save: "Uložen obrázek jako \"%s\""
error: "Nastala chyba při generování obrázku!"
profile:
main-menu:
- "---------------Terra/profile---------------"
- "start - Zapne profiler"
- "stop - Vypne profiler"
- "query - Ukáže profiler data"
- "reset - Resetuje profiler data"
reset: "Profiler byl resetován."
start: "Profiler byl zapnut."
stop: "Profiler byl vypnut."
structure:
main-menu:
- "---------------Terra/structure---------------"
- "export - Export vašeho výběru WorldEdit jako Terra struktura."
- "load - Načíst Terra strukturu"
invalid-radius: "Nesprávný radius: \"%s\""
invalid-rotation: "Nesprávná rotace: \"%s\""
invalid: "Nesprávné ID struktury: \"%s\""
export: "Uložena struktura do \"%s\""
world-config:
load: "Načteny konfigurační hodnoty světa pro svět \"%s\"..."
not-found: "Konfigurace pro svět \"%s\" nenalezena. Kopíruji defaultní konfig."
using-image: "Načítám svět z obrázku."
error: "Nelze načíst konfigurace pro svět %s"
done: "Načítání světa \"%1$s\" dokončeno. Uplynulý čas: %2$sms"
config-pack:
loaded: "Konfigurační balíček %1$s v%4$s od %3$s byl načten za %2$sms."
config:
loaded: "Načten %1$s ze souboru %2$s"
loaded-all: "Načteno %1$s %2$s(s) za %3$sms."
error:
invalid-failover: "Nesprávný typ failover: \"%s\""
duplicate: "Duplikační ID nalezeno v souboru: %s"
file:
- "Konfigurační chyba pro Terra objekt. Soubor: %1$s"
- "%2$s"
- "Opravte jej před pokračováním!"
generic:
- "Nastala chyba při načítání konfigurace."
- "Prosíme nahlašte to na Terra."
warning:
no-population: "Žádné populační chunky nebyly načteny. Pokud je to poprvé, co zapínáte server s Terra, či vytváříte nový svět, je tohle normální."
error:
severe-config: "Vážná konfigurační chyba zabránila Terra ze správné generace terénu na koordinátech: %1$s, %2$s. Prosíme zkontrolujte konfiguraci pro chyby. Jakékoli konfigurační chyby jsou vypsány výše."
debug:
data-save : "Uložena populační data."
use-paper:
- "Vypadá to, že používáte Spigot/CraftBukkit."
- "Ačkoli Terra &ofunguje&r na Spigot, některé funkce budou ztraceny. (Terra je netestována na CraftBukkit; žádná podpora nebude dána pro CraftBukkit)."
- "Pro nejvíce funkcí s Terra, použijte Paper."
- "Navíc, Paper přináší obrovské výkonnostní zlepešení než Spigot, a všechny Spigot pluginy by měli fungovat s Paper!"
- "Pro nejlepší zážitek s Terra a všemi pluginy, použijte prosím Paper."
- "Více info najdete na stránce Paperu: https://papermc.io/"
@@ -40,6 +40,7 @@ import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.profiler.Profiler;
import com.dfsek.terra.registry.config.BiomeRegistry;
import com.dfsek.terra.registry.config.NoiseRegistry;
import com.dfsek.terra.world.TerraWorld;
@@ -137,6 +138,11 @@ public class DistributionTest {
return null;
}
@Override
public Profiler getProfiler() {
return null;
}
@Override
public void register(TypeRegistry registry) {
@@ -153,7 +159,7 @@ public class DistributionTest {
new GenericLoaders(MAIN).register(loader);
BiomeRegistry biomeRegistry = new BiomeRegistry();
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), MAIN));
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.loadConfigs(inputStreams, TestBiome::new), MAIN));
BiomeProviderTemplate template = new BiomeProviderTemplate();
ConfigLoader pipeLoader = new ConfigLoader()
+1 -1
View File
@@ -46,7 +46,7 @@ public class ImageTest {
OpenRegistry<TerraBiome> biomeRegistry = new OpenRegistry<TerraBiome>() {
};
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), null));
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.loadConfigs(inputStreams, TestBiome::new), null));
return new ImageBiomeProvider(biomeRegistry.entries(), ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER);
}
@@ -0,0 +1,63 @@
package profiler;
import com.dfsek.terra.profiler.Profiler;
import com.dfsek.terra.profiler.ProfilerImpl;
public class ProfilerTest {
private static final Profiler PROFILER = new ProfilerImpl();
//@Test
public static void main(String... a) throws InterruptedException {
//PROFILER.start();
for(int i = 0; i < 1000; i++) {
doThing();
}
for(int i = 0; i < 100; i++) {
doThirdOtherThing();
}
for(int i = 0; i < 100; i++) {
doOtherThing();
}
PROFILER.stop();
PROFILER.push("thing");
PROFILER.push("thing2");
PROFILER.start();
PROFILER.pop("thing2");
PROFILER.pop("thing");
PROFILER.push("thing4");
PROFILER.pop("thing4");
PROFILER.getTimings().forEach((id, timings) -> {
System.out.println(id + ": " + timings.toString());
});
}
private static void doThing() throws InterruptedException {
PROFILER.push("thing");
Thread.sleep(1);
doOtherThing();
thing4();
PROFILER.pop("thing");
}
private static void doOtherThing() throws InterruptedException {
PROFILER.push("thing2");
Thread.sleep(2);
doThirdOtherThing();
thing4();
PROFILER.pop("thing2");
}
private static void doThirdOtherThing() throws InterruptedException {
PROFILER.push("thing3");
Thread.sleep(2);
PROFILER.pop("thing3");
}
private static void thing4() throws InterruptedException {
PROFILER.push("thing4");
Thread.sleep(2);
PROFILER.pop("thing4");
}
}
@@ -13,6 +13,7 @@ import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -20,7 +21,7 @@ import java.util.Map;
public class ParserTest {
@Test
public void parse() throws IOException, ParseException {
Parser parser = new Parser(IOUtils.toString(getClass().getResourceAsStream("/test.tesf")));
Parser parser = new Parser(IOUtils.toString(getClass().getResourceAsStream("/test.tesf"), Charset.defaultCharset()));
parser.registerFunction("test", new FunctionBuilder<Test1>() {
@Override
+15
View File
@@ -0,0 +1,15 @@
# Magic options for more perf
org.gradle.jvmargs=-Xmx2048M -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC
org.gradle.vfs.watch=true
kapt.use.worker.api=true
kapt.include.compile.classpath=false
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.warning.mode=all
#org.gradle.logging.level=info
# Project information
terra.description=A fast, modern, extensible, platform-agnostic data-driven world generator
terra.source=https://github.com/PolyhedralDev/Terra
terra.issues=https://github.com/PolyhedralDev/Terra/issues
terra.wiki=https://github.com/PolyhedralDev/Terra/wiki
terra.license=GNU General Public License, version 3.0
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
org.gradle.jvmargs=-Xmx4096m
+9 -15
View File
@@ -16,19 +16,12 @@ configureCommon()
group = "com.dfsek.terra.bukkit"
val mcVersion = "1.16.5"
val testDir = "target/server/"
val testDir = "target/server"
val testMem = "3G"
val paperURL = "https://papermc.io/api/v1/paper/%version%/latest/download/"
val purpurURL = "https://ci.pl3x.net/job/Purpur/lastSuccessfulBuild/artifact/final/purpurclip.jar"
repositories {
mavenCentral()
maven { url = uri("http://maven.enginehub.org/repo/") }
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
}
dependencies {
"shadedApi"(project(":common"))
@@ -39,17 +32,17 @@ dependencies {
"compileOnly"("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT")
"shadedImplementation"("com.google.guava:guava:30.0-jre")
"shadedApi"("com.google.guava:guava:30.0-jre")
}
val aikarsFlags = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200",
val jvmFlags = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200",
"-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch",
"-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M",
"-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4",
"-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90",
"-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem",
"-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs",
"-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear")
"-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear", "-javaagent:paperclip.jar")
fun downloadPaperclip(url: String, dir: String) {
val clip = URL(url.replace("%version%", mcVersion))
@@ -77,8 +70,8 @@ fun installServer(dir: String) {
// Cloning test setup.
gitClone("https://github.com/PolyhedralDev/WorldGenTestServer")
// Copying plugins
Files.move(Paths.get("WorldGenTestServer/plugins"),
Paths.get("$testDir/$dir/plugins"),
Files.move(file("WorldGenTestServer/plugins").toPath(),
file("$testDir/$dir/plugins").toPath(),
StandardCopyOption.REPLACE_EXISTING)
// Copying config
val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText()
@@ -160,7 +153,7 @@ task<JavaExec>(name = "runPaper") {
}
main = "io.papermc.paperclip.Paperclip"
jvmArgs = aikarsFlags
jvmArgs = jvmFlags
maxHeapSize = testMem
minHeapSize = testMem
//args = listOf("nogui")
@@ -178,7 +171,7 @@ task<JavaExec>(name = "runPurpur") {
}
main = "io.papermc.paperclip.Paperclip"
jvmArgs = aikarsFlags
jvmArgs = jvmFlags
maxHeapSize = testMem
minHeapSize = testMem
//args = listOf("nogui")
@@ -189,6 +182,7 @@ task<JavaExec>(name = "runPurpur") {
tasks.named<ShadowJar>("shadowJar") {
relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats")
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
relocate("com.google.common", "com.dfsek.terra.lib.google.common")
}
publishing {
@@ -34,12 +34,15 @@ import com.dfsek.terra.bukkit.listeners.SpigotListener;
import com.dfsek.terra.bukkit.listeners.TerraListener;
import com.dfsek.terra.bukkit.util.PaperUtil;
import com.dfsek.terra.bukkit.world.BukkitBiome;
import com.dfsek.terra.bukkit.world.BukkitWorld;
import com.dfsek.terra.commands.CommandUtil;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.profiler.Profiler;
import com.dfsek.terra.profiler.ProfilerImpl;
import com.dfsek.terra.registry.master.AddonRegistry;
import com.dfsek.terra.registry.master.ConfigRegistry;
import com.dfsek.terra.world.TerraWorld;
@@ -64,6 +67,8 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
private final Map<World, TerraWorld> worldMap = new HashMap<>();
private final Map<String, ConfigPack> worlds = new HashMap<>();
private final Profiler profiler = new ProfilerImpl();
private final ConfigRegistry registry = new ConfigRegistry();
private final CheckedRegistry<ConfigPack> checkedRegistry = new CheckedRegistry<>(registry);
@@ -141,6 +146,11 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
Bukkit.getScheduler().runTask(this, task);
}
@Override
public Profiler getProfiler() {
return profiler;
}
@Override
public void onDisable() {
BukkitChunkGeneratorWrapper.saveAll();
@@ -259,14 +269,15 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin {
return checkedRegistry;
}
public TerraWorld getWorld(World w) {
if(!TerraWorld.isTerraWorld(w))
public TerraWorld getWorld(World world) {
BukkitWorld w = (BukkitWorld) world;
if(!w.isTerraWorld())
throw new IllegalArgumentException("Not a Terra world! " + w.getGenerator());
if(!worlds.containsKey(w.getName())) {
getLogger().warning("Unexpected world load detected: \"" + w.getName() + "\"");
return new TerraWorld(w, ((TerraChunkGenerator) w.getGenerator().getHandle()).getConfigPack(), this);
}
return worldMap.computeIfAbsent(w, world -> new TerraWorld(w, worlds.get(w.getName()), this));
return worldMap.computeIfAbsent(w, w2 -> new TerraWorld(w, worlds.get(w.getName()), this));
}
@Override
@@ -3,19 +3,11 @@ package com.dfsek.terra.bukkit.generator;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.bukkit.population.PopulationManager;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.bukkit.world.BukkitBiomeGrid;
import com.dfsek.terra.profiler.DataType;
import com.dfsek.terra.profiler.Measurement;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.population.CavePopulator;
import com.dfsek.terra.world.population.FloraPopulator;
import com.dfsek.terra.world.population.OrePopulator;
import com.dfsek.terra.world.population.StructurePopulator;
import com.dfsek.terra.world.population.TreePopulator;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
@@ -24,13 +16,10 @@ import org.jetbrains.annotations.NotNull;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper {
@@ -63,7 +52,7 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener
}
public static synchronized void fixChunk(Chunk c) {
if(!TerraWorld.isTerraWorld(c.getWorld())) throw new IllegalArgumentException();
if(!c.getWorld().isTerraWorld()) throw new IllegalArgumentException();
popMap.get(c.getWorld()).checkNeighbors(c.getX(), c.getZ(), c.getWorld());
}
@@ -76,8 +65,6 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener
e.printStackTrace();
}
popMap.put(w, popMan);
main.getWorld(w).getProfiler().addMeasurement(new Measurement(15000000, DataType.PERIOD_MILLISECONDS), "PopulationManagerTime");
popMan.attachProfiler(main.getWorld(w).getProfiler());
needsLoad = false;
}
@@ -44,7 +44,7 @@ public class CommonListener implements Listener {
public void onSaplingGrow(StructureGrowEvent e) {
if(e.isCancelled()) return;
World bukkit = BukkitAdapter.adapt(e.getWorld());
if(!TerraWorld.isTerraWorld(bukkit)) return;
if(!bukkit.isTerraWorld()) return;
TerraWorld tw = main.getWorld(bukkit);
WorldConfig c = tw.getConfig();
if(c.getTemplate().isDisableSaplings()) return;
@@ -18,8 +18,7 @@ public class PaperListener implements Listener {
@EventHandler
public void onStructureLocate(StructureLocateEvent e) {
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getWorld()))) return;
e.setResult(null); // Assume no result.
if(!BukkitAdapter.adapt(e.getWorld()).isTerraWorld()) return;
String name = "minecraft:" + e.getType().getName();
main.getDebugLogger().info("Overriding structure location for \"" + name + "\"");
TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getWorld()));
@@ -32,10 +31,8 @@ public class PaperListener implements Listener {
}, main);
finder.run(); // Do this synchronously.
} else {
main.logger().warning("No overrides are defined for \"" + name + "\"");
e.setResult(e.getOrigin());
main.logger().warning("No overrides are defined for \"" + name + "\". Locating this structure will NOT work properly!");
}
}
}
@@ -34,7 +34,7 @@ public class SpigotListener implements Listener {
Entity entity = e.getEntity();
if(e.getEntityType().equals(EntityType.ENDER_SIGNAL)) {
main.getDebugLogger().info("Detected Ender Signal...");
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return;
if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return;
TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getEntity().getWorld()));
EnderSignal signal = (EnderSignal) entity;
TerraStructure config = tw.getConfig().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD"));
@@ -53,7 +53,7 @@ public class SpigotListener implements Listener {
@EventHandler
public void onCartographerChange(VillagerAcquireTradeEvent e) {
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return;
if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return;
if(!(e.getEntity() instanceof Villager)) return;
if(((Villager) e.getEntity()).getProfession().equals(Villager.Profession.CARTOGRAPHER)) {
main.logger().severe("Prevented server crash by stopping Cartographer villager from spawning.");
@@ -65,7 +65,7 @@ public class SpigotListener implements Listener {
@EventHandler
public void onCartographerLevel(VillagerCareerChangeEvent e) {
if(!TerraWorld.isTerraWorld(BukkitAdapter.adapt(e.getEntity().getWorld()))) return;
if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return;
if(e.getProfession().equals(Villager.Profession.CARTOGRAPHER)) {
main.logger().severe("Prevented server crash by stopping Cartographer villager from spawning.");
main.logger().severe("Please upgrade to Paper, which has a StructureLocateEvent that fixes this issue");
@@ -22,7 +22,9 @@ public class TerraListener implements EventListener {
public void injectTrees(ConfigPackPreLoadEvent event) {
for(TreeType value : TreeType.values()) {
try {
event.getPack().getTreeRegistry().add(BukkitAdapter.TREE_TRANSFORMER.translate(value), new BukkitTree(value, main));
String id = BukkitAdapter.TREE_TRANSFORMER.translate(value);
event.getPack().getTreeRegistry().add(id, new BukkitTree(value, main));
event.getPack().getTreeRegistry().get(id); // Platform trees should never be marked "dead"
} catch(DuplicateEntryException ignore) { // If another addon has already registered trees, do nothing.
}
}
@@ -2,6 +2,7 @@ package com.dfsek.terra.bukkit.population;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.bukkit.world.BukkitWorld;
import java.io.Serializable;
import java.util.UUID;
@@ -21,7 +22,7 @@ public class ChunkCoordinate implements Serializable {
public ChunkCoordinate(Chunk c) {
this.x = c.getX();
this.z = c.getZ();
this.worldID = c.getWorld().getUID();
this.worldID = ((BukkitWorld) c.getWorld()).getUID();
}
public UUID getWorldID() {
@@ -1,20 +0,0 @@
package com.dfsek.terra.bukkit.population;
import com.dfsek.terra.api.platform.world.World;
import java.io.File;
public class Gaea {
private static boolean debug;
public static File getGaeaFolder(World w) {
File f = new File(w.getWorldFolder(), "gaea");
f.mkdirs();
return f;
}
public static boolean isDebug() {
return debug;
}
}
@@ -5,12 +5,11 @@ import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.generation.Chunkified;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.profiler.WorldProfiler;
import com.dfsek.terra.bukkit.world.BukkitWorld;
import com.dfsek.terra.profiler.ProfileFrame;
import org.bukkit.generator.BlockPopulator;
import org.jetbrains.annotations.NotNull;
@@ -26,39 +25,36 @@ public class PopulationManager extends BlockPopulator {
private final TerraChunkGenerator generator;
private final HashSet<ChunkCoordinate> needsPop = new HashSet<>();
private final TerraPlugin main;
private WorldProfiler profiler;
public PopulationManager(TerraChunkGenerator generator, TerraPlugin main) {
this.generator = generator;
this.main = main;
}
private ProfileFuture measure() {
if(profiler != null) return profiler.measure("PopulationManagerTime");
return null;
}
public void attachProfiler(WorldProfiler p) {
this.profiler = p;
}
@SuppressWarnings("unchecked")
public synchronized void saveBlocks(World w) throws IOException {
File f = new File(Gaea.getGaeaFolder(w), "chunks.bin");
File f = new File(getDataFolder(w), "chunks.bin");
f.createNewFile();
SerializationUtil.toFile((HashSet<ChunkCoordinate>) needsPop.clone(), f);
}
@SuppressWarnings("unchecked")
public synchronized void loadBlocks(World w) throws IOException, ClassNotFoundException {
File f = new File(Gaea.getGaeaFolder(w), "chunks.bin");
File f = new File(getDataFolder(w), "chunks.bin");
needsPop.addAll((HashSet<ChunkCoordinate>) SerializationUtil.fromFile(f));
}
public static File getDataFolder(World w) {
File f = new File(((BukkitWorld) w).getWorldFolder(), "gaea");
f.mkdirs();
return f;
}
// Synchronize to prevent chunks from being queued for population multiple times.
public synchronized void checkNeighbors(int x, int z, World w) {
ChunkCoordinate c = new ChunkCoordinate(x, z, w.getUID());
public synchronized void checkNeighbors(int x, int z, World world) {
BukkitWorld w = (BukkitWorld) world;
ChunkCoordinate c = new ChunkCoordinate(x, z, (w).getUID());
if(w.isChunkGenerated(x + 1, z)
&& w.isChunkGenerated(x - 1, z)
&& w.isChunkGenerated(x, z + 1)
@@ -78,8 +74,9 @@ public class PopulationManager extends BlockPopulator {
}
@Override
@SuppressWarnings("try")
public void populate(org.bukkit.@NotNull World world, @NotNull Random random, org.bukkit.@NotNull Chunk source) {
try(ProfileFuture ignored = measure()) {
try(ProfileFrame ignore = main.getProfiler().profile("popman")) {
Chunk chunk = BukkitAdapter.adapt(source);
needsPop.add(new ChunkCoordinate(chunk));
int x = chunk.getX();
@@ -5,8 +5,10 @@ import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.profiler.ProfileFrame;
import org.bukkit.TreeType;
import java.util.Locale;
import java.util.Random;
public class BukkitTree implements Tree {
@@ -40,8 +42,11 @@ public class BukkitTree implements Tree {
}
@Override
@SuppressWarnings("try")
public boolean plant(Location l, Random r) {
return ((BukkitWorld) l.getWorld()).getHandle().generateTree(BukkitAdapter.adapt(l), delegate);
try(ProfileFrame ignore = main.getProfiler().profile("bukkit_tree:" + delegate.toString().toLowerCase(Locale.ROOT))) {
return ((BukkitWorld) l.getWorld()).getHandle().generateTree(BukkitAdapter.adapt(l), delegate);
}
}
@Override
@@ -37,17 +37,14 @@ public class BukkitWorld implements World {
return new BukkitChunkGenerator(delegate.getGenerator());
}
@Override
public String getName() {
return delegate.getName();
}
@Override
public UUID getUID() {
return delegate.getUID();
}
@Override
public boolean isChunkGenerated(int x, int z) {
return delegate.isChunkGenerated(x, z);
}
@@ -57,7 +54,6 @@ public class BukkitWorld implements World {
return BukkitAdapter.adapt(delegate.getChunkAt(x, z));
}
@Override
public File getWorldFolder() {
return delegate.getWorldFolder();
}
@@ -4,6 +4,7 @@ import com.dfsek.terra.api.platform.block.state.SerialState;
import com.dfsek.terra.api.platform.block.state.Sign;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("deprecation")
public class BukkitSign extends BukkitBlockState implements Sign {
protected BukkitSign(org.bukkit.block.Sign block) {
super(block);
@@ -3,16 +3,13 @@ main: "com.dfsek.terra.bukkit.TerraBukkitPlugin"
version: "@VERSION@"
load: "STARTUP"
author: dfsek
website: "@WIKI@"
api-version: "1.13"
description: "An insanely powerful free & open-source data-driven world generator."
description: "@DESCRIPTION@"
softdepend: [ "WorldEdit" ]
commands:
terra:
description: "Terra base command"
usage: "/terra "
aliases: [ "te" ]
permission: "terra.command"
locate:
description: "Locate a Terra Structure"
usage: "/locate <STRUCTURE_ID> <radius>"
permission: "terra.locate"
permission: "terra.command"
+35 -10
View File
@@ -6,6 +6,7 @@ import net.fabricmc.loom.task.RemapJarTask
plugins {
`java-library`
`maven-publish`
id("fabric-loom").version("0.6-SNAPSHOT")
id("com.modrinth.minotaur").version("1.1.0")
}
@@ -21,24 +22,24 @@ group = "com.dfsek.terra.fabric"
dependencies {
"shadedApi"(project(":common"))
"shadedImplementation"("org.yaml:snakeyaml:1.27")
"shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1")
"minecraft"("com.mojang:minecraft:1.16.5")
"mappings"("net.fabricmc:yarn:1.16.5+build.5:v2")
"modImplementation"("net.fabricmc:fabric-loader:0.11.2")
"modImplementation"("net.fabricmc.fabric-api:fabric-api:0.31.0+1.16")
}
tasks.named<ShadowJar>("shadowJar") {
relocate("org.json", "com.dfsek.terra.lib.json")
relocate("org.yaml", "com.dfsek.terra.lib.yaml")
"modCompileOnly"("com.sk89q.worldedit:worldedit-fabric-mc1.16:7.2.0-SNAPSHOT") {
exclude(group = "com.google.guava", module = "guava")
exclude(group = "com.google.code.gson", module = "gson")
exclude(group = "it.unimi.dsi", module = "fastutil")
exclude(group = "org.apache.logging.log4j", module = "log4j-api")
exclude(group = "org.apache.logging.log4j", module = "log4j-core")
}
}
configure<LoomGradleExtension> {
accessWidener("src/main/resources/terra.accesswidener")
refmapName = "terra-refmap.json"
}
val remapped = tasks.register<RemapJarTask>("remapShadedJar") {
@@ -52,15 +53,39 @@ val remapped = tasks.register<RemapJarTask>("remapShadedJar") {
}
tasks.register<TaskModrinthUpload>("publishModrinth") {
tasks.register<TaskModrinthUpload>("publishModrinthFabric") {
dependsOn("remapShadedJar")
group = "fabric"
token = System.getenv("MODRINTH_SECRET")
projectId = "FIlZB9L0"
versionNumber = project.version.toString()
versionNumber = "${project.version}-fabric"
uploadFile = remapped.get().archiveFile.get().asFile
releaseType = "beta"
addGameVersion("1.16.4")
addGameVersion("1.16.5")
addLoader("fabric")
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
artifact(tasks["sourcesJar"])
artifact(tasks["jar"])
}
}
repositories {
val mavenUrl = "https://repo.codemc.io/repository/maven-releases/"
maven(mavenUrl) {
val mavenUsername: String? by project
val mavenPassword: String? by project
if (mavenUsername != null && mavenPassword != null) {
credentials {
username = mavenUsername
password = mavenPassword
}
}
}
}
}
@@ -1,5 +1,8 @@
package com.dfsek.terra.fabric;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addons.TerraAddon;
@@ -8,15 +11,14 @@ import com.dfsek.terra.api.addons.annotations.Author;
import com.dfsek.terra.api.addons.annotations.Version;
import com.dfsek.terra.api.command.CommandManager;
import com.dfsek.terra.api.command.TerraCommandManager;
import com.dfsek.terra.api.command.exception.CommandException;
import com.dfsek.terra.api.command.exception.MalformedCommandException;
import com.dfsek.terra.api.event.EventListener;
import com.dfsek.terra.api.event.EventManager;
import com.dfsek.terra.api.event.TerraEventManager;
import com.dfsek.terra.api.event.annotations.Global;
import com.dfsek.terra.api.event.annotations.Priority;
import com.dfsek.terra.api.event.events.config.ConfigPackPostLoadEvent;
import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.platform.CommandSender;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.handle.WorldHandle;
@@ -24,126 +26,121 @@ import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.LockedRegistry;
import com.dfsek.terra.api.transform.NotNullValidator;
import com.dfsek.terra.api.transform.Transformer;
import com.dfsek.terra.api.transform.Validator;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.util.logging.DebugLogger;
import com.dfsek.terra.api.util.logging.Logger;
import com.dfsek.terra.commands.CommandUtil;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.fabric.inventory.FabricItemHandle;
import com.dfsek.terra.fabric.mixin.GeneratorTypeAccessor;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.FabricBiome;
import com.dfsek.terra.fabric.world.FabricTree;
import com.dfsek.terra.fabric.world.FabricWorldHandle;
import com.dfsek.terra.fabric.world.TerraBiomeSource;
import com.dfsek.terra.fabric.world.features.PopulatorFeature;
import com.dfsek.terra.fabric.world.generator.FabricChunkGenerator;
import com.dfsek.terra.fabric.world.generator.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.config.DimensionConfig;
import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions;
import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.PopulatorFeature;
import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.dfsek.terra.fabric.handle.FabricItemHandle;
import com.dfsek.terra.fabric.handle.FabricWorldHandle;
import com.dfsek.terra.fabric.util.FabricUtil;
import com.dfsek.terra.profiler.Profiler;
import com.dfsek.terra.profiler.ProfilerImpl;
import com.dfsek.terra.registry.exception.DuplicateEntryException;
import com.dfsek.terra.registry.master.AddonRegistry;
import com.dfsek.terra.registry.master.ConfigRegistry;
import com.dfsek.terra.world.TerraWorld;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.block.Blocks;
import net.minecraft.client.world.GeneratorType;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.LiteralText;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeEffects;
import net.minecraft.world.biome.GenerationSettings;
import net.minecraft.world.biome.SpawnSettings;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.decorator.Decorator;
import net.minecraft.world.gen.decorator.NopeDecoratorConfig;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.ConfiguredFeatures;
import net.minecraft.world.gen.feature.DefaultBiomeFeatures;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.FeatureConfig;
import net.minecraft.world.gen.surfacebuilder.SurfaceBuilder;
import net.minecraft.world.gen.surfacebuilder.TernarySurfaceConfig;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
private final org.apache.logging.log4j.Logger log4jLogger = LogManager.getLogger();
public static final PopulatorFeature POPULATOR_FEATURE = new PopulatorFeature(DefaultFeatureConfig.CODEC);
public static final ConfiguredFeature<?, ?> POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configure(FeatureConfig.DEFAULT).decorate(Decorator.NOPE.configure(NopeDecoratorConfig.INSTANCE));
private static TerraFabricPlugin instance;
private final Map<Long, TerraWorld> worldMap = new HashMap<>();
private final Map<DimensionType, Pair<ServerWorld, TerraWorld>> worldMap = new HashMap<>();
public Map<DimensionType, Pair<ServerWorld, TerraWorld>> getWorldMap() {
return worldMap;
}
private final EventManager eventManager = new TerraEventManager(this);
private final GenericLoaders genericLoaders = new GenericLoaders(this);
private final Logger logger = new Logger() {
private final org.apache.logging.log4j.Logger logger = LogManager.getLogger();
private final Profiler profiler = new ProfilerImpl();
private final Logger logger = new Logger() {
@Override
public void info(String message) {
logger.info(message);
log4jLogger.info(message);
}
@Override
public void warning(String message) {
logger.warn(message);
log4jLogger.warn(message);
}
@Override
public void severe(String message) {
logger.error(message);
log4jLogger.error(message);
}
};
private final DebugLogger debugLogger = new DebugLogger(logger);
private final ItemHandle itemHandle = new FabricItemHandle();
private final WorldHandle worldHandle = new FabricWorldHandle();
private final ConfigRegistry registry = new ConfigRegistry();
private final CheckedRegistry<ConfigPack> checkedRegistry = new CheckedRegistry<>(registry);
private final AddonRegistry addonRegistry = new AddonRegistry(new FabricAddon(this), this);
private final FabricAddon fabricAddon = new FabricAddon(this);
private final AddonRegistry addonRegistry = new AddonRegistry(fabricAddon, this);
private final LockedRegistry<TerraAddon> addonLockedRegistry = new LockedRegistry<>(addonRegistry);
private final PluginConfig config = new PluginConfig();
private final DimensionConfig dimensionConfig = new DimensionConfig();
private final Transformer<String, Biome> biomeFixer = new Transformer.Builder<String, Biome>()
.addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse(id)), new NotNullValidator<>())
.addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse("minecraft:" + id.toLowerCase())), new NotNullValidator<>()).build();
.addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse(id)), Validator.notNull())
.addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse("minecraft:" + id.toLowerCase())), Validator.notNull()).build();
private File dataFolder;
private final CommandManager manager = new TerraCommandManager(this);
public CommandManager getManager() {
return manager;
}
public static TerraFabricPlugin getInstance() {
return instance;
}
public static String createBiomeID(ConfigPack pack, String biomeID) {
return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT);
}
@Override
public WorldHandle getWorldHandle() {
return worldHandle;
@@ -151,10 +148,13 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
@Override
public TerraWorld getWorld(World world) {
return worldMap.computeIfAbsent(world.getSeed(), w -> {
logger.info("Loading world " + w);
return new TerraWorld(world, ((FabricChunkGeneratorWrapper) ((FabricChunkGenerator) world.getGenerator()).getHandle()).getPack(), this);
});
return getWorld(((WorldAccess) world).getDimension());
}
public TerraWorld getWorld(DimensionType type) {
TerraWorld world = worldMap.get(type).getRight();
if(world == null) throw new IllegalArgumentException("No world exists with dimension type " + type);
return world;
}
@Override
@@ -174,7 +174,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
@Override
public boolean isDebug() {
return true;
return config.isDebug();
}
@Override
@@ -197,14 +197,11 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
config.load(this);
LangUtil.load(config.getLanguage(), this); // Load language.
boolean succeed = registry.loadAll(this);
Map<Long, TerraWorld> newMap = new HashMap<>();
worldMap.forEach((seed, tw) -> {
tw.getConfig().getSamplerCache().clear();
String packID = tw.getConfig().getTemplate().getID();
newMap.put(seed, new TerraWorld(tw.getWorld(), registry.get(packID), this));
worldMap.forEach((seed, pair) -> {
pair.getRight().getConfig().getSamplerCache().clear();
String packID = pair.getRight().getConfig().getTemplate().getID();
pair.setRight(new TerraWorld(pair.getRight().getWorld(), registry.get(packID), this));
});
worldMap.clear();
worldMap.putAll(newMap);
return succeed;
}
@@ -238,54 +235,33 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
genericLoaders.register(registry);
registry
.registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o))
.registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> new FabricBiome(biomeFixer.translate((String) o)));
.registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> biomeFixer.translate((String) o))
.registerLoader(Identifier.class, (t, o, l) -> {
Identifier identifier = Identifier.tryParse((String) o);
if(identifier == null) throw new LoadException("Invalid identifier: " + o);
return identifier;
});
}
private Biome createBiome(BiomeBuilder biome) {
SpawnSettings.Builder spawnSettings = new SpawnSettings.Builder();
DefaultBiomeFeatures.addFarmAnimals(spawnSettings);
DefaultBiomeFeatures.addMonsters(spawnSettings, 95, 5, 100);
public void packInit() {
logger.info("Loading config packs...");
registry.loadAll(this);
BiomeTemplate template = biome.getTemplate();
Map<String, Integer> colors = template.getColors();
registry.forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> Registry.register(BuiltinRegistries.BIOME, new Identifier("terra", FabricUtil.createBiomeID(pack, id)), FabricUtil.createBiome(fabricAddon, biome, pack)))); // Register all Terra biomes.
Biome vanilla = ((FabricBiome) new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle();
GenerationSettings.Builder generationSettings = new GenerationSettings.Builder();
generationSettings.surfaceBuilder(SurfaceBuilder.DEFAULT.withConfig(new TernarySurfaceConfig(Blocks.GRASS_BLOCK.getDefaultState(), Blocks.DIRT.getDefaultState(), Blocks.GRAVEL.getDefaultState()))); // It needs a surfacebuilder, even though we dont use it.
generationSettings.feature(GenerationStep.Feature.VEGETAL_DECORATION, POPULATOR_CONFIGURED_FEATURE);
BiomeEffects.Builder effects = new BiomeEffects.Builder()
.waterColor(colors.getOrDefault("water", vanilla.getEffects().waterColor))
.waterFogColor(colors.getOrDefault("water-fog", vanilla.getEffects().waterFogColor))
.fogColor(colors.getOrDefault("fog", vanilla.getEffects().fogColor))
.skyColor(colors.getOrDefault("sky", vanilla.getEffects().skyColor))
.grassColorModifier(vanilla.getEffects().grassColorModifier);
if(colors.containsKey("grass")) {
effects.grassColor(colors.get("grass"));
} else {
vanilla.getEffects().grassColor.ifPresent(effects::grassColor);
}
vanilla.getEffects().foliageColor.ifPresent(effects::foliageColor);
if(colors.containsKey("foliage")) {
effects.foliageColor(colors.get("foliage"));
} else {
vanilla.getEffects().foliageColor.ifPresent(effects::foliageColor);
File configFile = new File(getDataFolder(), "config.yml");
ConfigLoader loader = new ConfigLoader();
loader.registerLoader(ConfigPack.class, registry);
register(loader);
try {
logger.info("Loading dimension config...");
loader.load(dimensionConfig, new FileInputStream(configFile));
logger.info("Loaded " + dimensionConfig.getDimensionPacks().size() + " dimension overrides.");
} catch(ConfigException | FileNotFoundException e) {
throw new RuntimeException("Failed to load dimension config", e);
}
return new Biome.Builder()
.precipitation(vanilla.getPrecipitation())
.category(vanilla.getCategory())
.depth(vanilla.getDepth())
.scale(vanilla.getScale())
.temperature(vanilla.getTemperature())
.downfall(vanilla.getDownfall())
.effects(effects.build())
.spawnSettings(spawnSettings.build())
.generationSettings(generationSettings.build())
.build();
logger.info("Loaded packs.");
}
@Override
@@ -295,6 +271,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
this.dataFolder = new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra");
saveDefaultConfig();
config.load(this);
debugLogger.setDebug(config.isDebug());
LangUtil.load(config.getLanguage(), this);
logger.info("Initializing Terra...");
@@ -303,84 +280,21 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
}
logger.info("Loaded addons.");
registry.loadAll(this);
logger.info("Loaded packs.");
Registry.register(Registry.FEATURE, new Identifier("terra", "flora_populator"), POPULATOR_FEATURE);
RegistryKey<ConfiguredFeature<?, ?>> floraKey = RegistryKey.of(Registry.CONFIGURED_FEATURE_WORLDGEN, new Identifier("terra", "flora_populator"));
Registry.register(Registry.FEATURE, new Identifier("terra", "populator"), POPULATOR_FEATURE);
RegistryKey<ConfiguredFeature<?, ?>> floraKey = RegistryKey.of(Registry.CONFIGURED_FEATURE_WORLDGEN, new Identifier("terra", "populator"));
Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, floraKey.getValue(), POPULATOR_CONFIGURED_FEATURE);
registry.forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> Registry.register(BuiltinRegistries.BIOME, new Identifier("terra", createBiomeID(pack, id)), createBiome(biome)))); // Register all Terra biomes.
Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), FabricChunkGeneratorWrapper.CODEC);
Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC);
if(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
registry.forEach(pack -> {
final GeneratorType generatorType = new GeneratorType("terra." + pack.getTemplate().getID()) {
@Override
protected ChunkGenerator getChunkGenerator(Registry<Biome> biomeRegistry, Registry<ChunkGeneratorSettings> chunkGeneratorSettingsRegistry, long seed) {
return new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack);
}
};
//noinspection ConstantConditions
((GeneratorTypeAccessor) generatorType).setTranslationKey(new LiteralText("Terra:" + pack.getTemplate().getID()));
GeneratorTypeAccessor.getVALUES().add(generatorType);
});
}
CommandManager manager = new TerraCommandManager(this);
try {
CommandUtil.registerAll(manager);
} catch(MalformedCommandException e) {
e.printStackTrace(); // TODO do something here even though this should literally never happen
}
CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> {
int max = manager.getMaxArgumentDepth();
RequiredArgumentBuilder<ServerCommandSource, String> arg = argument("arg" + (max - 1), StringArgumentType.word());
for(int i = 0; i < max; i++) {
RequiredArgumentBuilder<ServerCommandSource, String> next = argument("arg" + (max - i - 1), StringArgumentType.word());
arg = next.then(assemble(arg, manager));
}
dispatcher.register(literal("terra").executes(context -> 1).then(assemble(arg, manager)));
dispatcher.register(literal("te").executes(context -> 1).then(assemble(arg, manager)));
//dispatcher.register(literal("te").redirect(root));
}
);
}
private RequiredArgumentBuilder<ServerCommandSource, String> assemble(RequiredArgumentBuilder<ServerCommandSource, String> in, CommandManager manager) {
return in.suggests((context, builder) -> {
List<String> args = parseCommand(context.getInput());
CommandSender sender = FabricAdapter.adapt(context.getSource());
try {
manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest);
} catch(CommandException e) {
sender.sendMessage(e.getMessage());
}
return builder.buildFuture();
}).executes(context -> {
List<String> args = parseCommand(context.getInput());
try {
manager.execute(args.remove(0), FabricAdapter.adapt(context.getSource()), args);
} catch(CommandException e) {
context.getSource().sendError(new LiteralText(e.getMessage()));
}
return 1;
});
}
private List<String> parseCommand(String command) {
if(command.startsWith("/terra ")) command = command.substring("/terra ".length());
else if(command.startsWith("/te ")) command = command.substring("/te ".length());
List<String> c = new ArrayList<>(Arrays.asList(command.split(" ")));
if(command.endsWith(" ")) c.add("");
return c;
logger.info("Finished initialization.");
}
@@ -389,13 +303,20 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
return eventManager;
}
@Override
public Profiler getProfiler() {
return profiler;
}
@Addon("Terra-Fabric")
@Author("Terra")
@Version("1.0.0")
private static final class FabricAddon extends TerraAddon implements EventListener {
public static final class FabricAddon extends TerraAddon implements EventListener {
private final TerraPlugin main;
private final Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> templates = new HashMap<>();
private FabricAddon(TerraPlugin main) {
this.main = main;
}
@@ -428,14 +349,52 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
injectTree(treeRegistry, "MEGA_SPRUCE", ConfiguredFeatures.MEGA_SPRUCE);
injectTree(treeRegistry, "CRIMSON_FUNGUS", ConfiguredFeatures.CRIMSON_FUNGI);
injectTree(treeRegistry, "WARPED_FUNGUS", ConfiguredFeatures.WARPED_FUNGI);
PreLoadCompatibilityOptions template = new PreLoadCompatibilityOptions();
try {
event.loadTemplate(template);
} catch(ConfigException e) {
e.printStackTrace();
}
if(template.doRegistryInjection()) {
BuiltinRegistries.CONFIGURED_FEATURE.getEntries().forEach(entry -> {
if(!template.getExcludedRegistryFeatures().contains(entry.getKey().getValue())) {
try {
event.getPack().getTreeRegistry().add(entry.getKey().getValue().toString(), (Tree) entry.getValue());
main.getDebugLogger().info("Injected ConfiguredFeature " + entry.getKey().getValue() + " as Tree.");
} catch(DuplicateEntryException ignored) {
}
}
});
}
templates.put(event.getPack(), Pair.of(template, null));
}
@Priority(Priority.HIGHEST)
@Global
public void createInjectionOptions(ConfigPackPostLoadEvent event) {
PostLoadCompatibilityOptions template = new PostLoadCompatibilityOptions();
try {
event.loadTemplate(template);
} catch(ConfigException e) {
e.printStackTrace();
}
templates.get(event.getPack()).setRight(template);
}
private void injectTree(CheckedRegistry<Tree> registry, String id, ConfiguredFeature<?, ?> tree) {
try {
registry.add(id, new FabricTree(tree));
registry.add(id, (Tree) tree);
} catch(DuplicateEntryException ignore) {
}
}
public Map<ConfigPack, Pair<PreLoadCompatibilityOptions, PostLoadCompatibilityOptions>> getTemplates() {
return templates;
}
}
}
@@ -1,4 +1,4 @@
package com.dfsek.terra.fabric.world.block;
package com.dfsek.terra.fabric.block;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
@@ -6,9 +6,9 @@ import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.BlockType;
import com.dfsek.terra.api.platform.block.state.BlockState;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.block.state.FabricBlockState;
import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.fabric.util.FabricAdapter;
import net.minecraft.block.FluidBlock;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.WorldAccess;
@@ -21,7 +21,10 @@ public class FabricBlock implements Block {
@Override
public void setBlockData(BlockData data, boolean physics) {
delegate.worldAccess.setBlockState(delegate.position, ((FabricBlockData) data).getHandle(), physics ? 3 : 1042, 0);
delegate.worldAccess.setBlockState(delegate.position, ((FabricBlockData) data).getHandle(), physics ? 3 : 1042);
if(physics && ((FabricBlockData) data).getHandle().getBlock() instanceof FluidBlock) {
delegate.worldAccess.getFluidTickScheduler().schedule(delegate.position, ((FluidBlock) ((FabricBlockData) data).getHandle().getBlock()).getFluidState(((FabricBlockData) data).getHandle()).getFluid(), 0);
}
}
@Override
@@ -31,7 +34,7 @@ public class FabricBlock implements Block {
@Override
public BlockState getState() {
return FabricBlockState.newInstance(this);
return FabricAdapter.adapt(this);
}
@Override
@@ -47,7 +50,7 @@ public class FabricBlock implements Block {
@Override
public Location getLocation() {
return FabricAdapter.adapt(delegate.position).toLocation(new FabricWorldAccess(delegate.worldAccess));
return FabricAdapter.adapt(delegate.position).toLocation((World) delegate.worldAccess);
}
@Override
@@ -1,11 +1,10 @@
package com.dfsek.terra.fabric.world.block;
package com.dfsek.terra.fabric.block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockType;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.mixin.access.StateAccessor;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.state.State;
import net.minecraft.util.registry.Registry;
import java.util.stream.Collectors;
@@ -19,7 +18,7 @@ public class FabricBlockData implements BlockData {
@Override
public BlockType getBlockType() {
return FabricAdapter.adapt(delegate.getBlock());
return (BlockType) delegate.getBlock();
}
@Override
@@ -41,7 +40,7 @@ public class FabricBlockData implements BlockData {
StringBuilder data = new StringBuilder(Registry.BLOCK.getId(delegate.getBlock()).toString());
if(!delegate.getEntries().isEmpty()) {
data.append('[');
data.append(delegate.getEntries().entrySet().stream().map(State.PROPERTY_MAP_PRINTER).collect(Collectors.joining(",")));
data.append(delegate.getEntries().entrySet().stream().map(StateAccessor.getPropertyMapPrinter()).collect(Collectors.joining(",")));
data.append(']');
}
return data.toString();
@@ -1,7 +1,7 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.data.AnaloguePowerable;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
/**
@@ -1,9 +1,9 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.data.Directional;
import com.dfsek.terra.fabric.world.FabricAdapter;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import com.dfsek.terra.fabric.util.FabricAdapter;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.DirectionProperty;
@@ -1,8 +1,8 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.data.MultipleFacing;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;
@@ -1,8 +1,9 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.Axis;
import com.dfsek.terra.api.platform.block.data.Orientable;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import com.dfsek.terra.fabric.util.FabricAdapter;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.util.math.Direction;
@@ -26,11 +27,11 @@ public class FabricOrientable extends FabricBlockData implements Orientable {
@Override
public Axis getAxis() {
return FabricEnumAdapter.adapt(getHandle().get(property));
return FabricAdapter.adapt(getHandle().get(property));
}
@Override
public void setAxis(Axis axis) {
delegate = delegate.with(property, FabricEnumAdapter.adapt(axis));
delegate = delegate.with(property, FabricAdapter.adapt(axis));
}
}
@@ -1,8 +1,8 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.data.Rotatable;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;
@@ -1,6 +1,7 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.data.Slab;
import com.dfsek.terra.fabric.util.FabricAdapter;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;
@@ -11,11 +12,11 @@ public class FabricSlab extends FabricWaterlogged implements Slab {
@Override
public Type getType() {
return FabricEnumAdapter.adapt(delegate.get(Properties.SLAB_TYPE));
return FabricAdapter.adapt(delegate.get(Properties.SLAB_TYPE));
}
@Override
public void setType(Type type) {
delegate = delegate.with(Properties.SLAB_TYPE, FabricEnumAdapter.adapt(type));
delegate = delegate.with(Properties.SLAB_TYPE, FabricAdapter.adapt(type));
}
}
@@ -1,7 +1,8 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.data.Stairs;
import com.dfsek.terra.fabric.util.FabricAdapter;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;
@@ -12,31 +13,31 @@ public class FabricStairs extends FabricWaterlogged implements Stairs {
@Override
public Shape getShape() {
return FabricEnumAdapter.adapt(getHandle().get(Properties.STAIR_SHAPE));
return FabricAdapter.adapt(getHandle().get(Properties.STAIR_SHAPE));
}
@Override
public void setShape(Shape shape) {
super.delegate = getHandle().with(Properties.STAIR_SHAPE, FabricEnumAdapter.adapt(shape));
super.delegate = getHandle().with(Properties.STAIR_SHAPE, FabricAdapter.adapt(shape));
}
@Override
public Half getHalf() {
return FabricEnumAdapter.adapt(getHandle().get(Properties.BLOCK_HALF));
return FabricAdapter.adapt(getHandle().get(Properties.BLOCK_HALF));
}
@Override
public void setHalf(Half half) {
super.delegate = getHandle().with(Properties.BLOCK_HALF, FabricEnumAdapter.adapt(half));
super.delegate = getHandle().with(Properties.BLOCK_HALF, FabricAdapter.adapt(half));
}
@Override
public BlockFace getFacing() {
return FabricEnumAdapter.adapt(getHandle().get(Properties.HORIZONTAL_FACING));
return FabricAdapter.adapt(getHandle().get(Properties.HORIZONTAL_FACING));
}
@Override
public void setFacing(BlockFace facing) {
super.delegate = getHandle().with(Properties.HORIZONTAL_FACING, FabricEnumAdapter.adapt(facing));
super.delegate = getHandle().with(Properties.HORIZONTAL_FACING, FabricAdapter.adapt(facing));
}
}
@@ -1,7 +1,7 @@
package com.dfsek.terra.fabric.world.block.data;
package com.dfsek.terra.fabric.block.data;
import com.dfsek.terra.api.platform.block.data.Waterlogged;
import com.dfsek.terra.fabric.world.block.FabricBlockData;
import com.dfsek.terra.fabric.block.FabricBlockData;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Properties;
@@ -1,7 +0,0 @@
package com.dfsek.terra.fabric.command;
public class FabricCommandAdapter {
public static void register() {
}
}
@@ -1,17 +0,0 @@
package com.dfsek.terra.fabric.command;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class StringListArgumentType implements ArgumentType<List<String>> {
@Override
public List<String> parse(StringReader reader) {
final String text = reader.getRemaining();
reader.setCursor(reader.getTotalLength());
return new ArrayList<>(Arrays.asList(text.split(" ")));
}
}
@@ -0,0 +1,21 @@
package com.dfsek.terra.fabric.config;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.config.pack.ConfigPack;
import net.minecraft.util.Identifier;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("FieldMayBeFinal")
public class DimensionConfig implements ConfigTemplate {
@Value("dimensions")
@Default
private Map<Identifier, ConfigPack> dimensionPacks = new HashMap<>();
public Map<Identifier, ConfigPack> getDimensionPacks() {
return dimensionPacks;
}
}
@@ -0,0 +1,30 @@
package com.dfsek.terra.fabric.config;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.config.builder.BiomeBuilder;
import net.minecraft.util.Identifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@SuppressWarnings("FieldMayBeFinal")
public class PostLoadCompatibilityOptions implements ConfigTemplate {
@Value("structures.inject-biome.exclude-biomes")
@Default
private Map<BiomeBuilder, Set<Identifier>> excludedPerBiomeStructures = new HashMap<>();
@Value("features.inject-biome.exclude-biomes")
@Default
private Map<BiomeBuilder, Set<Identifier>> excludedPerBiomeFeatures = new HashMap<>();
public Map<BiomeBuilder, Set<Identifier>> getExcludedPerBiomeFeatures() {
return excludedPerBiomeFeatures;
}
public Map<BiomeBuilder, Set<Identifier>> getExcludedPerBiomeStructures() {
return excludedPerBiomeStructures;
}
}
@@ -0,0 +1,52 @@
package com.dfsek.terra.fabric.config;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import net.minecraft.util.Identifier;
import java.util.HashSet;
import java.util.Set;
@SuppressWarnings("FieldMayBeFinal")
public class PreLoadCompatibilityOptions implements ConfigTemplate {
@Value("features.inject-registry.enable")
@Default
private boolean doRegistryInjection = false;
@Value("features.inject-biome.enable")
@Default
private boolean doBiomeInjection = false;
@Value("features.inject-registry.excluded-features")
@Default
private Set<Identifier> excludedRegistryFeatures = new HashSet<>();
@Value("features.inject-biome.excluded-features")
@Default
private Set<Identifier> excludedBiomeFeatures = new HashSet<>();
@Value("structures.inject-biome.excluded-features")
@Default
private Set<Identifier> excludedBiomeStructures = new HashSet<>();
public boolean doBiomeInjection() {
return doBiomeInjection;
}
public boolean doRegistryInjection() {
return doRegistryInjection;
}
public Set<Identifier> getExcludedBiomeFeatures() {
return excludedBiomeFeatures;
}
public Set<Identifier> getExcludedRegistryFeatures() {
return excludedRegistryFeatures;
}
public Set<Identifier> getExcludedBiomeStructures() {
return excludedBiomeStructures;
}
}

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