mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-05-20 08:40:26 +00:00
Compare commits
221 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eca46a7c64 | |||
| 74fdf9a18e | |||
| c0f1ccb66a | |||
| 44410323af | |||
| aaf32709b4 | |||
| c1c2ab6df8 | |||
| fa164e5281 | |||
| ec3b0e5d04 | |||
| 4c63c2681f | |||
| dd661feaf1 | |||
| 1f17bfff1b | |||
| 809a0b375d | |||
| d55b3415ac | |||
| edcb818842 | |||
| 1e429e1bb3 | |||
| 3472859afb | |||
| 26025ec276 | |||
| 3b3905b513 | |||
| ce3d09cf2e | |||
| 5dd00db8d2 | |||
| 2dc7b50141 | |||
| b2ebcc63aa | |||
| f45bc0a0cc | |||
| bbe53cbca3 | |||
| 7354155c52 | |||
| c1acfee910 | |||
| 5287323865 | |||
| b09d0e42aa | |||
| a3f14061dd | |||
| 557098de17 | |||
| 2fdb96a850 | |||
| d93d064d97 | |||
| ae76fb7dc4 | |||
| 2626afd066 | |||
| c0042cfb6b | |||
| a549d2ef34 | |||
| 4aa20c32b8 | |||
| ce7033b4ca | |||
| 41a54f4b25 | |||
| f96740f1fa | |||
| 8844cd5069 | |||
| 800d846af4 | |||
| 95d50a0391 | |||
| 5a83eab1fe | |||
| bac026a1f4 | |||
| 65482c493a | |||
| a05f837ca2 | |||
| 6fbb5d712e | |||
| 2c9d195474 | |||
| b663d34320 | |||
| 43095d0df1 | |||
| 47e0dc862c | |||
| 460b11b9c8 | |||
| d974a72cb9 | |||
| e86f37fdfb | |||
| 2ed120dc4c | |||
| 973ae785f4 | |||
| 4835813e2e | |||
| 632409050b | |||
| 9d991dbb97 | |||
| cddf7c20e4 | |||
| 5fd2fc59f4 | |||
| 97d7ccacbf | |||
| 242e56b1d8 | |||
| 4c7aa11353 | |||
| cac84ffe03 | |||
| cf66e1e226 | |||
| fa647e1e2c | |||
| 4203121d40 | |||
| 82fe6d5aa4 | |||
| 32db83f091 | |||
| 0ab949174a | |||
| 2bfaa95a81 | |||
| 96de1554f1 | |||
| f83dcd802c | |||
| 808aa50f5f | |||
| e00271e493 | |||
| 76bf245e16 | |||
| 37e441206a | |||
| 5376f7e22e | |||
| 1186fc6624 | |||
| a1b3680643 | |||
| 501399919f | |||
| 725d57d967 | |||
| a821501392 | |||
| d3458148bd | |||
| df4da810ec | |||
| 8f47c84c8e | |||
| f61a544a57 | |||
| 3217d66c69 | |||
| fd48f5f110 | |||
| 77a4c95c4a | |||
| dbc60b1d82 | |||
| ed942bb997 | |||
| 6866084872 | |||
| 4c77419dcd | |||
| ecba6e0843 | |||
| 86dcb476f1 | |||
| 13e0857882 | |||
| bf93a9239c | |||
| 2d18aab709 | |||
| a1359da374 | |||
| f7bda835f9 | |||
| 7595896831 | |||
| 6614d19845 | |||
| 6209b86560 | |||
| a30859a3d4 | |||
| ddbb46289b | |||
| 64c35a9609 | |||
| f21069ab2e | |||
| 457729b832 | |||
| 756f04a0b3 | |||
| 5ee32cc3ba | |||
| 955558bc21 | |||
| c43a872c23 | |||
| de41b92d5d | |||
| 03091230ed | |||
| a8c88915ea | |||
| 4cd4720101 | |||
| 3b9280b19c | |||
| 2d27e07441 | |||
| 20a5762d2e | |||
| 146f71f704 | |||
| 1d4b0bc100 | |||
| 138ee0a448 | |||
| 2c8cae9d45 | |||
| 061d2b6493 | |||
| e71df936ab | |||
| f4253acb78 | |||
| c12518fa49 | |||
| 4704b2ebf7 | |||
| 89fdfdfb34 | |||
| 35d85f2aa3 | |||
| c0368f1c6d | |||
| abc069046c | |||
| 46d0b08068 | |||
| a7e3a0286e | |||
| 6da8924868 | |||
| d9dd6afe4b | |||
| dfec26f789 | |||
| d13be5e159 | |||
| 51c5f70d64 | |||
| 05b1902c06 | |||
| f4ae2cac68 | |||
| ea3995afce | |||
| c41d60c38f | |||
| 19edcbddd5 | |||
| 4f65555e82 | |||
| 9956cab507 | |||
| fddf0c51b7 | |||
| e2a52afb67 | |||
| c8c3a33912 | |||
| b178f69e47 | |||
| 049a56fcb0 | |||
| 2d41dd8f08 | |||
| aa9e33af1d | |||
| 02870805c7 | |||
| e493825ab7 | |||
| 762b248641 | |||
| f81ccee020 | |||
| 3561e5f30f | |||
| c67817b9d2 | |||
| 756619edb6 | |||
| ee1c889d54 | |||
| 9f3dcf07b6 | |||
| 93a2f103f7 | |||
| 3ea12ceeab | |||
| ce8ec51ae4 | |||
| 54bb4ef109 | |||
| 59b655ce5d | |||
| 4c1e1bb7d5 | |||
| eee54f507e | |||
| 6f1b1611ab | |||
| 205499220d | |||
| a0c5631eba | |||
| 9323abc788 | |||
| 632f898dc8 | |||
| 8737b0d984 | |||
| bcb68853d5 | |||
| 8823d6d65e | |||
| 5d3a2b6e84 | |||
| 23fb7753ab | |||
| f8e7e343cb | |||
| e5f4c5dc8d | |||
| 8a10867e5f | |||
| da366a75e8 | |||
| eb4bf74cc6 | |||
| 168c0ced13 | |||
| 5d4bdb431b | |||
| 40188c671f | |||
| f396e0e5eb | |||
| 942a8c9c8b | |||
| 414dcdae3e | |||
| 1195a6676f | |||
| 5501f53056 | |||
| 41d6e1c648 | |||
| 5ac7257517 | |||
| 9f4f9702a6 | |||
| 01d169256e | |||
| 7a703ad091 | |||
| ce9273c7e8 | |||
| 653a414ac1 | |||
| 2080db21ca | |||
| 8a933609ee | |||
| ba4a50e234 | |||
| f8e8ce8bc2 | |||
| 0013d4e682 | |||
| 9a97f1178d | |||
| e6a551d84d | |||
| 92921430d8 | |||
| 20c905aae4 | |||
| ec0730ef73 | |||
| e4576b3405 | |||
| c5800970a8 | |||
| 8f88b1c156 | |||
| 1360994a67 | |||
| e00b28d27e | |||
| c5ff5c101d | |||
| b1a1001c49 | |||
| 77d5162e73 | |||
| 2e8cd54ac2 |
+1
-1
@@ -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
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Global owners, automatically request review when pull request is submitted
|
||||
* @dfsek @solonovamax
|
||||
|
||||
# Platforms
|
||||
## dfsek wrote the majority of the platform impls
|
||||
/platforms/bukkit/ @dfsek
|
||||
/platforms/fabric/ @dfsek
|
||||
/platforms/forge/ @dfsek
|
||||
/platforms/sponge/ @dfsek
|
||||
## solonovamax is working on the region generator (unless duplexsystem takes it over)
|
||||
/platforms/region/ @solonovamax
|
||||
|
||||
# Common
|
||||
/common/ @dfsek @solonovamax
|
||||
|
||||
# Gradle Stuff
|
||||
## Most gradle stuff was written by solonovamax
|
||||
/buildSrc/ @solonovamax
|
||||
*.gradle.kts @solonovamax
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
name: "Bug Report"
|
||||
about: "Open a bug report to help us identify issues with Terra."
|
||||
title: "[Bug] <Put your title here>"
|
||||
labels: "Type: Bug, Status: Pending"
|
||||
assignees: ""
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
##############################################################################
|
||||
## WARNING! ##
|
||||
## IGNORING THE FOLLOWING TEMPLATE WILL RESULT IN YOUR ISSUE BEING CLOSED ##
|
||||
##############################################################################
|
||||
-->
|
||||
|
||||
## Pre-Issue Checklist
|
||||
|
||||
<!--
|
||||
Please go through this checklist item by item and make sure you have successfully completed each of these steps.
|
||||
- You must be on the LATEST version of Terra to receive any support. There is no support for older versions of Terra.
|
||||
- Make sure that this is not a *specific* compatibility issue with another terrain generation mod.
|
||||
Do not request *specific* compatibility with mods or plugins (e.g. "Compatibility with TechCraft v7").
|
||||
That should be implemented in an addon, **not** in the main project.
|
||||
*General* compatibility (e.g. "Ability to pull Vanilla/Modded features from parent biomes") will be considered in the main project.
|
||||
- Make sure that there are no already existing issues open with your problem. If you open a duplicate, it will be closed as such.
|
||||
- Make sure that it is actually Terra causing the issue, and not another mod/plugin.
|
||||
You can do this by testing to see if you can recreate the issue without Terra installed.
|
||||
- Make sure that this is not an issue with a specific Terra *pack* or Terra *addon*, and instead applies to all of Terra.
|
||||
- Make sure that you attach a copy of the latest.log file.
|
||||
Putting *just* the exception IS NOT ENOUGH. We need to be able to check that there wasn't anything else before that caused it.
|
||||
- Make sure that you have filled out all the required information and given descriptions of everything.
|
||||
|
||||
You must put an x in all the boxes you have completed. (Like this: [x])
|
||||
|
||||
To make sure that your issue is rendered properly, you may check the "Preview" tab (below the title) to see a rendered version of it before you submit it.
|
||||
-->
|
||||
|
||||
- [ ] I have checked that I am on the latest version of Terra.
|
||||
- [ ] I have searched the github issue tracker for similar issues, including closed ones.
|
||||
- [ ] I have made sure that this is not a bug with another mod or plugin, and it is Terra that is causing the issue.
|
||||
- [ ] I have checked that this is an issue with Terra and not an issue with the pack I am using.
|
||||
<!-- If this is an issue with the default Terra pack, please open an issue on the pack repo: https://github.com/PolyhedralDev/TerraDefaultConfig/issues/new -->
|
||||
- [ ] I have attached a copy of the `latest.log` file
|
||||
- [ ] I have filled out and provided all the appropriate information.
|
||||
|
||||
## Environment
|
||||
|
||||
<!-- You can fill out the different items by putting the correct value beside each cell. -->
|
||||
|
||||
| Name | Value |
|
||||
|------------------------------|-------|
|
||||
| Terra Version | <!-- Put your Terra version here. (remove the comment) -->
|
||||
| Platform / Platform Version | <!-- Put your platform and platform version here. (remove the comment) (eg. Spigot, Fabric, Paper, etc.) (If you are using the Region generator, put that here instead) -->
|
||||
| Any External Plugins or Mods | <!-- Put a list of all the plugins or mods you have installed here. (remove the comment) (Make sure to NOT include any new lines) -->
|
||||
| Terra Packs In Use | <!-- Put a list of all the Terra packs you have installed here. (remove the comment) (Make sure to NOT include any new lines) (/te packs may be used to get a list) -->
|
||||
| Terra Addons In Use | <!-- Put a list of all the Terra addons you have installed here. (remove the comment) (Make sure to NOT include any new lines) (/te addons may be used to get a list) -->
|
||||
|
||||
## Issue Description
|
||||
|
||||
<!--
|
||||
Put a quick description of the issue here.
|
||||
Example: 'When generating terrain, something causes the chunks to not load properly', etc.
|
||||
-->
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
<!--
|
||||
Describe what you were doing when this happened.
|
||||
Make sure to include ALL information. Including anything you were doing before that may have caused it.
|
||||
-->
|
||||
|
||||
1. <!-- Put step #1 here. -->
|
||||
2. <!-- Put step #2 here. -->
|
||||
3. <!-- etc. -->
|
||||
|
||||
### Expected behavior
|
||||
|
||||
<!-- Describe what you think *should* happen here: -->
|
||||
|
||||
### Actual behavior
|
||||
|
||||
<!-- Describe what *actually* happens here: -->
|
||||
<!-- example: When I do _______, it actually does _______ -->
|
||||
|
||||
### Full stacktrace
|
||||
|
||||
<details>
|
||||
<summary>Exception Stacktrace</summary>
|
||||
|
||||
<!--
|
||||
If Terra logs an exception, please put it in the following section: (You will find any error logs in your console, or your latest.log)
|
||||
Note: this *must* be included, in ADDITION to the latest.log file.
|
||||
-->
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Additional details
|
||||
|
||||
<!-- Any other information you think should be added -->
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
name: "Feature Request"
|
||||
about: "Give us suggestions of features we could add to Terra."
|
||||
title: "[Feature] <Put your title here>"
|
||||
labels: "Type: Enhancement, Status: Pending"
|
||||
assignees: ""
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
########################################################################################
|
||||
## WARNING! ##
|
||||
## IGNORING THE FOLLOWING TEMPLATE WILL RESULT IN YOUR FEATURE REQUEST BEING CLOSED ##
|
||||
########################################################################################
|
||||
-->
|
||||
|
||||
### Pre-Request Checklist
|
||||
|
||||
<!--
|
||||
Please go through this checklist item by item and make sure you have successfully completed each of these steps.
|
||||
- You must be on the LATEST version of Terra to make sure your feature hasn't been added yet.
|
||||
- Make sure that there are no already existing feature requests similar to yours. (Including closed!) If you open a duplicate, it will be closed as such.
|
||||
- Make sure that this is actually in the scope of Terra.
|
||||
- Make sure that this is not a feature request that should be made for a specific Terra *pack*, and instead applies to all of Terra.
|
||||
- Make sure that you attach a copy of the latest.log file, if there are any exceptions thrown in the console.
|
||||
Putting *just* the exception IS NOT ENOUGH. We need to be able to check that there wasn't anything else before that caused it.
|
||||
|
||||
You must put an x in all the boxes you have completed. (Like this: [x])
|
||||
|
||||
To make sure that your issue is rendered properly, you may check the "Preview" tab (below the title) to see a rendered version of it before you submit it.
|
||||
-->
|
||||
|
||||
- [ ] I have checked that I am on the latest version of Terra.
|
||||
- [ ] I have searched github for similar features requests, including closed ones, and found none.
|
||||
- [ ] I believe this is within the scope of Terra.
|
||||
- [ ] This feature request is for *all* of Terra, and isn't something that should be implemented by a pack or addon.
|
||||
|
||||
## Feature Description
|
||||
|
||||
<!--
|
||||
Quickly describe the basics of your feature request.
|
||||
Example: 'More noise presets should be added to Terra.'
|
||||
-->
|
||||
|
||||
### What Problem Does This Solve?
|
||||
|
||||
<!--
|
||||
Describe here what the issue is that you have.
|
||||
Examples: 'When I do _______, it annoys me that _______ does _______.' or 'There is not enough customization in _______ to do _______.'
|
||||
NOTE: This should NOT be used for a bug report. If this is unintentional, then please submit a bug report instead.
|
||||
-->
|
||||
|
||||
### A Solution You'd Like
|
||||
|
||||
<!-- Provide a clear and accurate description of how you would like this to be solved. -->
|
||||
|
||||
### Alternative Solutions
|
||||
|
||||
<!-- Provide a description of alternatives you have considered to this. -->
|
||||
|
||||
1. <!-- Alternative #1. -->
|
||||
2. <!-- Alternative #2. -->
|
||||
3. <!-- Alternative #3. -->
|
||||
|
||||
### Additonal Context
|
||||
|
||||
<!--
|
||||
Is there any additional context you would like to add?
|
||||
If not, you may remove this section.
|
||||
-->
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
name: "Other Issue"
|
||||
about: "Use this template if your issue doesn't accurately fit into any of the other categories."
|
||||
title: ""
|
||||
labels: "Type: Question, Status: Pending"
|
||||
assignees: ""
|
||||
|
||||
---
|
||||
|
||||
## Describe the issue
|
||||
<!-- Please describe the issue as clearly and as concisely as possible, without missing any details. -->
|
||||
@@ -0,0 +1,11 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Which Issue Template do I Choose?
|
||||
url: https://github.com/PolyhedralDev/Terra/wiki/How-To-Choose-An-Issue-Template
|
||||
about: Click this if you don't know which issue template to select. This will help you make sure you choose the right one and provide enough information for us to help you.
|
||||
- name: Terra Wiki
|
||||
url: https://github.com/PolyhedralDev/Terra/wiki
|
||||
about: Documentation for all things Terra.
|
||||
- name: Join the Support Discord
|
||||
url: https://discord.dfsek.com
|
||||
about: If you have a basic support question, join the Discord instead.
|
||||
@@ -0,0 +1,114 @@
|
||||
# Pull Request
|
||||
|
||||
## Brief description.
|
||||
|
||||
<!-- Please provide a brief description of the goals of your PR -->
|
||||
|
||||
<!--
|
||||
###########################################################################
|
||||
## WARNING! ##
|
||||
## IGNORING THE FOLLOWING TEMPLATE WILL RESULT IN YOUR PR BEING CLOSED ##
|
||||
###########################################################################
|
||||
-->
|
||||
<!--
|
||||
Please go through this checklist item by item and make sure you have successfully completed each of these steps.
|
||||
- Your pull request MUST be either on the latest version of Terra, or on a branch for a future release.
|
||||
- Make sure that there are no already existing PRs that fix this. If so, it will be closed as a duplicate.
|
||||
- Make sure that this change is actually within the scope of Terra and is something a terrain generator should be doing.
|
||||
- Make sure that this is not an issue with a specific Terra *pack*, and instead applies to all of Terra.
|
||||
- Make sure that you have filled out all the required information and given descriptions of everything.
|
||||
-->
|
||||
<!-- You can erase any parts of this template not applicable to your Pull Request. -->
|
||||
|
||||
### What Issues Does This Fix?
|
||||
|
||||
<!--
|
||||
Put Fix #XXXX or Closes #XXXX here if there are any open issues that this PR fixes.
|
||||
This is to automatically close the relevant issues.
|
||||
You may remove this if there is no issue for this PR.
|
||||
But unless this is a very small change, you should make an issue for it.
|
||||
-->
|
||||
|
||||
## Licensing
|
||||
|
||||
<!-- In order to be accepted, your changes must be under the GPLv3 license. Please check one of the following: -->
|
||||
|
||||
- [ ] I am the original author of this code, and I am willing to release it under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html).
|
||||
- [ ] I am not the original author of this code, but it is in public domain or released
|
||||
under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html) or a compatible license.
|
||||
<!--
|
||||
Please provide reliable evidence of this.
|
||||
NOTE: for compatible licenses, you must make sure to add the included license somewhere in the program, if so required.
|
||||
(And even if it's not required, it's still nice to do it. Also add attribution somewhere.)
|
||||
-->
|
||||
|
||||
## Goal of the PR
|
||||
|
||||
<!--
|
||||
What is the goal of the PR?
|
||||
Put a checklist here of what has been done
|
||||
(and what *hasn't*, but you plan to do),
|
||||
so we can easily know what was changed.
|
||||
Note: this is only required for PRs that add new features.
|
||||
If your PR is not adding new features, only fixing bugs or adding translations, then you may delete this section.
|
||||
-->
|
||||
|
||||
- [ ] <!-- First thing -->
|
||||
- [ ] <!-- A requirement of the first thing. -->
|
||||
- [ ] <!-- A second requirement of the first thing. -->
|
||||
- [ ] <!-- Second thing -->
|
||||
- [ ] <!-- etc. -->
|
||||
|
||||
## Affects of the PR
|
||||
|
||||
<!---
|
||||
What types of changes does your code introduce? (Select any that apply. You may select multiple.)
|
||||
You must put an x in all the boxes that it applies to. (Like this: [x])
|
||||
-->
|
||||
|
||||
#### Types of changes
|
||||
|
||||
- [ ] Bug Fix <!-- Anything which fixes an issue in Terra. -->
|
||||
- [ ] Build system <!-- Anything which pretain to the build system. -->
|
||||
- [ ] Documentation <!-- Anything which adds or improves documentation for existing features. -->
|
||||
- [ ] New Feature <!-- Anything which adds new functionality to Terra. -->
|
||||
- [ ] Performance <!-- Anything which is imrpoves the performance of Terra. -->
|
||||
- [ ] Refactoring <!-- Anything which does not add any new code, only moves code around. -->
|
||||
- [ ] Repository <!-- Anything which affects the repository. Eg. changes to the `README.md` file. -->
|
||||
- [ ] Revert <!-- Anything which reverts previous commits. -->
|
||||
- [ ] Style <!-- Anything which updates style. -->
|
||||
- [ ] Tests <!-- Anything which adds or updates tests. -->
|
||||
- [ ] Translation <!-- Anything which is internationalizing the Terra program to other languages. -->
|
||||
|
||||
#### Compatiblity
|
||||
|
||||
- [ ] Breaking change <!-- A fix, or a feature, that breaks some previous functionality to Terra. -->
|
||||
- [ ] Non-Breaking change.
|
||||
<!--
|
||||
A change which does not break *any* previous functionality of Terra.
|
||||
(ie. is backwards compatible and will work with *any* previously existing supported features.
|
||||
Note: if a feature is annotated with @Incubating, @Preview, @Experimental,
|
||||
or is in a package called something similar to the previous annotations,
|
||||
then you may push breaking changes to only THOSE parts of Terra.)
|
||||
-->
|
||||
|
||||
#### Contribution Guidelines.
|
||||
|
||||
- [ ] I have read the [`CONTRIBUTING.md`](https://github.com/PolyhedralDev/Terra/blob/master/CONTRIBUTING.md) document in the root of the
|
||||
git repository.
|
||||
- [ ] My code follows the code style for this
|
||||
project. <!-- There is an included `.editorconfig` file in the base of the repo. Please use a plugin for your IDE of choice that follows those settings. -->
|
||||
|
||||
#### Documentation
|
||||
|
||||
- [ ] My change requires a change to the documentation.
|
||||
- [ ] I have updated the documentation accordingly.
|
||||
|
||||
#### Testing
|
||||
|
||||
- [ ] I have added tests to cover my changes.
|
||||
- [ ] All new and existing tests passed.
|
||||
<!--
|
||||
If it only introduces small changes, you don't need to add tests.
|
||||
But if you add big changes, you should probably at least write *some* testing, where applicable.
|
||||
-->
|
||||
+11
-14
@@ -85,14 +85,14 @@ hs_err_pid*
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
.idea/artifacts
|
||||
.idea/compiler.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/modules.xml
|
||||
.idea/*.iml
|
||||
.idea/modules
|
||||
*.iml
|
||||
*.ipr
|
||||
.idea/artifacts
|
||||
.idea/compiler.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/modules.xml
|
||||
.idea/**.iml
|
||||
.idea/modules
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
@@ -137,10 +137,7 @@ build
|
||||
.idea/modules/**.iml
|
||||
|
||||
!lib/*.jar
|
||||
.idea/Terra.iml
|
||||
/run/
|
||||
.idea/**.iml
|
||||
/lang/
|
||||
/packs/
|
||||
/config.yml
|
||||
/region/
|
||||
idea/**
|
||||
|
||||
testDir/
|
||||
@@ -0,0 +1,337 @@
|
||||
# Terra Community Code of Conduct
|
||||
|
||||
# TL;DR
|
||||
|
||||
Polyhedral Development is dedicated to providing a harassment-free experience for everyone, regardless of gender, gender identity and
|
||||
expression, preferred pronouns, sexual orientation, disability, physical appearance, age, race, religion, etc. We do not tolerate harassment
|
||||
of participants in any form.
|
||||
|
||||
This code of conduct applies to all Terra community spaces, including the github discussions tab, our
|
||||
[community discord server](https://discord.gg/PXUEbbF), the [community subreddit](https://reddit.com/r/TerraGenerator), or any other Terra
|
||||
space, both online and off. Anyone in violation of this code, as determined by the applicable moderators, may be subject to verbal warning,
|
||||
expulsion from these spaces, or future events and activities for an undetermined amount of time.
|
||||
|
||||
Some Terra community spaces may have additional rules in place, which will be made clearly available to all participants. Participants are
|
||||
responsible for knowing and abiding by these rules.
|
||||
|
||||
# Longer version
|
||||
|
||||
Polyhedral Development is dedicated to providing a harassment-free experience for everyone. We do not tolerate harassment of participants in
|
||||
any form.
|
||||
|
||||
## When and How to Use These Guidelines
|
||||
|
||||
This code of conduct applies to all Terra community spaces, both online and off. This applies to the github discussion tab,
|
||||
the [Polyhedral Development community discord server](https://discord.gg/PXUEbbF), and any other Terra community. In addition, we may choose
|
||||
to invoke them in instances of harassment outside the Terra communities, and we will punish the responsible individuals appropriately. We
|
||||
will not tolerate harassment in any form, even outside of Terra.
|
||||
|
||||
Some Terra spaces may have additional rules in place, which will be made clearly available to participants. Participants are responsible for
|
||||
knowing and abiding by these rules, in addition to this code of conduct.
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
The following behaviors are expected of all members of the Terra community:
|
||||
|
||||
### Be Respectful
|
||||
|
||||
Value each other's ideas, styles and viewpoints. We may not always agree, but disagreement is no excuse for poor manners. Be open to
|
||||
different possibilities and to being wrong. Be respectful in all interactions and communications, especially when debating the merits of
|
||||
different options. Be aware of your impact and how intense interactions may be affecting people. Be direct, constructive and positive. Take
|
||||
responsibility for your impact, and your mistakes – if someone says they have been harmed through your words or actions, listen carefully,
|
||||
apologize sincerely, and correct the behavior going forward.
|
||||
|
||||
#### Be Prepared to Admit When You are Wrong
|
||||
|
||||
Any member of the Terra community should always be open to new ideas and must always be open to the possibility of being wrong. Nobody can
|
||||
always be right, and we are only human; we are [fallible](https://www.merriam-webster.com/dictionary/fallible) by nature. It is okay to make
|
||||
mistakes, but we must be willing to admit when we make one.
|
||||
|
||||
### Be Direct but Professional
|
||||
|
||||
We are likely to have some discussions about if and when criticism is respectful and when it's not. We must be able to speak directly when
|
||||
we disagree and when we think we need to improve. We cannot withhold hard truths. Doing so respectfully is hard, doing so when others don't
|
||||
seem to be listening is harder, and hearing such comments when one is the recipient can be even harder still. We need to be honest and
|
||||
direct, as well as respectful.
|
||||
|
||||
### Be Inclusive
|
||||
|
||||
Seek diverse perspectives. Diversity of views and of people on teams powers innovation, even if it is not always comfortable. Encourage all
|
||||
voices. Help new perspectives be heard and listen actively. If you find yourself dominating a discussion, it is especially important to step
|
||||
back and encourage other voices to join in. Be aware of how much time is taken up by dominant members of the group. Provide alternative ways
|
||||
to contribute or participate when possible.
|
||||
|
||||
Be inclusive of everyone in an interaction, respecting and facilitating people's participation whether they are:
|
||||
|
||||
- Not native language speakers
|
||||
- Coming from a different culture
|
||||
- Using pronouns other than "he", "she", or "they"
|
||||
- Living in a different time zone
|
||||
- Facing other challenges to participate
|
||||
- Or anything else. Be respectful of *everyone* at *all times*.
|
||||
|
||||
Think about how you might facilitate alternative ways to contribute or participate. If you find yourself dominating a discussion, step back.
|
||||
Make way for other voices and listen actively to them.
|
||||
|
||||
### Understand Different Perspectives
|
||||
|
||||
Our goal should not be to "win" every disagreement or argument. A more productive goal is to be open to ideas that make our own ideas
|
||||
better. Strive to be an example for inclusive thinking. "Winning" is when different perspectives make our work richer and stronger. That
|
||||
means, you must pay attention to all ideas proposed. Don't disregard one without giving it the attention it deserves.
|
||||
|
||||
### Appreciate and Accommodate Our Similarities and Differences
|
||||
|
||||
People come from many cultures and backgrounds. Cultural differences can encompass everything from official religious observances to
|
||||
personal habits to clothing. Be respectful of anyone with different cultural practices, attitudes and beliefs. Work to eliminate your own
|
||||
biases, prejudices and discriminatory practices. Think of others' needs from their point of view. Use preferred titles (including
|
||||
pronouns<sup>[\[1\]](#1)</sup>) and the appropriate tone of voice. Respect people's right to privacy and confidentiality. Be open to
|
||||
learning from and educating others as well as educating yourself; it is unrealistic to expect someone to know the cultural practices of
|
||||
every ethnic and cultural group. Therefore we must be ready to correct someone if they make a mistake, and must be ready ourselves to change
|
||||
and learn if we make a mistake.
|
||||
|
||||
### Lead by Example
|
||||
|
||||
By matching your actions with your words, you become a person others want to follow. Your actions influence others to behave and respond in
|
||||
ways that are valuable and appropriate for our organizational outcomes. Design your community and your work for inclusion. Hold yourself and
|
||||
others accountable for inclusive behaviors.
|
||||
|
||||
## Behavior That Will Not Be Tolerated
|
||||
|
||||
The following behaviors are considered to be unacceptable and will not be tolerated:
|
||||
|
||||
### Violence and Threats of Violence
|
||||
|
||||
Violence and threats of violence are not acceptable - online or offline. This includes incitement of violence toward any individual,
|
||||
including encouraging a person to commit self-harm, engage in self-harm, or put themselves in a negative position (e.g. one which can lead
|
||||
to an increase of depression, etc.).
|
||||
|
||||
### Personal Attacks
|
||||
|
||||
Conflicts will inevitably arise, but frustration should never turn into a personal attack. It is not okay to insult, demean or belittle
|
||||
others. Attacking someone for their opinions, beliefs and ideas is not acceptable. It is important to speak directly when we disagree and
|
||||
when we think we need to improve, but such discussions must be conducted respectfully and professionally, remaining focused on the issue at
|
||||
hand.
|
||||
|
||||
### Derogatory Language
|
||||
|
||||
Offensive, unwelcome, or hurtful comments related to:
|
||||
|
||||
- Gender
|
||||
- Gender identity or expression
|
||||
- Preferred pronouns<sup>[\[1\]](#1)</sup>
|
||||
- Marital status
|
||||
- Sex
|
||||
- Sexual orientation or identity
|
||||
- Native language
|
||||
- Age
|
||||
- (Dis)ability
|
||||
- Mental illness
|
||||
- Neuro(a)typicality
|
||||
- Race and/or ethnicity
|
||||
- Physical appearance
|
||||
- A person's lifestyle choices or practices,
|
||||
- A person's physical condition
|
||||
- A person's mental condition
|
||||
- Socioeconomic status
|
||||
- Religion
|
||||
- Employment
|
||||
- Or anything really. Just don't be offensive towards people, insult them, or make unwanted comments.
|
||||
|
||||
is not acceptable. This includes deliberately referring to someone by a gender that they do not identify with, and/or questioning the
|
||||
legitimacy of an individual's gender identity. If you're unsure if a word is derogatory, don't use it. This also includes repeated subtle
|
||||
and/or indirect discrimination; when asked to stop, stop the behavior in question.
|
||||
|
||||
### Unwelcome Sexual Attention or Physical Contact
|
||||
|
||||
Unwelcome sexual attention or unwelcome physical contact is not acceptable. This includes sexualized comments, jokes or imagery in
|
||||
interactions, communications or presentation materials, as well as inappropriate touching, groping, or sexual advances. Additionally,
|
||||
touching a person without permission, including sensitive areas such as their hair, pregnant stomach, mobility device (wheelchair, scooter,
|
||||
etc) or tattoos is unacceptable. This includes physically blocking or intimidating another person. Physical contact or simulated physical
|
||||
contact (e.g. emojis like ":​kiss:", ":hug:", or ":kiss_mark:", textual descriptions like "\*hug\*", "\*backrub\*", or "\*kisses
|
||||
you\*", etc.) without affirmative consent or after a request to stop will not be accepted.
|
||||
|
||||
### Sexual Behaviour Where it is Not Appropriate
|
||||
|
||||
Uninvited or off-topic sexual images, text, or behaviour in spaces where they're not appropriate will not be accepted whatsoever. We are an
|
||||
open community, which means spaces must be appropriate for all ages, and everybody must feel comfortable. Discussion of sexual things, will
|
||||
be prohibited unless otherwise noted.
|
||||
|
||||
### Discussion of Sensitive Topics
|
||||
|
||||
Discussion of sensitive topics when asked to stop, or when not appropriate. Including, but not limited to:
|
||||
|
||||
- Anything sexual
|
||||
- Gore
|
||||
- Suicide
|
||||
- Self harm
|
||||
- Anything related to death
|
||||
- Or really anything that someone may be sensitive about.
|
||||
|
||||
shall not be tolerated. As a community for all ages and all kinds of people, we must cater to everyone, and must make sure everyone feels
|
||||
comfortable here. Repeatedly breaking someone else's boundaries will not be tolerated.
|
||||
|
||||
### Disruptive Behavior
|
||||
|
||||
Sustained disruption of events, forums, or meetings, online or otherwise, including talks and presentations, will not be tolerated. This
|
||||
includes:
|
||||
|
||||
- 'Talking over', 'heckling', or otherwise disrupting speakers.
|
||||
- Making derogatory comments about someone else's choices, pushing people to do something they do not wish to do, talking about their
|
||||
choices or personal preferences to others, or pressuring them to do something they don't wish to - physically or through jeering.
|
||||
- Behaviour that intentionally disrupts an event.
|
||||
- Otherwise influencing actions that may cause hostility in the session.
|
||||
|
||||
### Influencing Unacceptable Behavior
|
||||
|
||||
We will treat influencing or leading such activities the same way we treat the activities themselves, and thus the same consequences apply.
|
||||
To make someone do something bad is the same thing as if you were to do it yourself, and we will not tolerate it.
|
||||
|
||||
### Stalking or Following
|
||||
|
||||
Stalking or following in any form (offline or online) is unnacceptable. In addition, you may not take pictures or record video of others
|
||||
without their express permission or when asked to stop. Any individual may also request for you to delete all footage you have of them, even
|
||||
if you took it with their prior consent.
|
||||
|
||||
### Publication of Personal Information
|
||||
|
||||
The publication of personally identifying information (commonly known as "[doxxing](https://en.wikipedia.org/wiki/Doxing)") is directly
|
||||
prohibited. You may not publish information that someone wants to keep private, unless it is necessary to protect vulnerable people from
|
||||
intentional abuse. Addditionally, you may not deliberately "out" any aspect of a person's identity without their consent, this includes
|
||||
gender, pronouns, sexual identity, etc.
|
||||
|
||||
Unless it pretains to a case of harassment, as outlined here, in which case some personally identifying information may need to be brought
|
||||
up in private with the appropriate moderation team to help aid our efforts in keeping the community safe.
|
||||
|
||||
### Deliberate Misuse of Pronouns<sup>[\[1\]](#1)</sup> or Names
|
||||
|
||||
As an inclusive community, we must respect everyone. That means respecting the pronouns or names they wish for us to use. Deliberate
|
||||
misgendering, misuse of preferred pronouns<sup>[\[1\]](#1)</sup>, or use of 'dead' or rejected names is not to be tolerated. (If someone
|
||||
*accidentally* uses the incorrect pronouns, gender, or name, politely ask them to use the correct pronouns/gender/name. But if they are to
|
||||
continue using the incorrect pronouns, gender, or name, then you should escalate and report them to us.)
|
||||
|
||||
### Not Stopping After Multiple Requests
|
||||
|
||||
If someone asks you to stop doing something, then you should stop. Continuing to do it may be considered harassment, and can lead you to be
|
||||
removed from our community.
|
||||
|
||||
## Complains We May Ignore
|
||||
|
||||
Additionally, Terra prioritizes marginalized people's safety over privileged people's comfort. We reserve the right to ignore complaints
|
||||
regarding:
|
||||
|
||||
- Claims of discrimination against non-marginalized or oppressed groups (eg. being 'superphobic', meaning to not support people who are
|
||||
'superstraight', which is a dog whistle for transphobic groups, or being 'cisphobic' without large amounts of evidence, etc.), or claims
|
||||
of discrimination with no evidence. (Basically, don't report 'cisphobia' to us, because it doesn't exist. But if someone is mocking you or
|
||||
making fun of you for being cis, and it is *really* getting out of hand, then do tell us.)
|
||||
- Reasonable communication of boundaries, such as "leave me alone," "go away," or "I'm not discussing this with you." (If someone is asking
|
||||
you to stop, that is not reason for you to report them as harassing you.)
|
||||
- Communicating in a 'tone' you don't find [congenial](https://www.thefreedictionary.com/congenial). (You may not report someone for
|
||||
harassment for being 'annoyed with you' or 'talking sternly to you')
|
||||
- Criticizing or calling out racist, sexist, discriminatory, or otherwise oppressive behavior or assumptions. (You may not say that someone
|
||||
is harassing you if they are telling you to stop discriminating against someone.)
|
||||
- Disagreements that do not qualify as harassment. If you have a simple disagreement with someone, and they have not been discriminating to
|
||||
anyone, in any form, then we will not take action against them. Two people are allowed to disagree on things without it getting toxic.
|
||||
|
||||
We may also additionally choose to enact punishment for submitting a complaint in bad-faith or without adequate justification, if we deem
|
||||
necessary; if you're submitting a complaint just to troll or to annoy people, we may choose to have you banned or removed from the community
|
||||
spaces. Don't waste our time.
|
||||
|
||||
In order to protect volunteers from abuse and burnout, we reserve the right to reject any report we believe to have been made in bad faith
|
||||
or with misintent. Reports intended to silence legitimate criticism may be deleted without response.
|
||||
|
||||
## Reporting
|
||||
|
||||
Terra has a global moderation team which is currently comprised of the following members:
|
||||
|
||||
- solonovamax
|
||||
- discord: [@solonovamax#6983](https://discord.com/channels/@me/566146322273402881)*
|
||||
- github: [@solonovamax](https://github.com/solonovamax)
|
||||
- email: [solonovamax@12oclockpoint.com](mailto:solonovamax@12oclockpoint.com)
|
||||
- dfsek
|
||||
- discord: [@dfsek#4208](https://discord.com/channels/@me/378350362236682240)*
|
||||
- github: [@dfsek](https://github.com/dfsek)
|
||||
- email: [dfsek@protonmail.com](mailto:dfsek@protonmail.com)
|
||||
- duplex (duplexsystem)
|
||||
- discord: [@Duplex#0797](https://discord.com/channels/@me/356822848641171456)*
|
||||
- github: [@duplexsystem](https://github.com/duplexsystem)
|
||||
- email: [duplexsys@protonmail.com](mailto:duplexsys@protonmail.com)
|
||||
|
||||
\* The preferred method of communication is through discord. Although we will still be responsive on the other platforms, we will be more
|
||||
responsive on discord.
|
||||
|
||||
These are people you can contact for anything regarding this code of conduct.
|
||||
|
||||
If you are being harassed by a member of the Terra community, or by someone in a Terra community space, notice that someone else is being
|
||||
harassed, or have any other concerns, please contact a moderator of the platform it occurred on, or someone on the global moderation team.
|
||||
If the person who is harassing you is on the global moderation team, they will [recuse](https://www.thefreedictionary.com/recuse) themselves
|
||||
from handling your incident. (Meaning: if you are reporting someone on the team, they will not be involved in the discussion.) We will
|
||||
respond within a reasonable time frame, but generally within about 1 day.
|
||||
|
||||
This code of conduct applies to Terra community spaces, but if you are being harassed by a member of Terra *outside* our spaces, we still
|
||||
want to know about it as we may choose to take action within our community. We will take all good-faith reports seriously and will always
|
||||
attempt to handle them appropriately. This includes harassment outside our spaces and harassment that took place at any point in time. The
|
||||
moderation team reserves the right to exclude people from Terra communities based on their past behavior, including behavior outside Terra
|
||||
spaces and behavior towards people who are not in Terra.
|
||||
|
||||
Note: although we only have the ability to moderate official community spaces, if you are being harassed by someone in a non-official
|
||||
community space, and the moderation team of that platform refuses to do anything to help you (or even if they *do* help you), then you
|
||||
should notify us so that we may take appropriate action.
|
||||
|
||||
We will respect confidentiality requests for the purpose of protecting victims of abuse. At our discretion, we may publicly name a person
|
||||
which we have received harassment complaints about, or privately warn third parties about them, but only if we believe that doing so will
|
||||
increase the safety of Terra community members or the general public. We will not name harassment victims or reporters of harassment
|
||||
(assuming the report was made in good-faith) without their explicit consent; all reports will remain anonymous by default.
|
||||
|
||||
## Consequences of Unacceptable Behavior
|
||||
|
||||
Participants asked to stop any harassing behavior are expected to comply immediately. Whether or not you comply immediately, you may still
|
||||
face consequences for you actions, but if the harasser doesn't comply immediately then we may choose to take additional actions to protect
|
||||
the Terra community members or the individual being harassed.
|
||||
|
||||
Violation of this code can result in being asked to leave an event or online space, either temporarily or for the duration of the event, or
|
||||
being banned from participation in spaces, or future events and activities in perpetuity. If a participant engages in harassing behavior,
|
||||
the global moderation team may take any action they deem appropriate, up to and including expulsion from all Terra community spaces and
|
||||
identification of the participant as a harasser to other Terra community members or the general public. Bad behavior from any community
|
||||
member, including those with decision-making authority, will not be tolerated.
|
||||
|
||||
In addition, any participants who abuse the reporting process will be considered to be in violation of these guidelines and subject to
|
||||
consequences. False reporting, especially to retaliate or exclude, will not be accepted or tolerated.
|
||||
|
||||
## Questions
|
||||
|
||||
if you have further questions for anything not addressed here, you may open an issue on this github repo, or contact a member of the global
|
||||
moderation team.
|
||||
|
||||
## License and Attribution
|
||||
|
||||
This set of guidelines is distributed under a
|
||||
[Creative Commons Attribution-ShareAlike license](https://creativecommons.org/licenses/by-sa/3.0/).
|
||||
|
||||
These guidelines have been adapted from
|
||||
[Mozilla's Community Participation Guidelines](https://www.mozilla.org/en-US/about/governance/policies/participation/), which were adapted
|
||||
from:
|
||||
|
||||
- Mozilla's original Community Participation Guidelines
|
||||
- The [Ubuntu Code of Conduct](https://ubuntu.com/community/code-of-conduct)
|
||||
- Mozilla's [View Source Conference Code of Conduct](https://viewsourceconf.org/berlin-2016/code-of-conduct/)
|
||||
- And the [Rust Language Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct)
|
||||
|
||||
which in turn were based on [Stumptown Syndicate's Citizen Code of Conduct](http://citizencodeofconduct.org/), along with some adapted text
|
||||
from the [LGBTQ in Technology Code of Conduct](https://lgbtq.technology/coc.html) and
|
||||
the [WisCon code of conduct](http://wiscon.net/policies/anti-harassment/code-of-conduct/).
|
||||
|
||||
It was then modified by solonovamax with various inclusions from
|
||||
the [LGBTQ in Technology Code of Conduct](https://lgbtq.technology/coc.html) and a few other sources.
|
||||
|
||||
## Notes
|
||||
|
||||
#### \[1\]
|
||||
|
||||
You provide a set of pronouns that everyone is comfortable addressing you with. Although some people are comfortable
|
||||
using [neopronouns](https://www.mypronouns.org/neopronouns), not everyone is. Therefore, if you use neopronouns, you should have at *least*
|
||||
one set of more common pronouns (One of he/him, she/her, or they/them; it doesn't matter which one. Anyone who doesn't respect your basic
|
||||
pronouns will be removed from the community.) that people may use, should they so choose, as some people are not comfortable
|
||||
using [neopronouns](https://www.mypronouns.org/neopronouns). But if someone refuses to use your more common pronouns, you should report them
|
||||
to us. Additionally, you may not ask people to use unreasonable pronouns, such as 'acab/acabself', 'that/bitch', 'ur/mom', or
|
||||
'dream/dreamself' (pronouns related to real people, eg. the minecraft youtuber 'dreamwastaken'). Doing so will be considered mockery of
|
||||
individuals who use non-standard pronouns and is very disrespectful.
|
||||
+319
@@ -0,0 +1,319 @@
|
||||
# Contributing to Terra
|
||||
|
||||
First off, thank you for considering contributing to Terra. It's people like you that make Terra such a great tool.
|
||||
|
||||
Following these guidelines helps to effectively use the time of the developers managing and developing this open source project, making it
|
||||
more enjoyable for all of us.
|
||||
|
||||
Terra is an open source project and we love to receive contributions from our community, you! There are many ways to contribute, from
|
||||
writing tutorials or blog posts, improving the documentation, submitting bug reports and feature requests or writing code which can be
|
||||
incorporated into Terra.
|
||||
|
||||
The following is a set of guidelines for contributing to Terra and its packages, which are hosted in
|
||||
the [PolyhedralDev Organization](https://github.com/PolyhedralDev) on GitHub. These are mostly guidelines, not rules. Use your best
|
||||
judgment, and feel free to propose changes to this document in a pull request.
|
||||
|
||||
#### Table Of Contents
|
||||
|
||||
[Code of Conduct](#code-of-conduct)
|
||||
|
||||
[I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question)
|
||||
|
||||
[Getting Started](#getting-started)
|
||||
|
||||
- [Your First Contribution](#your-first-contribution)
|
||||
- [Reporting Bugs](#reporting-bugs)
|
||||
- [Before Submitting A Bug Report](#before-submitting-a-bug-report)
|
||||
- [How Do I Submit A (Good) Bug Report?](#how-do-i-submit-a-good-bug-report)
|
||||
- [Suggesting Enhancements](#suggesting-enhancements)
|
||||
- [Before Submitting An Enhancement Suggestion](#before-submitting-an-enhancement-suggestion)
|
||||
- [How Do I Submit A (Good) Enhancement Suggestion?](#how-do-i-submit-a-good-enhancement-suggestion)
|
||||
- [Pull Requests](#pull-requests)
|
||||
- [Before Submitting A Pull Request](#before-submitting-a-pull-request)
|
||||
- [How Do I Submit A (Good) Pull Request?](#how-do-i-submit-a-good-pull-request)
|
||||
|
||||
[Styleguides](#styleguides)
|
||||
|
||||
- [Git Commits](#git-commits)
|
||||
- [Committing](#committing)
|
||||
- [Git Commit Messages](#git-commit-messages)
|
||||
- [Code Styleguide](#code-styleguide)
|
||||
- [Documentation Styleguide](#documentation-styleguide)
|
||||
- TODO
|
||||
|
||||
[Coding Pratices](#coding-practices)
|
||||
|
||||
- [Compatibility](#compatibility)
|
||||
- [General Compatibility](#general-compatibility)
|
||||
- [Specific Compatibility](#specific-compatibility)
|
||||
- [Platform-Agnostic Design](#platform-agnostic-design)
|
||||
- [Data-Driven](#data-driven)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project and everyone participating in it is governed by the [Terra of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected
|
||||
to uphold this code. Please report unacceptable behavior to [Terra global moderation team](CODE_OF_CONDUCT.md#Reporting).
|
||||
|
||||
## I don't want to read this whole thing I just have a question!!!
|
||||
|
||||
> **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below.
|
||||
|
||||
We have an official discord server where you can request help from various users
|
||||
|
||||
- [The official PolyhedralDev discord server](https://discord.dfsek.com)
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Your First Contribution
|
||||
|
||||
Unsure where to begin contributing to Terra? You can start by looking through "beginner" and "help wanted" issues:
|
||||
|
||||
- [Beginner issues](https://github.com/PolyhedralDev/Terra/labels/Note%3A%20Good%20First%20Issue) - issues which should be friendly to
|
||||
anyone new to terra.
|
||||
- [Help wanted issues](https://github.com/PolyhedralDev/Terra/labels/Note%3A%20Help%20Wanted) - issues which should be a bit more involved
|
||||
than "beginner" issues.
|
||||
|
||||
New to github? Working on your first Pull Request? Check
|
||||
out [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github)
|
||||
to get you up on your feet.
|
||||
|
||||
At this point, you're ready to make your changes! Feel free to ask for help; everyone is a beginner at first!
|
||||
|
||||
If a maintainer asks you to "rebase" your PR, they're saying that a lot of code has changed, and that you need to update your branch so it's
|
||||
easier to merge.
|
||||
|
||||
### Reporting Bugs
|
||||
|
||||
This section guides you through submitting a bug report for Terra. Following these guidelines helps maintainers and the community understand
|
||||
your report, and spend their time fixing the issue instead of understanding what you mean.
|
||||
|
||||
Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create
|
||||
one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report).
|
||||
|
||||
> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
|
||||
|
||||
#### Before Submitting A Bug Report
|
||||
|
||||
- Join the [discord server](https://discord.dfsek.com) to help resolve simple issues.
|
||||
- You must be on the LATEST version of Terra to receive any support. There is no support for older versions of Terra.
|
||||
- Make sure that this is not a *specific* compatibility issue with another terrain generation mod. Do not request *specific* compatibility
|
||||
with mods or plugins (e.g. "Compatibility with TechCraft v7"). That should be implemented in an addon, **not** in the main project.
|
||||
*General* compatibility (e.g. "Ability to pull Vanilla/Modded features from parent biomes") will be considered in the main project.
|
||||
- Search for any [already existing issues](https://github.com/PolyhedralDev/Terra/issues?q=is%3Aissue+) open with your problem. If you open
|
||||
a duplicate, it will be closed as such.
|
||||
- Make sure that it is actually Terra causing the issue, and not another mod/plugin. You can do this by testing to see if you can recreate
|
||||
the issue without Terra installed.
|
||||
- Double check that this is not an issue with a specific Terra *pack* or Terra *addon*, and instead applies to all of Terra.
|
||||
- Include a copy of the latest.log file. Putting *just* the exception is not enough. We need to be able to check that there wasn't anything
|
||||
else before that caused it.
|
||||
- Be sure to fill out all the required information and give descriptions of everything.
|
||||
|
||||
#### How Do I Submit A (Good) Bug Report?
|
||||
|
||||
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/)
|
||||
. [Create an issue](https://github.com/PolyhedralDev/Terra/issues/new) and provide the prerequisite information by filling in the Bug Report
|
||||
template.
|
||||
|
||||
Explain the problem and include additional details to help maintainers reproduce the problem:
|
||||
|
||||
- **Use a clear and descriptive title** for the issue to identify the problem.
|
||||
- **Describe the exact steps which reproduce the problem** in as many details as possible. When listing steps, **don't just say what you
|
||||
did, but explain how you did it**.
|
||||
- **Provide specific examples to demonstrate the steps**.
|
||||
- **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
|
||||
- **Explain which behavior you expected to see instead and why.**
|
||||
- **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more
|
||||
information using the guidelines below.
|
||||
|
||||
Include details about your configuration and environment:
|
||||
|
||||
- **Which version of Terra are you using?** You can get the exact version by running `/te version`.
|
||||
- **What's the name and version of the platform you're using**? (eg. Spigot, Fabric, Paper, etc.)
|
||||
- **Which external plugins or mods do you have installed?**
|
||||
- **Which Terra packs do you have installed?** You can get that list by running `/te packs`.
|
||||
- **Which Terra addons do you have installed?** You can get that list by running `/te addons`.
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
This section guides you through submitting an enhancement suggestion for Terra, including completely new features and minor improvements to
|
||||
existing functionality. Following these guidelines helps maintainers and the community understand your suggestion and find related
|
||||
suggestions.
|
||||
|
||||
Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that
|
||||
you don't need to create one. When you are creating an enhancement suggestion,
|
||||
please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion).
|
||||
|
||||
#### Before Submitting An Enhancement Suggestion
|
||||
|
||||
- You must be on the **LATEST** version of Terra to make sure your feature hasn't been added yet.
|
||||
- Search for any [already existing issues](https://github.com/PolyhedralDev/Terra/issues?q=is%3Aissue+) (Including closed!) with your
|
||||
problem. If you open a duplicate, it will be closed as such.
|
||||
- Verify that this is actually within the scope of Terra.
|
||||
- Be sure that this is not a feature request that should be made for a specific Terra *pack*, and instead applies to all of Terra.
|
||||
- Be sure that this is not something that should be implemented as a Terra addon, and instead applies to all of Terra.
|
||||
- Make sure that you attach a copy of the latest.log file, if there are any exceptions thrown in the console. Putting *just* the exception
|
||||
**is not enough**. We need to be able to check that there wasn't anything else before that caused it.
|
||||
|
||||
#### How Do I Submit A (Good) Enhancement Suggestion?
|
||||
|
||||
Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). Create an issue on our main repository
|
||||
and provide the following information:
|
||||
|
||||
- **Use a clear and descriptive title** for the issue to identify the suggestion.
|
||||
- **Provide a step-by-step description of the suggested enhancement** in as many details as possible.
|
||||
- **Provide specific examples to demonstrate the steps**.
|
||||
- **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
|
||||
- **Explain why this enhancement would be useful** to most Terra users and isn't something that can or should be implemented as an addon.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
This section guides you through submitting a pull request for Terra.
|
||||
|
||||
While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete
|
||||
additional design work, tests, or other changes before your pull request can be ultimately accepted.
|
||||
|
||||
#### Before Submitting A Pull Request
|
||||
|
||||
- You must be on the **LATEST** version of Terra to make sure your feature hasn't been added yet.
|
||||
- Search for any [already existing issues](https://github.com/PolyhedralDev/Terra/issues?q=is%3Aissue+) (Including closed!) with your
|
||||
problem. If you open a duplicate, it will be closed as such.
|
||||
- Verify that this is actually within the scope of Terra.
|
||||
- Be sure that this is not a feature request that should be made for a specific Terra *pack*, and instead applies to all of Terra.
|
||||
- Be sure that this is not something that should be implemented as a Terra addon, and instead applies to all of Terra.
|
||||
- Make sure that you attach a copy of the latest.log file, if there are any exceptions thrown in the console. Putting *just* the
|
||||
exception **is not enough**. We need to be able to check that there wasn't anything else before that caused it.
|
||||
|
||||
#### How Do I Submit A (Good) Pull Request?
|
||||
|
||||
Pull Requests are tracked as [GitHub Pull Requests](https://guides.github.com/activities/forking/#making-a-pull-request). Create a pr on our
|
||||
main repository and provide the following information:
|
||||
|
||||
- **Use a clear and descriptive title** to identify the pull request.
|
||||
- **State what this pull request adds/fixes**.
|
||||
- **Be sure that you are the owner of the code you contributed** or that it can be licensed under the GPLv3.
|
||||
- **Provide a description goals and non-goals of the pull request** in as many details as possible.
|
||||
- **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
|
||||
- **Explain why this enhancement would be useful** to most Terra users and isn't something that can or should be implemented as an addon.
|
||||
|
||||
## Styleguides
|
||||
|
||||
### Git Commits
|
||||
|
||||
Following this is not mandatory, but rather a set of guidelines. As long as your commit messages aren't absolutely awful, it's probably
|
||||
fine. But it would be nice if you followed them.
|
||||
|
||||
#### Committing
|
||||
|
||||
When you commit code, try to avoid committing large amounts of code in a single go. Splitting up code into smaller commits is much nicer and
|
||||
makes it easier to trace a feature to a single commit.
|
||||
|
||||
Try to stick to one feature/fix/etc. per commit. A good rule of thumb is if you need to use the word "and" in the subject line, then it
|
||||
should probably™ be two commits.
|
||||
|
||||
#### Git Commit Messages
|
||||
|
||||
- Subject line must fit the following format: `<type>: <short summary>`. Type must be one of the following:
|
||||
- Build: Changes that affect the build system or external dependencies.
|
||||
- Docs: Documentation only changes.
|
||||
- Feat: A new feature.
|
||||
- Fix: A bug fix.
|
||||
- Perf: Performance improvements.
|
||||
- Refactor: Refactoring sections of the codebase.
|
||||
- Repo: Changes to the repository structure that do not affect code. (Eg. modification of the `README.md` file, etc.)
|
||||
- Revert: Revert a previous commit.
|
||||
- Style: Code style updates.
|
||||
- Test: Anything related to testing.
|
||||
- Trans: Translation and localization of Terra to other languages.
|
||||
- WIP: Work in progress.
|
||||
- Separate the subject line from the body with a single blank line.
|
||||
- Do not end subject line with a period.
|
||||
- Limit the subject line to 50 or less.
|
||||
- The subject line and all body lines should be in sentence case.
|
||||
- Use the present tense. ("Add feature" not "Added feature")
|
||||
- Use the imperative mood. ("Move cursor to..." not "Moves cursor to...")
|
||||
- Reference relevant issues and pull requests in the body.
|
||||
|
||||
>
|
||||
> Here is a template you can follow:
|
||||
> ```
|
||||
> Capitalized, short (50 chars or less) summary
|
||||
>
|
||||
> More detailed explanatory text, if necessary. Wrap it to about 72
|
||||
> characters or so. In some contexts, the first line is treated as
|
||||
> the subject of the commit and the rest of the text as the body. The
|
||||
> blank line separating the summary from the body is critical (unless
|
||||
> you omit the body entirely); various tools like `log`, `shortlog` and
|
||||
> `rebase` can get confused if you run the two together.
|
||||
>
|
||||
> Explain the problem that this commit is solving. Focus on why you are
|
||||
> making this change as opposed to how (the code explains that). Are
|
||||
> there side effects or other unintuitive consequences of this
|
||||
> change? Here's the place to explain them.
|
||||
>
|
||||
>
|
||||
> Further paragraphs come after blank lines.
|
||||
> - Bullet points are okay, too
|
||||
> - Typically a hyphen or asterisk is used for the bullet, followed
|
||||
> by a single space, with blank lines in between, but conventions vary
|
||||
> here
|
||||
> - Use a hanging indent
|
||||
>
|
||||
> Reference any relevant issues at the bottom, like so:
|
||||
>
|
||||
> Resolves: #123
|
||||
> See also: #456, #789
|
||||
> ```
|
||||
|
||||
### Code Styleguide
|
||||
|
||||
Use an IDE with support for `.editorconfig` files. There is an included editorconfig file in the base of the project so that your IDE should
|
||||
automatically use the correct code style settings.
|
||||
|
||||
### Documentation Styleguide
|
||||
|
||||
TODO
|
||||
|
||||
## Coding Practices
|
||||
|
||||
### Compatibility
|
||||
|
||||
#### General Compatibility
|
||||
|
||||
General compatibility (example: injection of Vanilla structures/features/carvers into packs) is acceptable in the main project.
|
||||
|
||||
- General compatibility features should be *disabled by default*. Having things auto-injected causes unpredictable behaviour that is
|
||||
annoying to diagnose. General-compatibility options should have config values attached which are disabled by default.
|
||||
- These config options should also be *simple to use*. Think of the people who will be using these compatibility options. They want to flick
|
||||
a switch and have things be compatible. That means that a majority of compatibility options should stay in `pack.yml`, to make it simple
|
||||
to go into a pack and turn on specific compatibilities. This does *not* mean that more advanced compatibility options are off the table,
|
||||
for example, look at Feature compatibility, where features can either be automatically injected, *or* configured individually per Terra
|
||||
biome, depending on how much control the user wants.
|
||||
|
||||
#### Specific Compatibility
|
||||
|
||||
Specific compatibility should *not* be put in the main project. (Example: Adding the ability to generate TechCraft v7's doo-dads with a
|
||||
TerraScript function)
|
||||
|
||||
Having specific compatibilities leads to tons of extra dependencies to keep track of, as well as adding lots of additional stuff to
|
||||
maintain. It quickly becomes a mess. Especially when most users will never need to use this feature.
|
||||
|
||||
We have designed an addon API for exactly this purpose. **Specific compatibilities are welcome and encouraged, in the form of addons.**
|
||||
|
||||
### Platform-Agnostic Design
|
||||
|
||||
Terra must, at all times, remain platform agnostic. This means it must be able to run on theoretically any voxel based platform. Including
|
||||
non-minecraft games like Terasology.
|
||||
|
||||
When adding a new feature to `common`, make no assumptions about what platform it'll be running on.
|
||||
|
||||
Examples:
|
||||
|
||||
- Don't assume the world height is 256.
|
||||
- Don't assume that a specific block, item, or entity exists. (Eg. don't assume there exists a block called `minecraft:grass_block`)
|
||||
|
||||
### Data-Driven
|
||||
|
||||
When adding a new feature, make it abstract. Don't make assumptions about "specific use cases." If you can only think of a few use cases,
|
||||
your idea should probably be generalized.
|
||||
|
||||
You must use configs effectively. Make configs that are *powerful* but also *make sense* and are \[easy\] to use.
|
||||
@@ -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
@@ -1,10 +1,27 @@
|
||||
import com.dfsek.terra.getGitHash
|
||||
|
||||
val versionObj = Version("5", "1", "0", 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,30 +7,15 @@ 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 {
|
||||
val stdout = java.io.ByteArrayOutputStream()
|
||||
val stdout = ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine = mutableListOf("git", "rev-parse", "--short", "HEAD")
|
||||
standardOutput = stdout
|
||||
|
||||
@@ -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,26 +14,8 @@ fun Project.configureDistribution() {
|
||||
apply(plugin = "java-library")
|
||||
apply(plugin = "com.github.johnrengelman.shadow")
|
||||
|
||||
|
||||
// configurations.create("shaded")
|
||||
|
||||
configurations {
|
||||
val shaded = create("shaded")
|
||||
getByName("compile").extendsFrom(shaded)
|
||||
// shaded.extendsFrom(getByName("compile"))
|
||||
val shadedApi = create("shadedApi")
|
||||
shaded.extendsFrom(shadedApi)
|
||||
getByName("api").extendsFrom(shadedApi)
|
||||
val shadedImplementation = create("shadedImplementation")
|
||||
shaded.extendsFrom(shadedImplementation)
|
||||
getByName("implementation").extendsFrom(shadedImplementation)
|
||||
}
|
||||
|
||||
// tasks.withType<JavaCompile> {
|
||||
// classpath +=
|
||||
// }
|
||||
|
||||
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
|
||||
group = "terra"
|
||||
doFirst {
|
||||
file("${buildDir}/resources/main/packs/").deleteRecursively()
|
||||
|
||||
@@ -45,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)
|
||||
@@ -69,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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -160,7 +160,6 @@ public class TerraCommandManager implements CommandManager {
|
||||
if(field.isAnnotationPresent(SwitchTarget.class)) {
|
||||
SwitchTarget switchTarget = field.getAnnotation(SwitchTarget.class);
|
||||
if(!holder.switches.containsValue(switchTarget.value())) {
|
||||
System.out.println(holder.switches);
|
||||
throw new MalformedCommandException("Switch Target specifies nonexistent switch \"" + switchTarget.value() + "\"");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.dfsek.terra.api.event.events;
|
||||
|
||||
import com.dfsek.terra.api.util.mutable.MutableBoolean;
|
||||
|
||||
/**
|
||||
* Abstract class containing basic {@link Cancellable} implementation.
|
||||
*/
|
||||
public abstract class AbstractCancellable implements Cancellable {
|
||||
private final MutableBoolean cancelled = new MutableBoolean(false);
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
this.cancelled.set(cancelled);
|
||||
}
|
||||
}
|
||||
+18
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -1,6 +1,5 @@
|
||||
package com.dfsek.terra.api.event.events.world;
|
||||
|
||||
import com.dfsek.terra.api.event.events.Event;
|
||||
import com.dfsek.terra.api.event.events.PackEvent;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
import com.dfsek.terra.config.pack.WorldConfig;
|
||||
@@ -9,18 +8,24 @@ import com.dfsek.terra.world.TerraWorld;
|
||||
/**
|
||||
* Called upon initialization of a TerraWorld.
|
||||
*/
|
||||
public class TerraWorldLoadEvent implements Event {
|
||||
public class TerraWorldLoadEvent implements PackEvent {
|
||||
private final TerraWorld world;
|
||||
private final ConfigPack pack;
|
||||
|
||||
public TerraWorldLoadEvent(TerraWorld world) {
|
||||
public TerraWorldLoadEvent(TerraWorld world, ConfigPack pack) {
|
||||
this.world = world;
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
public TerraWorld getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public WorldConfig getPack() {
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
public WorldConfig getWorldConfig() {
|
||||
return world.getConfig();
|
||||
}
|
||||
}
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.dfsek.terra.api.event.events.world.generation;
|
||||
|
||||
import com.dfsek.terra.api.event.events.PackEvent;
|
||||
import com.dfsek.terra.api.math.vector.Location;
|
||||
import com.dfsek.terra.api.platform.entity.Entity;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedEntity;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
|
||||
/**
|
||||
* Called when an entity is spawned via {@link BufferedEntity}.
|
||||
*/
|
||||
public class EntitySpawnEvent implements PackEvent {
|
||||
private final ConfigPack pack;
|
||||
private final Entity entity;
|
||||
private final Location location;
|
||||
|
||||
public EntitySpawnEvent(ConfigPack pack, Entity entity, Location location) {
|
||||
this.pack = pack;
|
||||
this.entity = entity;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity that triggered the event.
|
||||
*
|
||||
* @return The entity.
|
||||
*/
|
||||
public Entity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the location of the entity.
|
||||
*
|
||||
* @return Location of the entity.
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.dfsek.terra.api.event.events.world.generation;
|
||||
|
||||
import com.dfsek.terra.api.event.events.AbstractCancellable;
|
||||
import com.dfsek.terra.api.event.events.Cancellable;
|
||||
import com.dfsek.terra.api.event.events.PackEvent;
|
||||
import com.dfsek.terra.api.platform.block.Block;
|
||||
import com.dfsek.terra.api.platform.block.state.Container;
|
||||
import com.dfsek.terra.api.structures.loot.LootTable;
|
||||
import com.dfsek.terra.api.structures.script.StructureScript;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called when loot is populated via {@link BufferedLootApplication}.
|
||||
*/
|
||||
public class LootPopulateEvent extends AbstractCancellable implements PackEvent, Cancellable {
|
||||
private final Block block;
|
||||
private final Container container;
|
||||
private LootTable table;
|
||||
private final ConfigPack pack;
|
||||
private final StructureScript script;
|
||||
|
||||
public LootPopulateEvent(Block block, Container container, LootTable table, ConfigPack pack, StructureScript script) {
|
||||
this.block = block;
|
||||
this.container = container;
|
||||
this.table = table;
|
||||
this.pack = pack;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block containing the tile entity loot is applied to.
|
||||
*
|
||||
* @return Block at which loot is applied.
|
||||
*/
|
||||
public Block getBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Container} representing the inventory.
|
||||
*
|
||||
* @return Inventory recieving loot.
|
||||
*/
|
||||
public Container getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the loot table to be populated.
|
||||
* @return Loot table.
|
||||
*/
|
||||
public LootTable getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the loot table to be populated.
|
||||
*
|
||||
* @param table New loot table.
|
||||
*/
|
||||
public void setTable(@NotNull LootTable table) {
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the script used to generate the structure.
|
||||
*
|
||||
* @return Structure script.
|
||||
*/
|
||||
public StructureScript getStructureScript() {
|
||||
return script;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
@@ -68,7 +70,7 @@ public class StructureScript {
|
||||
.registerFunction("setMark", new SetMarkFunctionBuilder())
|
||||
.registerFunction("getMark", new GetMarkFunctionBuilder())
|
||||
.registerFunction("pull", new PullFunctionBuilder(main))
|
||||
.registerFunction("loot", new LootFunctionBuilder(main, lootRegistry))
|
||||
.registerFunction("loot", new LootFunctionBuilder(main, lootRegistry, this))
|
||||
.registerFunction("entity", new EntityFunctionBuilder(main))
|
||||
.registerFunction("getBiome", new BiomeFunctionBuilder(main))
|
||||
.registerFunction("getBlock", new CheckBlockFunctionBuilder())
|
||||
@@ -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() {
|
||||
|
||||
+5
-2
@@ -3,6 +3,7 @@ package com.dfsek.terra.api.structures.script.builders;
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.StructureScript;
|
||||
import com.dfsek.terra.api.structures.script.functions.LootFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.registry.config.LootRegistry;
|
||||
@@ -12,16 +13,18 @@ import java.util.List;
|
||||
public class LootFunctionBuilder implements FunctionBuilder<LootFunction> {
|
||||
private final TerraPlugin main;
|
||||
private final LootRegistry registry;
|
||||
private final StructureScript script;
|
||||
|
||||
public LootFunctionBuilder(TerraPlugin main, LootRegistry registry) {
|
||||
public LootFunctionBuilder(TerraPlugin main, LootRegistry registry, StructureScript script) {
|
||||
this.main = main;
|
||||
this.registry = registry;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public LootFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new LootFunction(registry, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
|
||||
return new LootFunction(registry, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position, script);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-1
@@ -21,9 +21,11 @@ public class EntityFunction implements Function<Void> {
|
||||
private final EntityType data;
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
private final TerraPlugin main;
|
||||
|
||||
public EntityFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) throws ParseException {
|
||||
this.position = position;
|
||||
this.main = main;
|
||||
if(!(data instanceof ConstantExpression)) throw new ParseException("Entity data must be constant", data.getPosition());
|
||||
|
||||
this.data = main.getWorldHandle().getEntity(((ConstantExpression<String>) data).getConstant());
|
||||
@@ -39,7 +41,7 @@ public class EntityFunction implements Function<Void> {
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
arguments.getBuffer().addItem(new BufferedEntity(data), new Vector3(xz.getX(), y.apply(implementationArguments, variableMap).doubleValue(), xz.getZ()).toLocation(arguments.getBuffer().getOrigin().getWorld()));
|
||||
arguments.getBuffer().addItem(new BufferedEntity(data, main), new Vector3(xz.getX(), y.apply(implementationArguments, variableMap).doubleValue(), xz.getZ()).toLocation(arguments.getBuffer().getOrigin().getWorld()));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -8,6 +8,7 @@ import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.StructureScript;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.structure.RotationUtil;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication;
|
||||
@@ -23,8 +24,9 @@ public class LootFunction implements Function<Void> {
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
private final TerraPlugin main;
|
||||
private final StructureScript script;
|
||||
|
||||
public LootFunction(LootRegistry registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) {
|
||||
public LootFunction(LootRegistry registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position, StructureScript script) {
|
||||
this.registry = registry;
|
||||
this.position = position;
|
||||
this.data = data;
|
||||
@@ -32,6 +34,7 @@ public class LootFunction implements Function<Void> {
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.main = main;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,7 +52,7 @@ public class LootFunction implements Function<Void> {
|
||||
return null;
|
||||
}
|
||||
|
||||
arguments.getBuffer().addItem(new BufferedLootApplication(table, main), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
|
||||
arguments.getBuffer().addItem(new BufferedLootApplication(table, main, script), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+8
-2
@@ -1,18 +1,24 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer.items;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.event.events.world.generation.EntitySpawnEvent;
|
||||
import com.dfsek.terra.api.math.vector.Location;
|
||||
import com.dfsek.terra.api.platform.entity.Entity;
|
||||
import com.dfsek.terra.api.platform.entity.EntityType;
|
||||
|
||||
public class BufferedEntity implements BufferedItem {
|
||||
|
||||
private final EntityType type;
|
||||
private final TerraPlugin main;
|
||||
|
||||
public BufferedEntity(EntityType type) {
|
||||
public BufferedEntity(EntityType type, TerraPlugin main) {
|
||||
this.type = type;
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Location origin) {
|
||||
origin.clone().add(0.5, 0, 0.5).getWorld().spawnEntity(origin, type);
|
||||
Entity entity = origin.clone().add(0.5, 0, 0.5).getWorld().spawnEntity(origin, type);
|
||||
main.getEventManager().callEvent(new EntitySpawnEvent(entity.getWorld().getTerraGenerator().getConfigPack(), entity, entity.getLocation()));
|
||||
}
|
||||
}
|
||||
|
||||
+15
-4
@@ -1,35 +1,46 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer.items;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.event.events.world.generation.LootPopulateEvent;
|
||||
import com.dfsek.terra.api.math.vector.Location;
|
||||
import com.dfsek.terra.api.platform.block.Block;
|
||||
import com.dfsek.terra.api.platform.block.state.BlockState;
|
||||
import com.dfsek.terra.api.platform.block.state.Container;
|
||||
import com.dfsek.terra.api.structures.loot.LootTable;
|
||||
import com.dfsek.terra.api.structures.script.StructureScript;
|
||||
import com.dfsek.terra.api.util.FastRandom;
|
||||
|
||||
public class BufferedLootApplication implements BufferedItem {
|
||||
private final LootTable table;
|
||||
private final TerraPlugin main;
|
||||
private final StructureScript structure;
|
||||
|
||||
public BufferedLootApplication(LootTable table, TerraPlugin main) {
|
||||
public BufferedLootApplication(LootTable table, TerraPlugin main, StructureScript structure) {
|
||||
this.table = table;
|
||||
this.main = main;
|
||||
this.structure = structure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Location origin) {
|
||||
try {
|
||||
BlockState data = origin.getBlock().getState();
|
||||
Block block = origin.getBlock();
|
||||
BlockState data = block.getState();
|
||||
if(!(data instanceof Container)) {
|
||||
main.logger().severe("Failed to place loot at " + origin + "; block " + data + " is not container.");
|
||||
return;
|
||||
}
|
||||
Container container = (Container) data;
|
||||
table.fillInventory(container.getInventory(), new FastRandom(origin.hashCode()));
|
||||
|
||||
LootPopulateEvent event = new LootPopulateEvent(block, container, table, block.getLocation().getWorld().getTerraGenerator().getConfigPack(), structure);
|
||||
main.getEventManager().callEvent(event);
|
||||
if(event.isCancelled()) return;
|
||||
|
||||
event.getTable().fillInventory(container.getInventory(), new FastRandom(origin.hashCode()));
|
||||
data.update(false);
|
||||
} catch(Exception e) {
|
||||
main.logger().warning("Could not apply loot at " + origin + ": " + e.getMessage());
|
||||
main.getDebugLogger().stack(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class MutableBoolean implements MutablePrimitive<Boolean> {
|
||||
private boolean value;
|
||||
|
||||
public MutableBoolean() {
|
||||
this.value = false;
|
||||
}
|
||||
|
||||
public MutableBoolean(boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean get() {
|
||||
return value;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.dfsek.terra.api.world.generation;
|
||||
|
||||
/**
|
||||
* Marker interface that marks a feature as "chunkified" (only modifying one chunk at a time)
|
||||
*/
|
||||
public interface Chunkified {
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.dfsek.terra.api.world.generation;
|
||||
|
||||
/**
|
||||
* The phase of terrain generation. Used for modifying values based on the phase of generation.
|
||||
*/
|
||||
public enum GenerationPhase {
|
||||
BASE, POPULATE, GENERATION_POPULATE, PALETTE_APPLY, POST_GEN
|
||||
}
|
||||
@@ -6,10 +6,10 @@ import com.dfsek.terra.api.platform.world.World;
|
||||
import com.dfsek.terra.api.platform.world.generator.ChunkData;
|
||||
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
|
||||
import com.dfsek.terra.config.pack.ConfigPack;
|
||||
import com.dfsek.terra.world.generation.math.SamplerCache;
|
||||
import com.dfsek.terra.world.generation.math.samplers.Sampler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public interface TerraChunkGenerator {
|
||||
@@ -32,4 +32,6 @@ public interface TerraChunkGenerator {
|
||||
TerraPlugin getMain();
|
||||
|
||||
Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth);
|
||||
|
||||
List<TerraBlockPopulator> getPopulators();
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,6 @@ public class StructureLoadCommand implements CommandTemplate {
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
System.out.println(rotation);
|
||||
|
||||
Player player = (Player) sender;
|
||||
|
||||
long t = System.nanoTime();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -4,7 +4,10 @@ import com.dfsek.terra.api.platform.world.Biome;
|
||||
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.util.seeded.SeededBuilder;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.config.templates.BiomeTemplate;
|
||||
|
||||
public interface BiomeBuilder extends SeededBuilder<TerraBiome> {
|
||||
ProbabilityCollection<Biome> getVanillaBiomes();
|
||||
|
||||
BiomeTemplate getTemplate();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -66,4 +66,9 @@ public class UserDefinedBiomeBuilder implements BiomeBuilder {
|
||||
public ProbabilityCollection<Biome> getVanillaBiomes() {
|
||||
return template.getVanilla();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeTemplate getTemplate() {
|
||||
return template;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
-1
@@ -65,7 +65,6 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
|
||||
Map<String, Function> noiseFunctionMap = new HashMap<>();
|
||||
|
||||
for(Map.Entry<String, FunctionTemplate> entry : expressions.entrySet()) {
|
||||
System.out.println(entry);
|
||||
noiseFunctionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), new Parser(), new Scope()));
|
||||
}
|
||||
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,46 @@ public class ConfigPackTemplate implements ConfigTemplate {
|
||||
@Default
|
||||
private String version = "0.1.0";
|
||||
|
||||
@Value("disable.carvers")
|
||||
@Default
|
||||
private boolean disableCarvers = false;
|
||||
|
||||
@Value("disable.structures")
|
||||
@Default
|
||||
private boolean disableStructures = false;
|
||||
|
||||
@Value("disable.ores")
|
||||
@Default
|
||||
private boolean disableOres = false;
|
||||
|
||||
@Value("disable.trees")
|
||||
@Default
|
||||
private boolean disableTrees = false;
|
||||
|
||||
@Value("disable.flora")
|
||||
@Default
|
||||
private boolean disableFlora = false;
|
||||
|
||||
public boolean disableCarvers() {
|
||||
return disableCarvers;
|
||||
}
|
||||
|
||||
public boolean disableFlora() {
|
||||
return disableFlora;
|
||||
}
|
||||
|
||||
public boolean disableOres() {
|
||||
return disableOres;
|
||||
}
|
||||
|
||||
public boolean disableStructures() {
|
||||
return disableStructures;
|
||||
}
|
||||
|
||||
public boolean disableTrees() {
|
||||
return disableTrees;
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, FunctionTemplate> getFunctions() {
|
||||
return functions;
|
||||
}
|
||||
|
||||
@@ -190,10 +190,19 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
|
||||
@Default
|
||||
private Map<UserDefinedCarver, Integer> carvers = new HashMap<>();
|
||||
|
||||
@Value("colors")
|
||||
@Abstractable
|
||||
@Default
|
||||
private Map<String, Integer> colors = new HashMap<>(); // Plain ol' map, so platforms can decide what to do with colors (if anything).
|
||||
|
||||
public Set<String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getColors() {
|
||||
return colors;
|
||||
}
|
||||
|
||||
public Map<UserDefinedCarver, Integer> getCarvers() {
|
||||
return carvers;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
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
|
||||
|
||||
+20
-2
@@ -10,20 +10,27 @@ import com.dfsek.terra.api.util.world.PaletteUtil;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
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.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;
|
||||
import com.dfsek.terra.world.generation.math.SamplerCache;
|
||||
import com.dfsek.terra.world.generation.math.samplers.Sampler;
|
||||
import com.dfsek.terra.world.generation.math.samplers.Sampler2D;
|
||||
import com.dfsek.terra.world.population.CavePopulator;
|
||||
import com.dfsek.terra.world.population.OrePopulator;
|
||||
import com.dfsek.terra.world.population.StructurePopulator;
|
||||
import com.dfsek.terra.world.population.TreePopulator;
|
||||
import net.jafama.FastMath;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class DefaultChunkGenerator2D implements TerraChunkGenerator {
|
||||
@@ -31,12 +38,18 @@ public class DefaultChunkGenerator2D implements TerraChunkGenerator {
|
||||
private final TerraPlugin main;
|
||||
|
||||
private final Carver carver;
|
||||
private final List<TerraBlockPopulator> blockPopulators = new ArrayList<>();
|
||||
|
||||
private final SamplerCache cache;
|
||||
|
||||
public DefaultChunkGenerator2D(ConfigPack c, TerraPlugin main, SamplerCache cache) {
|
||||
this.configPack = c;
|
||||
this.main = main;
|
||||
blockPopulators.add(new CavePopulator(main));
|
||||
blockPopulators.add(new StructurePopulator(main));
|
||||
blockPopulators.add(new OrePopulator(main));
|
||||
blockPopulators.add(new TreePopulator(main));
|
||||
blockPopulators.add(new TreePopulator(main));
|
||||
carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main);
|
||||
this.cache = cache;
|
||||
}
|
||||
@@ -81,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);
|
||||
@@ -125,4 +138,9 @@ public class DefaultChunkGenerator2D implements TerraChunkGenerator {
|
||||
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
|
||||
return new Sampler2D(chunkX, chunkZ, provider, world, elevationSmooth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TerraBlockPopulator> getPopulators() {
|
||||
return blockPopulators;
|
||||
}
|
||||
}
|
||||
|
||||
+39
-16
@@ -17,19 +17,27 @@ import com.dfsek.terra.api.util.world.PaletteUtil;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
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.api.world.generation.TerraChunkGenerator;
|
||||
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;
|
||||
import com.dfsek.terra.world.generation.math.samplers.Sampler;
|
||||
import com.dfsek.terra.world.generation.math.samplers.Sampler3D;
|
||||
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.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -38,14 +46,20 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
|
||||
private final TerraPlugin main;
|
||||
private final BlockType water;
|
||||
private final SinglePalette<BlockData> blank;
|
||||
private final List<TerraBlockPopulator> blockPopulators = new ArrayList<>();
|
||||
|
||||
private final Carver carver;
|
||||
|
||||
|
||||
|
||||
public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) {
|
||||
this.configPack = c;
|
||||
this.main = main;
|
||||
|
||||
blockPopulators.add(new CavePopulator(main));
|
||||
blockPopulators.add(new StructurePopulator(main));
|
||||
blockPopulators.add(new OrePopulator(main));
|
||||
blockPopulators.add(new TreePopulator(main));
|
||||
blockPopulators.add(new FloraPopulator(main));
|
||||
|
||||
carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main);
|
||||
water = main.getWorldHandle().createBlockData("minecraft:water").getBlockType();
|
||||
blank = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:air"));
|
||||
@@ -89,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);
|
||||
@@ -105,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();
|
||||
@@ -212,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,4 +254,9 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
|
||||
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
|
||||
return new Sampler3D(chunkX, chunkZ, provider, world, elevationSmooth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TerraBlockPopulator> getPopulators() {
|
||||
return blockPopulators;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,11 +9,12 @@ import com.dfsek.terra.api.platform.handle.WorldHandle;
|
||||
import com.dfsek.terra.api.platform.world.Chunk;
|
||||
import com.dfsek.terra.api.platform.world.World;
|
||||
import com.dfsek.terra.api.util.world.PopulationUtil;
|
||||
import com.dfsek.terra.api.world.generation.Chunkified;
|
||||
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;
|
||||
|
||||
@@ -23,7 +24,7 @@ import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public class CavePopulator implements TerraBlockPopulator {
|
||||
public class CavePopulator implements TerraBlockPopulator, Chunkified {
|
||||
private static final Map<BlockType, BlockData> shiftStorage = new HashMap<>(); // Persist BlockData created for shifts, to avoid re-calculating each time.
|
||||
private final TerraPlugin main;
|
||||
|
||||
@@ -37,48 +38,51 @@ public class CavePopulator implements TerraBlockPopulator {
|
||||
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();
|
||||
if(config.getTemplate().disableCarvers()) return;
|
||||
|
||||
for(UserDefinedCarver c : config.getCarvers()) {
|
||||
CarverTemplate template = c.getConfig();
|
||||
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()) {
|
||||
@@ -91,7 +95,7 @@ public class CavePopulator implements TerraBlockPopulator {
|
||||
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,7 +32,9 @@ 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")) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("flora")) {
|
||||
if(tw.getConfig().getTemplate().disableFlora()) return;
|
||||
|
||||
if(!tw.isSafe()) return;
|
||||
BiomeProvider provider = tw.getBiomeProvider();
|
||||
Map<Vector2, List<FloraLayer>> layers = new HashMap<>();
|
||||
|
||||
@@ -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,7 +27,9 @@ 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")) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("ore")) {
|
||||
if(tw.getConfig().getTemplate().disableOres()) return;
|
||||
|
||||
if(!tw.isSafe()) return;
|
||||
for(int cx = -1; cx <= 1; cx++) {
|
||||
for(int cz = -1; cz <= 1; cz++) {
|
||||
@@ -38,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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ import com.dfsek.terra.api.structures.structure.Rotation;
|
||||
import com.dfsek.terra.api.util.FastRandom;
|
||||
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;
|
||||
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class StructurePopulator implements TerraBlockPopulator {
|
||||
public class StructurePopulator implements TerraBlockPopulator, Chunkified {
|
||||
private final TerraPlugin main;
|
||||
|
||||
public StructurePopulator(TerraPlugin main) {
|
||||
@@ -31,7 +31,9 @@ public class StructurePopulator implements TerraBlockPopulator {
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Chunk chunk) {
|
||||
TerraWorld tw = main.getWorld(world);
|
||||
try(ProfileFuture ignored = tw.getProfiler().measure("StructureTime")) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("structure")) {
|
||||
if(tw.getConfig().getTemplate().disableStructures()) return;
|
||||
|
||||
int cx = (chunk.getX() << 4);
|
||||
int cz = (chunk.getZ() << 4);
|
||||
if(!tw.isSafe()) return;
|
||||
|
||||
@@ -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,7 +32,9 @@ 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")) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("tree")) {
|
||||
if(tw.getConfig().getTemplate().disableTrees()) return;
|
||||
|
||||
if(!tw.isSafe()) return;
|
||||
BiomeProvider provider = tw.getBiomeProvider();
|
||||
Random random = PopulationUtil.getRandom(chunk);
|
||||
@@ -40,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ cache:
|
||||
carver: 512
|
||||
structure: 32
|
||||
sampler: 128
|
||||
master-disable:
|
||||
caves: false
|
||||
biome-provider: 32
|
||||
script:
|
||||
max-recursion: 1000
|
||||
@@ -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/"
|
||||
@@ -39,6 +39,8 @@ import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiom
|
||||
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;
|
||||
@@ -136,6 +138,11 @@ public class DistributionTest {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Profiler getProfiler() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TypeRegistry registry) {
|
||||
|
||||
@@ -152,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()
|
||||
@@ -306,6 +313,11 @@ public class DistributionTest {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeTemplate getTemplate() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Generator getGenerator(World w) {
|
||||
return null;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -15,12 +15,12 @@ configureCommon()
|
||||
|
||||
group = "com.dfsek.terra.bukkit"
|
||||
|
||||
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/") }
|
||||
}
|
||||
val mcVersion = "1.16.5"
|
||||
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"
|
||||
|
||||
dependencies {
|
||||
"shadedApi"(project(":common"))
|
||||
@@ -32,76 +32,159 @@ 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 testDir = "target/server/"
|
||||
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", "-javaagent:paperclip.jar")
|
||||
|
||||
val setupServer = tasks.create("setupServer") {
|
||||
dependsOn("shadowJar")
|
||||
doFirst {
|
||||
// clean
|
||||
file("${testDir}/").deleteRecursively()
|
||||
file("${testDir}/plugins").mkdirs()
|
||||
fun downloadPaperclip(url: String, dir: String) {
|
||||
val clip = URL(url.replace("%version%", mcVersion))
|
||||
val clipReadableByteChannel = Channels.newChannel(clip.openStream())
|
||||
val clipFile = file("$testDir/$dir/paperclip.jar")
|
||||
val clipOutputStream = clipFile.outputStream()
|
||||
val clipFileChannel = clipOutputStream.channel
|
||||
clipFileChannel.transferFrom(clipReadableByteChannel, 0, Long.MAX_VALUE)
|
||||
}
|
||||
|
||||
// Downloading latest paper jar.
|
||||
val paperUrl = URL("https://papermc.io/api/v1/paper/1.16.4/latest/download")
|
||||
val paperReadableByteChannel = Channels.newChannel(paperUrl.openStream())
|
||||
val paperFile = file("${testDir}/paper.jar")
|
||||
val paperFileOutputStream = paperFile.outputStream()
|
||||
val paperFileChannel = paperFileOutputStream.channel
|
||||
paperFileChannel.transferFrom(paperReadableByteChannel, 0, Long.MAX_VALUE)
|
||||
|
||||
// Cloning test setup.
|
||||
gitClone("https://github.com/PolyhedralDev/WorldGenTestServer")
|
||||
// Copying plugins
|
||||
Files.move(Paths.get("WorldGenTestServer/plugins"),
|
||||
Paths.get("$testDir/plugins"),
|
||||
StandardCopyOption.REPLACE_EXISTING)
|
||||
// Copying config
|
||||
val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText()
|
||||
file("${testDir}/server.properties").writeText(serverText)
|
||||
val bukkitText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/bukkit.yml").readText()
|
||||
file("${testDir}/bukkit.yml").writeText(bukkitText.replace("\${world}", "world").replace("\${gen}", "Terra:DEFAULT"))
|
||||
|
||||
File("${testDir}/eula.txt").writeText("eula=true")
|
||||
|
||||
// clean up
|
||||
file("WorldGenTestServer").deleteRecursively()
|
||||
fun copyTerra(dir: String) {
|
||||
file("$testDir/$dir").walk().forEach {
|
||||
if(it.name.startsWith("Terra-") && it.name.endsWith(".jar")) it.delete() // Delete old Terra jar(s)
|
||||
}
|
||||
copy {
|
||||
from("$buildDir/libs/Terra-bukkit-$version-shaded.jar")
|
||||
into("$testDir/$dir/plugins/")
|
||||
}
|
||||
}
|
||||
|
||||
val testWithPaper = task<JavaExec>(name = "testWithPaper") {
|
||||
fun installServer(dir: String) {
|
||||
// clean
|
||||
file("$testDir/$dir").deleteRecursively()
|
||||
file("$testDir/$dir/plugins").mkdirs()
|
||||
// Cloning test setup.
|
||||
gitClone("https://github.com/PolyhedralDev/WorldGenTestServer")
|
||||
// Copying 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()
|
||||
file("$testDir/$dir/server.properties").writeText(serverText)
|
||||
val bukkitText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/bukkit.yml").readText()
|
||||
file("$testDir/$dir/bukkit.yml").writeText(bukkitText.replace("\${world}", "world").replace("\${gen}", "Terra:DEFAULT"))
|
||||
|
||||
println("By proceeding, you are agreeing to the Minecraft EULA: https://account.mojang.com/documents/minecraft_eula")
|
||||
file("$testDir/$dir/eula.txt").writeText("eula=true")
|
||||
|
||||
// clean up
|
||||
file("WorldGenTestServer").deleteRecursively()
|
||||
}
|
||||
|
||||
fun deleteFolder(folder: File) {
|
||||
if(folder.exists()) folder.deleteRecursively()
|
||||
}
|
||||
|
||||
fun deleteFile(file: File) {
|
||||
if(file.exists()) file.delete()
|
||||
}
|
||||
|
||||
tasks.create("cleanWorlds") {
|
||||
group = "bukkit"
|
||||
doFirst {
|
||||
deleteFolder(file("$testDir/paper/world"))
|
||||
deleteFolder(file("$testDir/paper/world_nether"))
|
||||
deleteFolder(file("$testDir/paper/world_the_end"))
|
||||
|
||||
deleteFolder(file("$testDir/purpur/world"))
|
||||
deleteFolder(file("$testDir/purpur/world_nether"))
|
||||
deleteFolder(file("$testDir/purpur/world_the_end"))
|
||||
}
|
||||
}
|
||||
|
||||
tasks.create("updatePaper") {
|
||||
group = "bukkit"
|
||||
doFirst {
|
||||
deleteFile(file("$testDir/paper/paperclip.jar"))
|
||||
downloadPaperclip(paperURL, "paper")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.create("updatePurpur") {
|
||||
group = "bukkit"
|
||||
doFirst {
|
||||
deleteFile(file("$testDir/paper/paperclip.jar"))
|
||||
downloadPaperclip(purpurURL, "purpur")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.create("installPaper") {
|
||||
group = "bukkit"
|
||||
dependsOn("shadowJar")
|
||||
doFirst {
|
||||
installServer("paper")
|
||||
// Downloading latest paper jar.
|
||||
downloadPaperclip(paperURL, "paper")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.create("installPurpur") {
|
||||
group = "bukkit"
|
||||
dependsOn("shadowJar")
|
||||
doFirst {
|
||||
installServer("purpur")
|
||||
// Downloading latest paper jar.
|
||||
downloadPaperclip(purpurURL, "purpur")
|
||||
}
|
||||
}
|
||||
|
||||
task<JavaExec>(name = "runPaper") {
|
||||
group = "bukkit"
|
||||
standardInput = System.`in`
|
||||
dependsOn("shadowJar")
|
||||
// Copy Terra into dir
|
||||
doFirst {
|
||||
copy {
|
||||
from("${buildDir}/libs/Terra-bukkit-${version}-shaded.jar")
|
||||
into("${testDir}/plugins/")
|
||||
}
|
||||
copyTerra("paper")
|
||||
}
|
||||
|
||||
main = "io.papermc.paperclip.Paperclip"
|
||||
jvmArgs = 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")
|
||||
maxHeapSize = "4G"
|
||||
minHeapSize = "4G"
|
||||
jvmArgs = jvmFlags
|
||||
maxHeapSize = testMem
|
||||
minHeapSize = testMem
|
||||
//args = listOf("nogui")
|
||||
workingDir = file("${testDir}/")
|
||||
classpath = files("${testDir}/paper.jar")
|
||||
workingDir = file("$testDir/paper")
|
||||
classpath = files("$testDir/paper/paperclip.jar")
|
||||
}
|
||||
|
||||
task<JavaExec>(name = "runPurpur") {
|
||||
group = "bukkit"
|
||||
standardInput = System.`in`
|
||||
dependsOn("shadowJar")
|
||||
// Copy Terra into dir
|
||||
doFirst {
|
||||
copyTerra("purpur")
|
||||
}
|
||||
|
||||
main = "io.papermc.paperclip.Paperclip"
|
||||
jvmArgs = jvmFlags
|
||||
maxHeapSize = testMem
|
||||
minHeapSize = testMem
|
||||
//args = listOf("nogui")
|
||||
workingDir = file("$testDir/purpur")
|
||||
classpath = files("$testDir/purpur/paperclip.jar")
|
||||
}
|
||||
|
||||
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 {
|
||||
publications {
|
||||
create<MavenPublication>("mavenJava") {
|
||||
@@ -112,7 +195,6 @@ publishing {
|
||||
|
||||
repositories {
|
||||
val mavenUrl = "https://repo.codemc.io/repository/maven-releases/"
|
||||
val mavenSnapshotUrl = "https://repo.codemc.io/repository/maven-snapshots/"
|
||||
|
||||
maven(mavenUrl) {
|
||||
val mavenUsername: String? by project
|
||||
|
||||
@@ -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
|
||||
|
||||
+5
-23
@@ -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;
|
||||
@@ -23,12 +15,11 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
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 {
|
||||
|
||||
@@ -40,20 +31,13 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener
|
||||
|
||||
private final TerraPlugin main;
|
||||
|
||||
private final List<TerraBlockPopulator> populators = new LinkedList<>();
|
||||
|
||||
private boolean needsLoad = true;
|
||||
|
||||
public BukkitChunkGeneratorWrapper(TerraChunkGenerator delegate) {
|
||||
this.delegate = delegate;
|
||||
this.main = delegate.getMain();
|
||||
popMan = new PopulationManager(main);
|
||||
popMan.attach(new OrePopulator(main));
|
||||
popMan.attach(new TreePopulator(main));
|
||||
popMan.attach(new FloraPopulator(main));
|
||||
populators.add(new CavePopulator(main));
|
||||
populators.add(new StructurePopulator(main));
|
||||
populators.add(popMan);
|
||||
this.popMan = new PopulationManager(delegate, main);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -68,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());
|
||||
}
|
||||
|
||||
@@ -81,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;
|
||||
}
|
||||
|
||||
@@ -96,7 +78,7 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener
|
||||
|
||||
@Override
|
||||
public @NotNull List<BlockPopulator> getDefaultPopulators(@NotNull World world) {
|
||||
return populators.stream().map(BukkitPopulatorWrapper::new).collect(Collectors.toList());
|
||||
return Arrays.asList(popMan, new BukkitPopulatorWrapper(delegate));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.dfsek.terra.bukkit.generator;
|
||||
|
||||
import com.dfsek.terra.api.platform.world.Chunk;
|
||||
import com.dfsek.terra.api.platform.world.World;
|
||||
import com.dfsek.terra.api.platform.world.generator.BlockPopulator;
|
||||
import com.dfsek.terra.bukkit.world.BukkitChunk;
|
||||
import com.dfsek.terra.bukkit.world.BukkitWorld;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class BukkitPopulator implements BlockPopulator {
|
||||
private final org.bukkit.generator.BlockPopulator handle;
|
||||
|
||||
public BukkitPopulator(org.bukkit.generator.BlockPopulator handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(World world, Random random, Chunk chunk) {
|
||||
handle.populate(((BukkitWorld) world).getHandle(), random, ((BukkitChunk) chunk).getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.generator.BlockPopulator getHandle() {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
+9
-3
@@ -1,6 +1,8 @@
|
||||
package com.dfsek.terra.bukkit.generator;
|
||||
|
||||
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.world.BukkitAdapter;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
@@ -10,14 +12,18 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.Random;
|
||||
|
||||
public class BukkitPopulatorWrapper extends BlockPopulator {
|
||||
private final TerraBlockPopulator delegate;
|
||||
private final TerraChunkGenerator delegate;
|
||||
|
||||
public BukkitPopulatorWrapper(TerraBlockPopulator delegate) {
|
||||
public BukkitPopulatorWrapper(TerraChunkGenerator delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk source) {
|
||||
delegate.populate(BukkitAdapter.adapt(world), BukkitAdapter.adapt(source));
|
||||
delegate.getPopulators().forEach(populator -> {
|
||||
if(populator instanceof Chunkified) {
|
||||
populator.populate(BukkitAdapter.adapt(world), BukkitAdapter.adapt(source));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user