diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..4afb8b9c1 --- /dev/null +++ b/.github/CODEOWNERS @@ -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 \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md new file mode 100644 index 000000000..9a1b69189 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.md @@ -0,0 +1,105 @@ +--- +name: "Bug Report" +about: "Open a bug report to help us identify issues with Terra." +title: "[Bug] " +labels: "Type: Bug, Status: Pending" +assignees: "" + +--- + + + +## Pre-Issue Checklist + + + +- [ ] 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. + +- [ ] I have attached a copy of the `latest.log` file +- [ ] I have filled out and provided all the appropriate information. + +## Environment + + + +| Name | Value | +|------------------------------|-------| +| Terra Version | +| Platform / Platform Version | +| Any External Plugins or Mods | +| Terra Packs In Use | +| Terra Addons In Use | + +## Issue Description + + + +### Steps to reproduce + + + +1. +2. +3. + +### Expected behavior + + + +### Actual behavior + + + + +### Full stacktrace + +
+Exception Stacktrace + + + +``` + +``` + +
+ +### Additional details + + + diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md new file mode 100644 index 000000000..090354420 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md @@ -0,0 +1,70 @@ +--- +name: "Feature Request" +about: "Give us suggestions of features we could add to Terra." +title: "[Feature] " +labels: "Type: Enhancement, Status: Pending" +assignees: "" + +--- + + + +### Pre-Request Checklist + + + +- [ ] 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 + + + +### What Problem Does This Solve? + + + +### A Solution You'd Like + + + +### Alternative Solutions + + + +1. +2. +3. + +### Additonal Context + + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/OTHER_ISSUES.md b/.github/ISSUE_TEMPLATE/OTHER_ISSUES.md new file mode 100644 index 000000000..1677fab03 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/OTHER_ISSUES.md @@ -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 + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..9c7f2e470 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -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. \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..9db773e99 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,114 @@ +# Pull Request + +## Brief description. + + + + + + + +### What Issues Does This Fix? + + + +## Licensing + + + +- [ ] 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. + + +## Goal of the PR + + + +- [ ] + - [ ] + - [ ] +- [ ] +- [ ] + +## Affects of the PR + + + +#### Types of changes + +- [ ] Bug Fix +- [ ] Build system +- [ ] Documentation +- [ ] New Feature +- [ ] Performance +- [ ] Refactoring +- [ ] Repository +- [ ] Revert +- [ ] Style +- [ ] Tests +- [ ] Translation + +#### Compatiblity + +- [ ] Breaking change +- [ ] Non-Breaking change. + + +#### 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. + +#### 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. + \ No newline at end of file diff --git a/.gitignore b/.gitignore index b1c99d269..cde9583f4 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..b2d97634b --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -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[\[1\]](#1)) 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[\[1\]](#1) +- 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[\[1\]](#1) 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[\[1\]](#1), 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. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..743a1face --- /dev/null +++ b/CONTRIBUTING.md @@ -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 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. \ No newline at end of file diff --git a/README.md b/README.md index 8986ce6b7..0b0eb8b93 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ 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: [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 @@ -32,15 +32,15 @@ To run Minecraft with Terra in the IDE (for testing) use the following tasks: * `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 client with Terra installed. - * `runServer` - Run a Minecraft server with Terra installed. + * `runClient` - Run a Minecraft Fabric client with Terra installed. + * `runServer` - Run a Minecraft Fabric server with Terra installed. * Forge - * `runClient` - Run a Minecraft client with Terra installed. - * `runServer` - Run a Minecraft server with Terra installed. + * `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! \ No newline at end of file +Terra is still in beta! While it is stable, it is not feature-complete. There is a lot to be added! diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt index a8fc73b96..c48a7de3b 100644 --- a/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt @@ -14,8 +14,8 @@ fun Project.configureCompilation() { apply(plugin = "idea") configure { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_16 + targetCompatibility = JavaVersion.VERSION_16 } tasks.withType { @@ -29,7 +29,12 @@ fun Project.configureCompilation() { include("**/*.*") filter( "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"] ) ) } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 311054dd7..ca834dd81 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -17,7 +17,7 @@ dependencies { "shadedApi"("commons-io:commons-io:2.4") "shadedApi"("com.dfsek:Paralithic:0.3.2") - "shadedApi"("com.dfsek:Tectonic:1.3.1") + "shadedApi"("com.dfsek:Tectonic:1.4.0") "shadedApi"("net.jafama:jafama:2.3.2") "shadedApi"("org.yaml:snakeyaml:1.27") "shadedApi"("org.ow2.asm:asm:9.0") diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackLoadEvent.java index 7aa7ab8a4..e995c8897 100644 --- a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackLoadEvent.java +++ b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackLoadEvent.java @@ -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 configLoader; - public ConfigPackLoadEvent(ConfigPack pack) { + public ConfigPackLoadEvent(ConfigPack pack, ExceptionalConsumer 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 { + void accept(T value) throws ConfigException; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPostLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPostLoadEvent.java index 138de647c..1398ec219 100644 --- a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPostLoadEvent.java +++ b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPostLoadEvent.java @@ -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 loader) { + super(pack, loader); } } diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPreLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPreLoadEvent.java index 317603c9e..1ac2de54d 100644 --- a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPreLoadEvent.java +++ b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPreLoadEvent.java @@ -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 configLoader) { + super(pack, configLoader); } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/ZeroArgFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/ZeroArgFunctionBuilder.java index 897f88726..0bc7beff1 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/ZeroArgFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/ZeroArgFunctionBuilder.java @@ -42,7 +42,7 @@ public class ZeroArgFunctionBuilder implements FunctionBuilder> { @Override public int argNumber() { - return 1; + return 0; } @Override diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedPulledBlock.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedPulledBlock.java index 8132a53a8..e82a061d8 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedPulledBlock.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedPulledBlock.java @@ -15,7 +15,7 @@ public class BufferedPulledBlock implements BufferedItem { @Override public void paste(Location origin) { Block pos = origin.getBlock(); - while(pos.getY() > 0) { + while(pos.getY() > origin.getWorld().getMinHeight()) { if(!pos.isEmpty()) { pos.setBlockData(data, false); break; diff --git a/common/src/main/java/com/dfsek/terra/api/transform/NotNullValidator.java b/common/src/main/java/com/dfsek/terra/api/transform/NotNullValidator.java deleted file mode 100644 index b94b7be39..000000000 --- a/common/src/main/java/com/dfsek/terra/api/transform/NotNullValidator.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.api.transform; - -public class NotNullValidator implements Validator { - @Override - public boolean validate(T value) { - return !(value == null); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/Validator.java b/common/src/main/java/com/dfsek/terra/api/transform/Validator.java index c9ba5db9e..b22b7c08b 100644 --- a/common/src/main/java/com/dfsek/terra/api/transform/Validator.java +++ b/common/src/main/java/com/dfsek/terra/api/transform/Validator.java @@ -1,6 +1,12 @@ package com.dfsek.terra.api.transform; +import java.util.Objects; + public interface Validator { boolean validate(T value) throws TransformException; + + static Validator notNull() { + return Objects::nonNull; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java b/common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java index 71e2b0de5..cfeadc836 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java +++ b/common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java @@ -1,6 +1,7 @@ package com.dfsek.terra.api.world.carving; import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.world.World; import net.jafama.FastMath; import java.util.Random; @@ -85,7 +86,7 @@ public abstract class Worm { return rad[index]; } - public void carve(int chunkX, int chunkZ, BiConsumer consumer) { + public void carve(int chunkX, int chunkZ, BiConsumer consumer, World world) { int xRad = getRadius(0); int yRad = getRadius(1); int zRad = getRadius(2); @@ -97,7 +98,7 @@ public abstract class Worm { if(!(FastMath.floorDiv(origin.getBlockZ() + z, 16) == chunkZ)) continue; for(int y = -yRad - 1; y <= yRad + 1; y++) { Vector3 position = origin.clone().add(new Vector3(x, y, z)); - if(position.getY() < 0 || position.getY() > 255) continue; + if(position.getY() < world.getMinHeight() || position.getY() > world.getMaxHeight()) continue; double eq = ellipseEquation(x, y, z, xRad, yRad, zRad); if(eq <= 1 && y >= -yRad - 1 + bottomCut && y <= yRad + 1 - topCut) { diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolder.java b/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolder.java index 743bbba14..256f82eed 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolder.java +++ b/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolder.java @@ -4,12 +4,19 @@ import com.dfsek.terra.api.world.palette.Palette; public class PaletteHolder { private final Palette[] palettes; + private final int offset; - protected PaletteHolder(Palette[] palettes) { + protected PaletteHolder(Palette[] palettes, int offset) { this.palettes = palettes; + this.offset = offset; } public Palette getPalette(int y) { - return palettes[y]; + int index = y + offset; + return index >= 0 + ? index < palettes.length + ? palettes[index] + : palettes[palettes.length - 1] + : palettes[0]; } } diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolderBuilder.java b/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolderBuilder.java index 451567113..17587ac6a 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolderBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolderBuilder.java @@ -16,8 +16,12 @@ public class PaletteHolderBuilder { @SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"}) public PaletteHolder build() { - Palette[] palettes = new Palette[paletteMap.lastKey() + 1]; - for(int y = 0; y <= FastMath.max(paletteMap.lastKey(), 255); y++) { + + int min = FastMath.min(paletteMap.keySet().stream().min(Integer::compareTo).orElse(0), 0); + int max = FastMath.max(paletteMap.keySet().stream().max(Integer::compareTo).orElse(255), 255); + + Palette[] palettes = new Palette[paletteMap.lastKey() + 1 - min]; + for(int y = min; y <= FastMath.max(paletteMap.lastKey(), max); y++) { Palette d = null; for(Map.Entry e : paletteMap.entrySet()) { if(e.getKey() >= y) { @@ -26,8 +30,8 @@ public class PaletteHolderBuilder { } } if(d == null) throw new IllegalArgumentException("No palette for Y=" + y); - palettes[y] = d; + palettes[y - min] = d; } - return new PaletteHolder(palettes); + return new PaletteHolder(palettes, -min); } } diff --git a/common/src/main/java/com/dfsek/terra/carving/CarverCache.java b/common/src/main/java/com/dfsek/terra/carving/CarverCache.java index 00d3427a1..096635943 100644 --- a/common/src/main/java/com/dfsek/terra/carving/CarverCache.java +++ b/common/src/main/java/com/dfsek/terra/carving/CarverCache.java @@ -15,6 +15,7 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.List; import java.util.Random; @@ -41,13 +42,13 @@ public class CarverCache { carving.step(); TerraBiome biome = provider.getBiome(carving.getRunning().toLocation(w)); if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(CarverCache.this.carver)) { // Stop if we enter a biome this carver is not present in - return new GlueList<>(); + return Collections.emptyList(); } points.add(carving.getPoint()); } return points; } - return new GlueList<>(); + return Collections.emptyList(); } }); } diff --git a/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java b/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java index a15d1710c..73e302e70 100644 --- a/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java +++ b/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java @@ -4,6 +4,7 @@ import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.api.util.collections.ProbabilityCollection; +import net.jafama.FastMath; import java.util.Map; import java.util.TreeMap; @@ -14,6 +15,7 @@ public class CarverPalette { private final MaterialSet replace; private final TreeMap> map = new TreeMap<>(); private ProbabilityCollection[] layers; + private int offset = 0; public CarverPalette(MaterialSet replaceable, boolean blacklist) { this.blacklist = blacklist; @@ -26,7 +28,12 @@ public class CarverPalette { } public ProbabilityCollection get(int y) { - return layers[y]; + int index = y + offset; + return index >= 0 + ? index < layers.length + ? layers[index] + : layers[layers.length - 1] + : layers[0]; } public boolean canReplace(BlockType material) { @@ -37,9 +44,11 @@ public class CarverPalette { * Build the palette to an array. */ public void build() { - int size = map.lastKey() + 1; - layers = new ProbabilityCollection[size]; - for(int y = 0; y < size; y++) { + int min = FastMath.min(map.keySet().stream().min(Integer::compareTo).orElse(0), 0); + int max = FastMath.max(map.keySet().stream().max(Integer::compareTo).orElse(255), 255); + + layers = new ProbabilityCollection[map.lastKey() + 1 - min]; + for(int y = min; y <= FastMath.max(map.lastKey(), max); y++) { ProbabilityCollection d = null; for(Map.Entry> e : map.entrySet()) { if(e.getKey() >= y) { @@ -47,8 +56,9 @@ public class CarverPalette { break; } } - if(d == null) throw new IllegalArgumentException("Null collection at Y=" + y); - layers[y] = d; + if(d == null) throw new IllegalArgumentException("No palette for Y=" + y); + layers[y - min] = d; } + offset = -min; } } diff --git a/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java b/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java index 79bd897a4..3da18626a 100644 --- a/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java +++ b/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java @@ -116,7 +116,7 @@ public class UserDefinedCarver extends Carver { Vector3 origin = point.getOrigin(); if(FastMath.floorDiv(origin.getBlockX(), 16) != chunkX && FastMath.floorDiv(origin.getBlockZ(), 16) != chunkZ) // We only want to carve this chunk. return; - point.carve(chunkX, chunkZ, consumer); + point.carve(chunkX, chunkZ, consumer, w); }); } } diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeInfoCommand.java b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeInfoCommand.java index 4fe3fe2ac..b1d0ffe1b 100644 --- a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeInfoCommand.java +++ b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeInfoCommand.java @@ -29,19 +29,24 @@ public class BiomeInfoCommand implements CommandTemplate { @Override public void execute(CommandSender sender) { - sender.sendMessage("Biome info for \"" + biome.getID() + "\"."); sender.sendMessage("Vanilla biome: " + biome.getVanillaBiomes()); if(biome instanceof UserDefinedBiome) { BiomeTemplate bio = ((UserDefinedBiome) biome).getConfig(); - if(bio.getExtend() != null) sender.sendMessage("Extends: " + bio.getExtend()); + if(bio.getExtended().size() == 0) { + sender.sendMessage("No Parent Biomes"); + } else { + sender.sendMessage("------Parent Biomes-----"); + bio.getExtended().forEach(id -> sender.sendMessage(" - " + id)); + } List structureConfigs = bio.getStructures(); - if(structureConfigs.size() == 0) sender.sendMessage("No Structures"); - else { + if(structureConfigs.size() == 0) { + sender.sendMessage("No Structures"); + } else { sender.sendMessage("-------Structures-------"); for(TerraStructure c : structureConfigs) { sender.sendMessage(" - " + c.getTemplate().getID()); diff --git a/common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java index 17a3c9222..e69de29bb 100644 --- a/common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java +++ b/common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java @@ -1,148 +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.api.world.palette.slant.SlantHolder; -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 gens = Collections.synchronizedMap(new HashMap<>()); - - private String noiseEquation; - - private String elevationEquation; - - private String carvingEquation; - - private Scope varScope; - - private Map noiseBuilderMap; - - private Map functionTemplateMap; - - private PaletteHolder palettes; - - private SlantHolder 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 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 noiseBuilderMap) { - this.noiseBuilderMap = noiseBuilderMap; - } - - public PaletteHolder getPalettes() { - return palettes; - } - - public void setPalettes(PaletteHolder palettes) { - this.palettes = palettes; - } - - public SlantHolder getSlantPalettes() { - return slantPalettes; - } - - public void setSlantPalettes(SlantHolder 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; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java index fdbf6ea90..be6ea19d9 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java @@ -13,9 +13,9 @@ public class OreFactory implements ConfigFactory { BlockData m = config.getMaterial(); switch(config.getType()) { case SPHERE: - return new DeformedSphereOre(m, config.getReplaceable(), config.doPhysics(), config.getDeform(), config.getDeformFrequency(), config.getSize(), main); + return new DeformedSphereOre(m, config.getReplaceable(), config.doPhysics(), config.getDeform(), config.getDeformFrequency(), config.getSize(), main, config.getMaterialOverrides()); case VANILLA: - return new VanillaOre(m, config.getReplaceable(), config.doPhysics(), config.getSize(), main); + return new VanillaOre(m, config.getReplaceable(), config.doPhysics(), config.getSize(), main, config.getMaterialOverrides()); } return null; } diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java index eb731d054..bfbdfc6fa 100644 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java +++ b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java @@ -4,6 +4,7 @@ import com.dfsek.paralithic.eval.parser.Scope; import com.dfsek.tectonic.abstraction.AbstractConfigLoader; import com.dfsek.tectonic.config.ConfigTemplate; import com.dfsek.tectonic.config.Configuration; +import com.dfsek.tectonic.config.Configuration; import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; @@ -74,6 +75,9 @@ public class ConfigPack implements LoaderRegistrar { private final Scope varScope = new Scope(); private final TerraPlugin main; private final Loader loader; + + private final Configuration configuration; + private final BiomeProvider.BiomeProviderBuilder biomeProviderBuilder; @@ -99,11 +103,15 @@ 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(); @@ -142,9 +150,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(); @@ -199,8 +210,6 @@ public class ConfigPack implements LoaderRegistrar { @SuppressWarnings({"unchecked", "rawtypes"}) private void load(long start, TerraPlugin main) throws ConfigException { - main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this)); - for(Map.Entry var : template.getVariables().entrySet()) { varScope.create(var.getKey(), var.getValue()); } @@ -242,7 +251,7 @@ public class ConfigPack implements LoaderRegistrar { } } - 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."); } diff --git a/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java index baff39e3b..6a355a3e6 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java @@ -30,6 +30,7 @@ import com.dfsek.terra.world.population.items.flora.FloraLayer; import com.dfsek.terra.world.population.items.ores.OreHolder; import com.dfsek.terra.world.population.items.tree.TreeLayer; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -39,7 +40,6 @@ import java.util.Set; @SuppressWarnings({"FieldMayBeFinal", "unused"}) public class BiomeTemplate extends AbstractableTemplate implements ValidatedConfigTemplate { - private final ConfigPack pack; @Value("id") @@ -47,7 +47,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf @Value("extends") @Default - private String extend = null; + private List extended = Collections.emptyList(); @Value("variables") @Abstractable @@ -190,6 +190,10 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf @Default private Map colors = new HashMap<>(); // Plain ol' map, so platforms can decide what to do with colors (if anything). + public List getExtended() { + return extended; + } + public Set getTags() { return tags; } @@ -222,10 +226,6 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf return interpolateElevation; } - public String getExtend() { - return extend; - } - public SlantHolder getSlant() { return slant; } diff --git a/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java index b3ecdb61f..82de9a134 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java @@ -5,9 +5,13 @@ import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.util.collections.MaterialSet; import com.dfsek.terra.world.population.items.ores.Ore; +import java.util.HashMap; +import java.util.Map; + @SuppressWarnings({"unused", "FieldMayBeFinal"}) public class OreTemplate extends AbstractableTemplate { @Value("id") @@ -17,6 +21,11 @@ public class OreTemplate extends AbstractableTemplate { @Abstractable private BlockData material; + @Value("material-overrides") + @Default + @Abstractable + private Map materials = new HashMap<>(); + @Value("algorithm") @Abstractable @Default @@ -76,4 +85,8 @@ public class OreTemplate extends AbstractableTemplate { public Ore.Type getType() { return oreType; } + + public Map getMaterialOverrides() { + return materials; + } } diff --git a/common/src/main/java/com/dfsek/terra/world/TerraWorld.java b/common/src/main/java/com/dfsek/terra/world/TerraWorld.java index f92635ef3..a989d3906 100644 --- a/common/src/main/java/com/dfsek/terra/world/TerraWorld.java +++ b/common/src/main/java/com/dfsek/terra/world/TerraWorld.java @@ -6,10 +6,8 @@ import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -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; @@ -70,7 +68,7 @@ public class TerraWorld { double noise = sampler.sample(fdX, y, fdZ); if(noise > 0) { int level = 0; - for(int yi = world.getMaxHeight(); yi > y; yi--) { + for(int yi = world.getMaxHeight() - 1; yi > y; yi--) { if(sampler.sample(fdX, yi, fdZ) > 0) level++; else level = 0; } diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator3D.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator3D.java index 727a8e25e..9d71d8774 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator3D.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator3D.java @@ -59,7 +59,7 @@ public class ChunkInterpolator3D implements ChunkInterpolator { } for(int y = 0; y < size + 1; y++) { - noiseStorage[x][z][y] = computeNoise(genMap, (x << 2) + xOrigin, y << 2, (z << 2) + zOrigin); + noiseStorage[x][z][y] = computeNoise(genMap, (x << 2) + xOrigin, (y << 2) + min, (z << 2) + zOrigin); } } } @@ -98,10 +98,10 @@ public class ChunkInterpolator3D implements ChunkInterpolator { */ @Override public double getNoise(double x, double y, double z) { - return interpGrid[reRange(((int) x) / 4, 3)][FastMath.max(FastMath.min(((int) y), max), min) / 4][reRange(((int) z) / 4, 3)].trilerp((x % 4) / 4, (y % 4) / 4, (z % 4) / 4); + return interpGrid[reRange(((int) x) / 4, 3)][(FastMath.max(FastMath.min(((int) y), max), min) - min) / 4][reRange(((int) z) / 4, 3)].trilerp((x % 4) / 4, (y % 4) / 4, (z % 4) / 4); } public double getNoise(int x, int y, int z) { - return interpGrid[x / 4][y / 4][z / 4].trilerp((double) (x % 4) / 4, (double) (y % 4) / 4, (double) (z % 4) / 4); + return interpGrid[x / 4][(y - min) / 4][z / 4].trilerp((double) (x % 4) / 4, (double) (y % 4) / 4, (double) (z % 4) / 4); } } diff --git a/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java index 8b6e0bab0..09ce5976a 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java +++ b/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java @@ -90,7 +90,7 @@ public class CavePopulator implements TerraBlockPopulator, Chunkified { Location mut = l.clone(); BlockData orig = l.getBlock().getBlockData(); do mut.subtract(0, 1, 0); - while(mut.getY() > 0 && mut.getBlock().getBlockData().matches(orig)); + while(mut.getY() > world.getMinHeight() && mut.getBlock().getBlockData().matches(orig)); try { if(template.getShift().get(entry.getValue().getBlockType()).contains(mut.getBlock().getBlockData().getBlockType())) { mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(entry.getValue().getBlockType(), BlockType::getDefaultData), false); diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java index 2b4ea13ee..2bc782196 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java @@ -6,10 +6,11 @@ import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.handle.WorldHandle; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.util.collections.MaterialSet; +import java.util.Map; import java.util.Random; public class DeformedSphereOre extends Ore { @@ -17,8 +18,8 @@ public class DeformedSphereOre extends Ore { private final double deformFrequency; private final Range size; - public DeformedSphereOre(BlockData material, MaterialSet replaceable, boolean applyGravity, double deform, double deformFrequency, Range size, TerraPlugin main) { - super(material, replaceable, applyGravity, main); + public DeformedSphereOre(BlockData material, MaterialSet replaceable, boolean applyGravity, double deform, double deformFrequency, Range size, TerraPlugin main, Map materials) { + super(material, replaceable, applyGravity, main, materials); this.deform = deform; this.deformFrequency = deformFrequency; this.size = size; @@ -27,7 +28,6 @@ public class DeformedSphereOre extends Ore { @Override public void generate(Vector3 origin, Chunk c, Random r) { - WorldHandle handle = main.getWorldHandle(); OpenSimplex2Sampler ore = new OpenSimplex2Sampler(r.nextInt()); ore.setFrequency(deformFrequency); int rad = size.get(r); @@ -35,12 +35,13 @@ public class DeformedSphereOre extends Ore { for(int y = -rad; y <= rad; y++) { for(int z = -rad; z <= rad; z++) { Vector3 oreLoc = origin.clone().add(new Vector3(x, y, z)); - if(oreLoc.getBlockX() > 15 || oreLoc.getBlockZ() > 15 || oreLoc.getBlockY() > 255 || oreLoc.getBlockX() < 0 || oreLoc.getBlockZ() < 0 || oreLoc.getBlockY() < 0) + if(oreLoc.getBlockX() > 15 || oreLoc.getBlockZ() > 15 || oreLoc.getBlockY() > c.getWorld().getMaxHeight() || oreLoc.getBlockX() < 0 || oreLoc.getBlockZ() < 0 || oreLoc.getBlockY() < c.getWorld().getMinHeight()) continue; if(oreLoc.distance(origin) < (rad + 0.5) * ((ore.getNoise(x, y, z) + 1) * deform)) { Block b = c.getBlock(oreLoc.getBlockX(), oreLoc.getBlockY(), oreLoc.getBlockZ()); - if(getReplaceable().contains(b.getType()) && b.getLocation().getY() >= 0) - b.setBlockData(getMaterial(), isApplyGravity()); + BlockType type = b.getType(); + if(getReplaceable().contains(type) && b.getLocation().getY() >= c.getWorld().getMinHeight()) + b.setBlockData(getMaterial(type), isApplyGravity()); } } } diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java index e7f3faedd..d52bdf4a0 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java @@ -3,9 +3,11 @@ package com.dfsek.terra.world.population.items.ores; import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.util.collections.MaterialSet; +import java.util.Map; import java.util.Random; public abstract class Ore { @@ -14,18 +16,20 @@ public abstract class Ore { private final MaterialSet replaceable; private final boolean applyGravity; protected TerraPlugin main; + private final Map materials; - public Ore(BlockData material, MaterialSet replaceable, boolean applyGravity, TerraPlugin main) { + public Ore(BlockData material, MaterialSet replaceable, boolean applyGravity, TerraPlugin main, Map materials) { this.material = material; this.replaceable = replaceable; this.applyGravity = applyGravity; this.main = main; + this.materials = materials; } public abstract void generate(Vector3 origin, Chunk c, Random r); - public BlockData getMaterial() { - return material; + public BlockData getMaterial(BlockType replace) { + return materials.getOrDefault(replace, material); } public MaterialSet getReplaceable() { diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java index 549e1e378..0e5e5d4af 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java +++ b/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java @@ -5,18 +5,20 @@ import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.util.collections.MaterialSet; import net.jafama.FastMath; +import java.util.Map; import java.util.Random; public class VanillaOre extends Ore { private final Range sizeRange; - public VanillaOre(BlockData material, MaterialSet replaceable, boolean applyGravity, Range size, TerraPlugin main) { - super(material, replaceable, applyGravity, main); + public VanillaOre(BlockData material, MaterialSet replaceable, boolean applyGravity, Range size, TerraPlugin main, Map materials) { + super(material, replaceable, applyGravity, main, materials); this.sizeRange = size; } @@ -67,8 +69,9 @@ public class VanillaOre extends Ore { double d15 = (z + 0.5D - (d3 + (d4 - d3) * iFactor)) / (d11 / 2.0D); if(x > 15 || z > 15 || y > 255 || x < 0 || z < 0 || y < 0) continue; Block block = chunk.getBlock(x, y, z); - if((d13 * d13 + d14 * d14 + d15 * d15 < 1.0D) && getReplaceable().contains(block.getType())) { - block.setBlockData(getMaterial(), isApplyGravity()); + BlockType type = block.getType(); + if((d13 * d13 + d14 * d14 + d15 * d15 < 1.0D) && getReplaceable().contains(type)) { + block.setBlockData(getMaterial(type), isApplyGravity()); } } } diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index 21e811d94..198af9683 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -11,7 +11,6 @@ cache: carver: 512 structure: 32 sampler: 128 -master-disable: - caves: false + biome-provider: 32 script: max-recursion: 1000 \ No newline at end of file diff --git a/common/src/main/resources/lang/cs_cz.yml b/common/src/main/resources/lang/cs_cz.yml new file mode 100644 index 000000000..c01c6fcf9 --- /dev/null +++ b/common/src/main/resources/lang/cs_cz.yml @@ -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/" diff --git a/gradle.properties b/gradle.properties index 94dc0b5ce..7221e08e0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,3 +8,9 @@ org.gradle.caching=true org.gradle.warning.mode=all #org.gradle.logging.level=info #org.gradle.configureondemand=true +# 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 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a29c5e5c5..cc9cd46e9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists org.gradle.jvmargs=-Xmx4096m \ No newline at end of file diff --git a/platforms/bukkit/build.gradle.kts b/platforms/bukkit/build.gradle.kts index 1a4d3cce6..4c7c3648f 100644 --- a/platforms/bukkit/build.gradle.kts +++ b/platforms/bukkit/build.gradle.kts @@ -15,7 +15,7 @@ configureCommon() group = "com.dfsek.terra.bukkit" -val mcVersion = "1.16.5" +val mcVersion = "1.17" val testDir = "target/server" val testMem = "3G" @@ -25,7 +25,7 @@ val purpurURL = "https://ci.pl3x.net/job/Purpur/lastSuccessfulBuild/artifact/fin dependencies { "shadedApi"(project(":common")) - "compileOnly"("com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT") + "compileOnly"("io.papermc.paper:paper-api:1.17-R0.1-SNAPSHOT") "shadedImplementation"("io.papermc:paperlib:1.0.5") "shadedImplementation"("org.bstats:bstats-bukkit:1.7") diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java index acc83d986..189fc5139 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java @@ -84,7 +84,8 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { static { String ver = Bukkit.getServer().getClass().getPackage().getName(); - if(ver.contains("1_16")) BUKKIT_VERSION = BukkitVersion.V1_16; + if(ver.contains("1_17")) BUKKIT_VERSION = BukkitVersion.V1_17; + else if(ver.contains("1_16")) BUKKIT_VERSION = BukkitVersion.V1_16; else if(ver.contains("1_15")) BUKKIT_VERSION = BukkitVersion.V1_15; else if(ver.contains("1_14")) BUKKIT_VERSION = BukkitVersion.V1_14; else if(ver.contains("1_13")) BUKKIT_VERSION = BukkitVersion.V1_13; @@ -316,6 +317,8 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { V1_16(16), + V1_17(17), + UNKNOWN(Integer.MAX_VALUE); // Assume unknown version is latest. private final int index; diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java index f2013e7a6..a94300592 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java @@ -19,7 +19,6 @@ public class PaperListener implements Listener { @EventHandler public void onStructureLocate(StructureLocateEvent e) { if(!BukkitAdapter.adapt(e.getWorld()).isTerraWorld()) return; - e.setResult(null); // Assume no result. String name = "minecraft:" + e.getType().getName(); main.getDebugLogger().info("Overriding structure location for \"" + name + "\""); TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getWorld())); @@ -32,10 +31,8 @@ public class PaperListener implements Listener { }, main); finder.run(); // Do this synchronously. } else { - main.logger().warning("No overrides are defined for \"" + name + "\""); + e.setResult(e.getOrigin()); + main.logger().warning("No overrides are defined for \"" + name + "\". Locating this structure will NOT work properly!"); } - } - - } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java index 48f3b7863..158041ae5 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java @@ -70,7 +70,7 @@ public class BukkitWorld implements World { @Override public int getMinHeight() { - return 0; + return delegate.getMinHeight(); } @Override diff --git a/platforms/bukkit/src/main/resources/plugin.yml b/platforms/bukkit/src/main/resources/plugin.yml index 0b0a1fafc..1daeb981f 100644 --- a/platforms/bukkit/src/main/resources/plugin.yml +++ b/platforms/bukkit/src/main/resources/plugin.yml @@ -3,16 +3,13 @@ main: "com.dfsek.terra.bukkit.TerraBukkitPlugin" version: "@VERSION@" load: "STARTUP" author: dfsek +website: "@WIKI@" api-version: "1.13" -description: "An insanely powerful free & open-source data-driven world generator." +description: "@DESCRIPTION@" softdepend: [ "WorldEdit" ] commands: terra: description: "Terra base command" usage: "/terra " aliases: [ "te" ] - permission: "terra.command" - locate: - description: "Locate a Terra Structure" - usage: "/locate " - permission: "terra.locate" \ No newline at end of file + permission: "terra.command" \ No newline at end of file diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 38aafb791..0625cd483 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -7,7 +7,7 @@ import net.fabricmc.loom.task.RemapJarTask plugins { `java-library` `maven-publish` - id("fabric-loom").version("0.6-SNAPSHOT") + id("fabric-loom").version("0.8-SNAPSHOT") id("com.modrinth.minotaur").version("1.1.0") } @@ -23,11 +23,22 @@ group = "com.dfsek.terra.fabric" dependencies { "shadedApi"(project(":common")) - "minecraft"("com.mojang:minecraft:1.16.5") - "mappings"("net.fabricmc:yarn:1.16.5+build.5:v2") - "modImplementation"("net.fabricmc:fabric-loader:0.11.2") + "minecraft"("com.mojang:minecraft:1.17") + "mappings"("net.fabricmc:yarn:1.17+build.1:v2") + "modImplementation"("net.fabricmc:fabric-loader:0.11.3") - "modImplementation"("net.fabricmc.fabric-api:fabric-api:0.31.0+1.16") + "modCompileOnly"("com.sk89q.worldedit:worldedit-fabric-mc1.16:7.2.0-SNAPSHOT") { + exclude(group = "com.google.guava", module = "guava") + exclude(group = "com.google.code.gson", module = "gson") + exclude(group = "it.unimi.dsi", module = "fastutil") + exclude(group = "org.apache.logging.log4j", module = "log4j-api") + exclude(group = "org.apache.logging.log4j", module = "log4j-core") + } +} + +tasks.named("shadowJar") { + relocate("org.json", "com.dfsek.terra.lib.json") + relocate("org.yaml", "com.dfsek.terra.lib.yaml") } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java index 78b6c123d..735886486 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java @@ -1,5 +1,7 @@ package com.dfsek.terra.fabric; +import com.dfsek.tectonic.exception.ConfigException; +import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.TypeRegistry; import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.addons.TerraAddon; @@ -8,31 +10,29 @@ import com.dfsek.terra.api.addons.annotations.Author; import com.dfsek.terra.api.addons.annotations.Version; import com.dfsek.terra.api.command.CommandManager; import com.dfsek.terra.api.command.TerraCommandManager; -import com.dfsek.terra.api.command.exception.CommandException; import com.dfsek.terra.api.command.exception.MalformedCommandException; import com.dfsek.terra.api.event.EventListener; import com.dfsek.terra.api.event.EventManager; import com.dfsek.terra.api.event.TerraEventManager; import com.dfsek.terra.api.event.annotations.Global; import com.dfsek.terra.api.event.annotations.Priority; +import com.dfsek.terra.api.event.events.config.ConfigPackPostLoadEvent; import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent; -import com.dfsek.terra.api.platform.CommandSender; import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.entity.Entity; import com.dfsek.terra.api.platform.handle.ItemHandle; import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.Tree; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.registry.LockedRegistry; -import com.dfsek.terra.api.transform.NotNullValidator; import com.dfsek.terra.api.transform.Transformer; +import com.dfsek.terra.api.transform.Validator; +import com.dfsek.terra.api.util.generic.pair.Pair; import com.dfsek.terra.api.util.logging.DebugLogger; import com.dfsek.terra.api.util.logging.Logger; import com.dfsek.terra.commands.CommandUtil; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.builder.BiomeBuilder; import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.config.lang.Language; import com.dfsek.terra.config.pack.ConfigPack; @@ -40,112 +40,117 @@ import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.dfsek.terra.fabric.generation.PopulatorFeature; import com.dfsek.terra.fabric.generation.TerraBiomeSource; +import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions; +import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.fabric.event.BiomeRegistrationEvent; +import com.dfsek.terra.fabric.event.GameInitializationEvent; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.generation.PopulatorFeature; +import com.dfsek.terra.fabric.generation.TerraBiomeSource; import com.dfsek.terra.fabric.handle.FabricItemHandle; import com.dfsek.terra.fabric.handle.FabricWorldHandle; import com.dfsek.terra.fabric.mixin.access.BiomeEffectsAccessor; import com.dfsek.terra.fabric.mixin.access.GeneratorTypeAccessor; +import com.dfsek.terra.fabric.util.FabricUtil; +import com.dfsek.terra.fabric.util.ProtoBiome; import com.dfsek.terra.profiler.Profiler; import com.dfsek.terra.profiler.ProfilerImpl; import com.dfsek.terra.registry.exception.DuplicateEntryException; import com.dfsek.terra.registry.master.AddonRegistry; import com.dfsek.terra.registry.master.ConfigRegistry; import com.dfsek.terra.world.TerraWorld; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.block.Blocks; -import net.minecraft.client.world.GeneratorType; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.LiteralText; +import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.WorldAccess; import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.BiomeEffects; -import net.minecraft.world.biome.GenerationSettings; -import net.minecraft.world.gen.GenerationStep; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; +import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.gen.decorator.Decorator; import net.minecraft.world.gen.decorator.NopeDecoratorConfig; import net.minecraft.world.gen.feature.ConfiguredFeature; import net.minecraft.world.gen.feature.ConfiguredFeatures; import net.minecraft.world.gen.feature.DefaultFeatureConfig; import net.minecraft.world.gen.feature.FeatureConfig; -import net.minecraft.world.gen.surfacebuilder.SurfaceBuilder; -import net.minecraft.world.gen.surfacebuilder.TernarySurfaceConfig; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; -import java.util.List; -import java.util.Locale; import java.util.Map; -import static net.minecraft.server.command.CommandManager.argument; -import static net.minecraft.server.command.CommandManager.literal; - public class TerraFabricPlugin implements TerraPlugin, ModInitializer { - + private final org.apache.logging.log4j.Logger log4jLogger = LogManager.getLogger(); public static final PopulatorFeature POPULATOR_FEATURE = new PopulatorFeature(DefaultFeatureConfig.CODEC); public static final ConfiguredFeature POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configure(FeatureConfig.DEFAULT).decorate(Decorator.NOPE.configure(NopeDecoratorConfig.INSTANCE)); private static TerraFabricPlugin instance; - private final Map worldMap = new HashMap<>(); + private final Map> worldMap = new HashMap<>(); + + public Map> getWorldMap() { + return worldMap; + } + private final EventManager eventManager = new TerraEventManager(this); private final GenericLoaders genericLoaders = new GenericLoaders(this); private final Profiler profiler = new ProfilerImpl(); private final Logger logger = new Logger() { - private final org.apache.logging.log4j.Logger logger = LogManager.getLogger(); - @Override public void info(String message) { - logger.info(message); + log4jLogger.info(message); } @Override public void warning(String message) { - logger.warn(message); + log4jLogger.warn(message); } @Override public void severe(String message) { - logger.error(message); + log4jLogger.error(message); } }; + private final DebugLogger debugLogger = new DebugLogger(logger); private final ItemHandle itemHandle = new FabricItemHandle(); private final WorldHandle worldHandle = new FabricWorldHandle(); - private final ConfigRegistry registry = new ConfigRegistry(); - private final CheckedRegistry checkedRegistry = new CheckedRegistry<>(registry); - private final AddonRegistry addonRegistry = new AddonRegistry(new FabricAddon(this), this); + private final ConfigRegistry configRegistry = new ConfigRegistry(); + private final CheckedRegistry checkedRegistry = new CheckedRegistry<>(configRegistry); + + private final FabricAddon fabricAddon = new FabricAddon(); + private final AddonRegistry addonRegistry = new AddonRegistry(fabricAddon, this); private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); + private final PluginConfig config = new PluginConfig(); - private final Transformer biomeFixer = new Transformer.Builder() - .addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse(id)), new NotNullValidator<>()) - .addTransform(id -> BuiltinRegistries.BIOME.get(Identifier.tryParse("minecraft:" + id.toLowerCase())), new NotNullValidator<>()).build(); + + private final Transformer biomeFixer = new Transformer.Builder() + .addTransform(this::parseBiome, Validator.notNull()) + .addTransform(id -> parseBiome("minecraft:" + id.toLowerCase()), Validator.notNull()).build(); + + private ProtoBiome parseBiome(String id) { + Identifier identifier = Identifier.tryParse(id); + if(BuiltinRegistries.BIOME.get(identifier) == null) return null; // failure. + return new ProtoBiome(identifier); + } + private File dataFolder; + private final CommandManager manager = new TerraCommandManager(this); + + public CommandManager getManager() { + return manager; + } public static TerraFabricPlugin getInstance() { return instance; } - public static String createBiomeID(ConfigPack pack, String biomeID) { - return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT); - } - @Override public WorldHandle getWorldHandle() { return worldHandle; @@ -153,15 +158,12 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { @Override public TerraWorld getWorld(World world) { - return worldMap.computeIfAbsent(world.getSeed(), w -> { - logger.info("Loading world " + w); - return new TerraWorld(world, ((FabricChunkGeneratorWrapper) world.getGenerator()).getPack(), this); - }); + return getWorld(((WorldAccess) world).getDimension()); } - public TerraWorld getWorld(long seed) { - TerraWorld world = worldMap.get(seed); - if(world == null) throw new IllegalArgumentException("No world exists with seed " + seed); + public TerraWorld getWorld(DimensionType type) { + TerraWorld world = worldMap.get(type).getRight(); + if(world == null) throw new IllegalArgumentException("No world exists with dimension type " + type); return world; } @@ -180,11 +182,20 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { return dataFolder; } + @Override + public boolean isDebug() { + return config.isDebug(); + } + @Override public Language getLanguage() { return LangUtil.getLanguage(); } + public FabricAddon getFabricAddon() { + return fabricAddon; + } + @Override public CheckedRegistry getConfigRegistry() { return checkedRegistry; @@ -199,15 +210,12 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { public boolean reload() { config.load(this); LangUtil.load(config.getLanguage(), this); // Load language. - boolean succeed = registry.loadAll(this); - Map newMap = new HashMap<>(); - worldMap.forEach((seed, tw) -> { - tw.getConfig().getSamplerCache().clear(); - String packID = tw.getConfig().getTemplate().getID(); - newMap.put(seed, new TerraWorld(tw.getWorld(), registry.get(packID), this)); + boolean succeed = configRegistry.loadAll(this); + worldMap.forEach((seed, pair) -> { + pair.getRight().getConfig().getSamplerCache().clear(); + String packID = pair.getRight().getConfig().getTemplate().getID(); + pair.setRight(new TerraWorld(pair.getRight().getWorld(), configRegistry.get(packID), this)); }); - worldMap.clear(); - worldMap.putAll(newMap); return succeed; } @@ -241,50 +249,12 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { genericLoaders.register(registry); registry .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) - .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> biomeFixer.translate((String) o)); - } - - private Biome createBiome(BiomeBuilder biome) { - BiomeTemplate template = biome.getTemplate(); - Map colors = template.getColors(); - - Biome vanilla = (Biome) (new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle(); - - GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); - generationSettings.surfaceBuilder(SurfaceBuilder.DEFAULT.withConfig(new TernarySurfaceConfig(Blocks.GRASS_BLOCK.getDefaultState(), Blocks.DIRT.getDefaultState(), Blocks.GRAVEL.getDefaultState()))); // It needs a surfacebuilder, even though we dont use it. - generationSettings.feature(GenerationStep.Feature.VEGETAL_DECORATION, POPULATOR_CONFIGURED_FEATURE); - - - BiomeEffectsAccessor accessor = (BiomeEffectsAccessor) vanilla.getEffects(); - BiomeEffects.Builder effects = new BiomeEffects.Builder() - .waterColor(colors.getOrDefault("water", accessor.getWaterColor())) - .waterFogColor(colors.getOrDefault("water-fog", accessor.getWaterFogColor())) - .fogColor(colors.getOrDefault("fog", accessor.getFogColor())) - .skyColor(colors.getOrDefault("sky", accessor.getSkyColor())) - .grassColorModifier(accessor.getGrassColorModifier()); - - if(colors.containsKey("grass")) { - effects.grassColor(colors.get("grass")); - } else { - accessor.getGrassColor().ifPresent(effects::grassColor); - } - if(colors.containsKey("foliage")) { - effects.foliageColor(colors.get("foliage")); - } else { - accessor.getFoliageColor().ifPresent(effects::foliageColor); - } - - return new Biome.Builder() - .precipitation(vanilla.getPrecipitation()) - .category(vanilla.getCategory()) - .depth(vanilla.getDepth()) - .scale(vanilla.getScale()) - .temperature(vanilla.getTemperature()) - .downfall(vanilla.getDownfall()) - .effects(effects.build()) - .spawnSettings(vanilla.getSpawnSettings()) - .generationSettings(generationSettings.build()) - .build(); + .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> biomeFixer.translate((String) o)) + .registerLoader(Identifier.class, (t, o, l) -> { + Identifier identifier = Identifier.tryParse((String) o); + if(identifier == null) throw new LoadException("Invalid identifier: " + o); + return identifier; + }); } @Override @@ -305,93 +275,21 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { } logger.info("Loaded addons."); - registry.loadAll(this); - logger.info("Loaded packs."); - - Registry.register(Registry.FEATURE, new Identifier("terra", "flora_populator"), POPULATOR_FEATURE); - RegistryKey> floraKey = RegistryKey.of(Registry.CONFIGURED_FEATURE_WORLDGEN, new Identifier("terra", "flora_populator")); + Registry.register(Registry.FEATURE, new Identifier("terra", "populator"), POPULATOR_FEATURE); + RegistryKey> floraKey = RegistryKey.of(Registry.CONFIGURED_FEATURE_KEY, new Identifier("terra", "populator")); Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, floraKey.getValue(), POPULATOR_CONFIGURED_FEATURE); - registry.forEach(pack -> pack.getRegistry(BiomeBuilder.class).forEach((id, biome) -> Registry.register(BuiltinRegistries.BIOME, new Identifier("terra", createBiomeID(pack, id)), createBiome(biome)))); // Register all Terra biomes. Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), FabricChunkGeneratorWrapper.CODEC); Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC); - if(FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { - registry.forEach(pack -> { - final GeneratorType generatorType = new GeneratorType("terra." + pack.getTemplate().getID()) { - @Override - protected ChunkGenerator getChunkGenerator(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { - return new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); - } - }; - //noinspection ConstantConditions - ((GeneratorTypeAccessor) generatorType).setTranslationKey(new LiteralText("Terra:" + pack.getTemplate().getID())); - GeneratorTypeAccessor.getValues().add(generatorType); - }); - } - - CommandManager manager = new TerraCommandManager(this); try { CommandUtil.registerAll(manager); } catch(MalformedCommandException e) { e.printStackTrace(); // TODO do something here even though this should literally never happen } - - CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> { - int max = manager.getMaxArgumentDepth(); - RequiredArgumentBuilder arg = argument("arg" + (max - 1), StringArgumentType.word()); - for(int i = 0; i < max; i++) { - RequiredArgumentBuilder next = argument("arg" + (max - i - 1), StringArgumentType.word()); - - arg = next.then(assemble(arg, manager)); - } - - dispatcher.register(literal("terra").executes(context -> 1).then(assemble(arg, manager))); - dispatcher.register(literal("te").executes(context -> 1).then(assemble(arg, manager))); - //dispatcher.register(literal("te").redirect(root)); - } - ); - - } - - private RequiredArgumentBuilder assemble(RequiredArgumentBuilder in, CommandManager manager) { - return in.suggests((context, builder) -> { - List args = parseCommand(context.getInput()); - CommandSender sender = (CommandSender) context.getSource(); - try { - sender = (Entity) context.getSource().getEntityOrThrow(); - } catch(CommandSyntaxException ignore) { - } - try { - manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest); - } catch(CommandException e) { - sender.sendMessage(e.getMessage()); - } - return builder.buildFuture(); - }).executes(context -> { - List args = parseCommand(context.getInput()); - CommandSender sender = (CommandSender) context.getSource(); - try { - sender = (Entity) context.getSource().getEntityOrThrow(); - } catch(CommandSyntaxException ignore) { - } - try { - manager.execute(args.remove(0), sender, args); - } catch(CommandException e) { - context.getSource().sendError(new LiteralText(e.getMessage())); - } - return 1; - }); - } - - private List parseCommand(String command) { - if(command.startsWith("/terra ")) command = command.substring("/terra ".length()); - else if(command.startsWith("/te ")) command = command.substring("/te ".length()); - List c = new ArrayList<>(Arrays.asList(command.split(" "))); - if(command.endsWith(" ")) c.add(""); - return c; + logger.info("Finished initialization."); } @@ -408,17 +306,12 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { @Addon("Terra-Fabric") @Author("Terra") @Version("1.0.0") - private static final class FabricAddon extends TerraAddon implements EventListener { - - private final TerraPlugin main; - - private FabricAddon(TerraPlugin main) { - this.main = main; - } + public final class FabricAddon extends TerraAddon implements EventListener { + private final Map> templates = new HashMap<>(); @Override public void initialize() { - main.getEventManager().registerListener(this, this); + eventManager.registerListener(this, this); } @Priority(Priority.LOWEST) @@ -432,7 +325,7 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { injectTree(treeRegistry, "LARGE_OAK", ConfiguredFeatures.FANCY_OAK); injectTree(treeRegistry, "LARGE_SPRUCE", ConfiguredFeatures.PINE); injectTree(treeRegistry, "SMALL_JUNGLE", ConfiguredFeatures.JUNGLE_TREE); - injectTree(treeRegistry, "SWAMP_OAK", ConfiguredFeatures.SWAMP_TREE); + injectTree(treeRegistry, "SWAMP_OAK", ConfiguredFeatures.SWAMP_OAK); injectTree(treeRegistry, "TALL_BIRCH", ConfiguredFeatures.BIRCH_TALL); injectTree(treeRegistry, "ACACIA", ConfiguredFeatures.ACACIA); injectTree(treeRegistry, "BIRCH", ConfiguredFeatures.BIRCH); @@ -444,8 +337,57 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { injectTree(treeRegistry, "MEGA_SPRUCE", ConfiguredFeatures.MEGA_SPRUCE); injectTree(treeRegistry, "CRIMSON_FUNGUS", ConfiguredFeatures.CRIMSON_FUNGI); injectTree(treeRegistry, "WARPED_FUNGUS", ConfiguredFeatures.WARPED_FUNGI); + + PreLoadCompatibilityOptions template = new PreLoadCompatibilityOptions(); + try { + event.loadTemplate(template); + } catch(ConfigException e) { + e.printStackTrace(); + } + + if(template.doRegistryInjection()) { + BuiltinRegistries.CONFIGURED_FEATURE.getEntries().forEach(entry -> { + if(!template.getExcludedRegistryFeatures().contains(entry.getKey().getValue())) { + try { + event.getPack().getTreeRegistry().add(entry.getKey().getValue().toString(), (Tree) entry.getValue()); + debugLogger.info("Injected ConfiguredFeature " + entry.getKey().getValue() + " as Tree."); + } catch(DuplicateEntryException ignored) { + } + } + }); + } + templates.put(event.getPack(), Pair.of(template, null)); } + @Priority(Priority.HIGHEST) + @Global + public void createInjectionOptions(ConfigPackPostLoadEvent event) { + PostLoadCompatibilityOptions template = new PostLoadCompatibilityOptions(); + + try { + event.loadTemplate(template); + } catch(ConfigException e) { + e.printStackTrace(); + } + + templates.get(event.getPack()).setRight(template); + } + + @Global + public void injectBiomes(BiomeRegistrationEvent event) { + logger.info("Registering biomes..."); + Registry biomeRegistry = event.getRegistryManager().get(Registry.BIOME_KEY); + configRegistry.forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> FabricUtil.registerOrOverwrite(biomeRegistry, Registry.BIOME_KEY, new Identifier("terra", FabricUtil.createBiomeID(pack, id)), FabricUtil.createBiome(biome, pack, event.getRegistryManager())))); // Register all Terra biomes. + logger.info("Biomes registered."); + } + + @Global + public void initializePacks(GameInitializationEvent event) { + TerraFabricPlugin main = TerraFabricPlugin.getInstance(); + main.logger().info("Loading config packs..."); + configRegistry.loadAll(TerraFabricPlugin.this); + logger.info("Loaded packs."); + } private void injectTree(CheckedRegistry registry, String id, ConfiguredFeature tree) { try { @@ -453,5 +395,9 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer { } catch(DuplicateEntryException ignore) { } } + + public Map> getTemplates() { + return templates; + } } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlock.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlock.java index b53bff68f..78c1211b5 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlock.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlock.java @@ -7,7 +7,7 @@ import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.block.state.BlockState; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.fabric.FabricAdapter; +import com.dfsek.terra.fabric.util.FabricAdapter; import net.minecraft.block.FluidBlock; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldAccess; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricDirectional.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricDirectional.java index 4d15d1c16..be4eb316b 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricDirectional.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricDirectional.java @@ -2,8 +2,8 @@ package com.dfsek.terra.fabric.block.data; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.data.Directional; -import com.dfsek.terra.fabric.FabricAdapter; import com.dfsek.terra.fabric.block.FabricBlockData; +import com.dfsek.terra.fabric.util.FabricAdapter; import net.minecraft.block.BlockState; import net.minecraft.state.property.DirectionProperty; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricOrientable.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricOrientable.java index 1633df9ab..d8e88d566 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricOrientable.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricOrientable.java @@ -2,8 +2,8 @@ package com.dfsek.terra.fabric.block.data; import com.dfsek.terra.api.platform.block.Axis; import com.dfsek.terra.api.platform.block.data.Orientable; -import com.dfsek.terra.fabric.FabricAdapter; import com.dfsek.terra.fabric.block.FabricBlockData; +import com.dfsek.terra.fabric.util.FabricAdapter; import net.minecraft.block.BlockState; import net.minecraft.state.property.EnumProperty; import net.minecraft.util.math.Direction; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricSlab.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricSlab.java index 390702582..cf0d0c277 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricSlab.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricSlab.java @@ -1,7 +1,7 @@ package com.dfsek.terra.fabric.block.data; import com.dfsek.terra.api.platform.block.data.Slab; -import com.dfsek.terra.fabric.FabricAdapter; +import com.dfsek.terra.fabric.util.FabricAdapter; import net.minecraft.block.BlockState; import net.minecraft.state.property.Properties; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricStairs.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricStairs.java index 098cd75d6..d18ec13da 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricStairs.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricStairs.java @@ -2,7 +2,7 @@ package com.dfsek.terra.fabric.block.data; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.data.Stairs; -import com.dfsek.terra.fabric.FabricAdapter; +import com.dfsek.terra.fabric.util.FabricAdapter; import net.minecraft.block.BlockState; import net.minecraft.state.property.Properties; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java new file mode 100644 index 000000000..ae812bed5 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.fabric.config; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.config.ConfigTemplate; +import com.dfsek.terra.config.builder.BiomeBuilder; +import net.minecraft.util.Identifier; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +@SuppressWarnings("FieldMayBeFinal") +public class PostLoadCompatibilityOptions implements ConfigTemplate { + @Value("structures.inject-biome.exclude-biomes") + @Default + private Map> excludedPerBiomeStructures = new HashMap<>(); + + @Value("features.inject-biome.exclude-biomes") + @Default + private Map> excludedPerBiomeFeatures = new HashMap<>(); + + public Map> getExcludedPerBiomeFeatures() { + return excludedPerBiomeFeatures; + } + + public Map> getExcludedPerBiomeStructures() { + return excludedPerBiomeStructures; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PreLoadCompatibilityOptions.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PreLoadCompatibilityOptions.java new file mode 100644 index 000000000..0dfbccf00 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PreLoadCompatibilityOptions.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.fabric.config; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.config.ConfigTemplate; +import net.minecraft.util.Identifier; + +import java.util.HashSet; +import java.util.Set; + +@SuppressWarnings("FieldMayBeFinal") +public class PreLoadCompatibilityOptions implements ConfigTemplate { + @Value("features.inject-registry.enable") + @Default + private boolean doRegistryInjection = false; + + @Value("features.inject-biome.enable") + @Default + private boolean doBiomeInjection = false; + + @Value("features.inject-registry.excluded-features") + @Default + private Set excludedRegistryFeatures = new HashSet<>(); + + @Value("features.inject-biome.excluded-features") + @Default + private Set excludedBiomeFeatures = new HashSet<>(); + + @Value("structures.inject-biome.excluded-features") + @Default + private Set excludedBiomeStructures = new HashSet<>(); + + public boolean doBiomeInjection() { + return doBiomeInjection; + } + + public boolean doRegistryInjection() { + return doRegistryInjection; + } + + public Set getExcludedBiomeFeatures() { + return excludedBiomeFeatures; + } + + public Set getExcludedRegistryFeatures() { + return excludedRegistryFeatures; + } + + public Set getExcludedBiomeStructures() { + return excludedBiomeStructures; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/BiomeRegistrationEvent.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/BiomeRegistrationEvent.java new file mode 100644 index 000000000..747645e67 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/BiomeRegistrationEvent.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.fabric.event; + +import com.dfsek.terra.api.event.events.Event; +import net.minecraft.util.registry.DynamicRegistryManager; + +/** + * Fired when biomes should be registered. + */ +public class BiomeRegistrationEvent implements Event { + private final DynamicRegistryManager registryManager; + + public BiomeRegistrationEvent(DynamicRegistryManager registryManager) { + this.registryManager = registryManager; + } + + public DynamicRegistryManager getRegistryManager() { + return registryManager; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/GameInitializationEvent.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/GameInitializationEvent.java new file mode 100644 index 000000000..1a2ca827f --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/GameInitializationEvent.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.fabric.event; + +import com.dfsek.terra.api.event.events.Event; + +/** + * Called when the game is initialized and packs should be registered. + */ +public class GameInitializationEvent implements Event { +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index 39a4f9fd5..cae1e2f90 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -4,32 +4,38 @@ import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.generator.ChunkData; import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.generation.Chunkified; import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.api.world.locate.AsyncStructureFinder; import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.fabric.FabricAdapter; import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.block.FabricBlockData; +import com.dfsek.terra.fabric.mixin.StructureAccessorAccessor; +import com.dfsek.terra.fabric.util.FabricAdapter; import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; -import com.dfsek.terra.world.generation.math.samplers.Sampler; import com.dfsek.terra.world.population.items.TerraStructure; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.jafama.FastMath; import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; +import net.minecraft.entity.SpawnGroup; import net.minecraft.server.world.ServerWorld; import net.minecraft.structure.StructureManager; +import net.minecraft.util.collection.Pool; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.Registry; -import net.minecraft.world.BlockView; import net.minecraft.world.ChunkRegion; +import net.minecraft.world.HeightLimitView; import net.minecraft.world.Heightmap; -import net.minecraft.world.WorldAccess; +import net.minecraft.world.SpawnHelper; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.SpawnSettings; import net.minecraft.world.biome.source.BiomeAccess; import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.ChunkRandom; import net.minecraft.world.gen.GenerationStep; import net.minecraft.world.gen.StructureAccessor; import net.minecraft.world.gen.chunk.ChunkGenerator; @@ -41,24 +47,32 @@ import org.jetbrains.annotations.Nullable; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; public class FabricChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { + public static final Codec PACK_CODEC = RecordCodecBuilder.create( + config -> config.group( + Codec.STRING.fieldOf("pack") + .forGetter(pack -> pack.getTemplate().getID()) + ).apply(config, config.stable(TerraFabricPlugin.getInstance().getConfigRegistry()::get))); + + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group( + TerraBiomeSource.CODEC.fieldOf("biome_source") + .forGetter(generator -> generator.biomeSource), + Codec.LONG.fieldOf("seed").stable() + .forGetter(generator -> generator.seed), + PACK_CODEC.fieldOf("pack").stable() + .forGetter(generator -> generator.pack) + ).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new)) + ); + private final long seed; private final DefaultChunkGenerator3D delegate; private final TerraBiomeSource biomeSource; - public static final Codec PACK_CODEC = (RecordCodecBuilder.create(config -> config.group( - Codec.STRING.fieldOf("pack").forGetter(pack -> pack.getTemplate().getID()) - ).apply(config, config.stable(TerraFabricPlugin.getInstance().getConfigRegistry()::get)))); - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - TerraBiomeSource.CODEC.fieldOf("biome_source").forGetter(generator -> generator.biomeSource), - Codec.LONG.fieldOf("seed").stable().forGetter(generator -> generator.seed), - PACK_CODEC.fieldOf("pack").stable().forGetter(generator -> generator.pack)) - .apply(instance, instance.stable(FabricChunkGeneratorWrapper::new))); - private final ConfigPack pack; - public ConfigPack getPack() { - return pack; - } + private final ConfigPack pack; + private DimensionType dimensionType; public FabricChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) { super(biomeSource, new StructuresConfig(false)); @@ -82,93 +96,141 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener return new FabricChunkGeneratorWrapper((TerraBiomeSource) this.biomeSource.withSeed(seed), seed, pack); } + public ConfigPack getPack() { + return pack; + } + @Override public void buildSurface(ChunkRegion region, Chunk chunk) { + // No-op + } + public void setDimensionType(DimensionType dimensionType) { + this.dimensionType = dimensionType; } @Nullable @Override public BlockPos locateStructure(ServerWorld world, StructureFeature feature, BlockPos center, int radius, boolean skipExistingChunks) { - String name = Objects.requireNonNull(Registry.STRUCTURE_FEATURE.getId(feature)).toString(); - TerraWorld terraWorld = TerraFabricPlugin.getInstance().getWorld((World) world); - TerraStructure located = pack.getRegistry(TerraStructure.class).get(pack.getTemplate().getLocatable().get(name)); - if(located != null) { - CompletableFuture result = new CompletableFuture<>(); - AsyncStructureFinder finder = new AsyncStructureFinder(terraWorld.getBiomeProvider(), located, FabricAdapter.adapt(center).toLocation((World) world), 0, 500, location -> { - result.complete(FabricAdapter.adapt(location)); - }, TerraFabricPlugin.getInstance()); - finder.run(); // Do this synchronously. - try { - return result.get(); - } catch(InterruptedException | ExecutionException e) { - throw new RuntimeException(e); + if(!pack.getTemplate().disableStructures()) { + String name = Objects.requireNonNull(Registry.STRUCTURE_FEATURE.getId(feature)).toString(); + TerraWorld terraWorld = TerraFabricPlugin.getInstance().getWorld((World) world); + TerraStructure located = pack.getStructure(pack.getTemplate().getLocatable().get(name)); + if(located != null) { + CompletableFuture result = new CompletableFuture<>(); + AsyncStructureFinder finder = new AsyncStructureFinder(terraWorld.getBiomeProvider(), located, FabricAdapter.adapt(center).toLocation((World) world), 0, 500, location -> { + result.complete(FabricAdapter.adapt(location)); + }, TerraFabricPlugin.getInstance()); + finder.run(); // Do this synchronously. + try { + return result.get(); + } catch(InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } } } - TerraFabricPlugin.getInstance().logger().warning("No overrides are defined for \"" + name + "\""); - return null; - } - - @Override - public void generateFeatures(ChunkRegion region, StructureAccessor accessor) { - super.generateFeatures(region, accessor); - } - - @Override - public void populateNoise(WorldAccess world, StructureAccessor accessor, Chunk chunk) { - delegate.generateChunkData((World) world, new FastRandom(), chunk.getPos().x, chunk.getPos().z, (ChunkData) chunk); + return super.locateStructure(world, feature, center, radius, skipExistingChunks); } @Override public void carve(long seed, BiomeAccess access, Chunk chunk, GenerationStep.Carver carver) { - // No caves + if(pack.getTemplate().vanillaCaves()) { + super.carve(seed, access, chunk, carver); + } } @Override public void setStructureStarts(DynamicRegistryManager dynamicRegistryManager, StructureAccessor structureAccessor, Chunk chunk, StructureManager structureManager, long worldSeed) { - + if(pack.getTemplate().vanillaStructures()) { + super.setStructureStarts(dynamicRegistryManager, structureAccessor, chunk, structureManager, worldSeed); + } } - + @Override + public CompletableFuture populateNoise(Executor executor, StructureAccessor accessor, Chunk chunk) { + return CompletableFuture.supplyAsync(() -> { + World world = (World) ((StructureAccessorAccessor) accessor).getWorld(); + delegate.generateChunkData(world, new FastRandom(), chunk.getPos().x, chunk.getPos().z, (ChunkData) chunk); + delegate.getPopulators().forEach(populator -> { + if(populator instanceof Chunkified) { + populator.populate(world, (com.dfsek.terra.api.platform.world.Chunk) world); + } + }); + return chunk; + }, executor); + } @Override public boolean isStrongholdStartingChunk(ChunkPos chunkPos) { + if(pack.getTemplate().vanillaStructures()) { + return super.isStrongholdStartingChunk(chunkPos); + } return false; } @Override - public int getHeight(int x, int z, Heightmap.Type heightmapType) { - TerraWorld world = TerraFabricPlugin.getInstance().getWorld(seed); - Sampler sampler = world.getConfig().getSamplerCache().getChunk(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16)); - int cx = FastMath.floorMod(x, 16); - int cz = FastMath.floorMod(z, 16); + public int getHeightOnGround(int x, int z, Heightmap.Type heightmap, HeightLimitView world) { + return super.getHeightOnGround(x, z, heightmap, world); + } + @Override + public int getHeight(int x, int z, Heightmap.Type heightmap, HeightLimitView heightmapType) { + TerraWorld world = TerraFabricPlugin.getInstance().getWorld(dimensionType); int height = world.getWorld().getMaxHeight(); - - while (height >= 0 && sampler.sample(cx, height - 1, cz) < 0) { + while(height >= world.getWorld().getMinHeight() && !heightmap.getBlockPredicate().test(((FabricBlockData) world.getUngeneratedBlock(x, height - 1, z)).getHandle())) { height--; } - return height; } @Override - public BlockView getColumnSample(int x, int z) { - int height = 64; // TODO: implementation - BlockState[] array = new BlockState[256]; - for(int y = 255; y >= 0; y--) { - if(y > height) { - if(y > getSeaLevel()) { - array[y] = Blocks.AIR.getDefaultState(); - } else { - array[y] = Blocks.WATER.getDefaultState(); - } - } else { - array[y] = Blocks.STONE.getDefaultState(); + public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView view) { + TerraWorld world = TerraFabricPlugin.getInstance().getWorld(dimensionType); + BlockState[] array = new BlockState[view.getHeight()]; + for(int y = view.getBottomY() + view.getHeight() - 1; y >= view.getBottomY(); y--) { + array[y] = ((FabricBlockData) world.getUngeneratedBlock(x, y, z)).getHandle(); + } + return new VerticalBlockSample(view.getBottomY(), array); + } + + @Override + public void populateEntities(ChunkRegion region) { + if(pack.getTemplate().vanillaMobs()) { + int cx = region.getCenterPos().x; + int cy = region.getCenterPos().z; + Biome biome = region.getBiome((new ChunkPos(cx, cy)).getStartPos()); + ChunkRandom chunkRandom = new ChunkRandom(); + chunkRandom.setPopulationSeed(region.getSeed(), cx << 4, cy << 4); + SpawnHelper.populateEntities(region, biome, region.getCenterPos(), chunkRandom); + } + } + + public Pool getEntitySpawnList(Biome biome, StructureAccessor accessor, SpawnGroup group, BlockPos pos) { + if(accessor.getStructureAt(pos, true, StructureFeature.SWAMP_HUT).hasChildren()) { + if(group == SpawnGroup.MONSTER) { + return StructureFeature.SWAMP_HUT.getMonsterSpawns(); + } + + if(group == SpawnGroup.CREATURE) { + return StructureFeature.SWAMP_HUT.getCreatureSpawns(); } } - return new VerticalBlockSample(array); + if(group == SpawnGroup.MONSTER) { + if(accessor.getStructureAt(pos, false, StructureFeature.PILLAGER_OUTPOST).hasChildren()) { + return StructureFeature.PILLAGER_OUTPOST.getMonsterSpawns(); + } + + if(accessor.getStructureAt(pos, false, StructureFeature.MONUMENT).hasChildren()) { + return StructureFeature.MONUMENT.getMonsterSpawns(); + } + + if(accessor.getStructureAt(pos, true, StructureFeature.FORTRESS).hasChildren()) { + return StructureFeature.FORTRESS.getMonsterSpawns(); + } + } + + return group == SpawnGroup.UNDERGROUND_WATER_CREATURE && accessor.getStructureAt(pos, false, StructureFeature.MONUMENT).hasChildren() ? StructureFeature.MONUMENT.getUndergroundWaterCreatureSpawns() : super.getEntitySpawnList(biome, accessor, group, pos); } @Override diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/PopulatorFeature.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/PopulatorFeature.java index c58fad225..99a30d378 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/PopulatorFeature.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/PopulatorFeature.java @@ -2,15 +2,13 @@ package com.dfsek.terra.fabric.generation; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.api.world.generation.Chunkified; import com.mojang.serialization.Codec; -import net.minecraft.util.math.BlockPos; import net.minecraft.world.StructureWorldAccess; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.feature.DefaultFeatureConfig; import net.minecraft.world.gen.feature.Feature; - -import java.util.Random; +import net.minecraft.world.gen.feature.util.FeatureContext; /** * Feature wrapper for Terra populator @@ -21,9 +19,16 @@ public class PopulatorFeature extends Feature { } @Override - public boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos, DefaultFeatureConfig config) { + public boolean generate(FeatureContext context) { + ChunkGenerator chunkGenerator = context.getGenerator(); + if(!(chunkGenerator instanceof FabricChunkGeneratorWrapper)) return true; + StructureWorldAccess world = context.getWorld(); FabricChunkGeneratorWrapper gen = (FabricChunkGeneratorWrapper) chunkGenerator; - gen.getHandle().getPopulators().forEach(populator -> populator.populate((World) world, (Chunk) world)); + gen.getHandle().getPopulators().forEach(populator -> { + if(!(populator instanceof Chunkified)) { + populator.populate((World) world, (Chunk) world); + } + }); return true; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java index e2d821192..d8ee36830 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java @@ -4,15 +4,16 @@ import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.util.FabricUtil; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.util.Identifier; +import net.minecraft.util.dynamic.RegistryLookupCodec; import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryLookupCodec; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.source.BiomeSource; -import net.minecraft.world.gen.feature.StructureFeature; +import java.util.Objects; import java.util.stream.Collectors; public class TerraBiomeSource extends BiomeSource { @@ -31,7 +32,9 @@ public class TerraBiomeSource extends BiomeSource { private final ConfigPack pack; public TerraBiomeSource(Registry biomes, long seed, ConfigPack pack) { - super(biomes.stream().collect(Collectors.toList())); + super(biomes.stream() + .filter(biome -> Objects.requireNonNull(biomes.getId(biome)).getNamespace().equals("terra")) // Filter out non-Terra biomes. + .collect(Collectors.toList())); this.biomeRegistry = biomes; this.seed = seed; this.grid = pack.getBiomeProviderBuilder().build(seed); @@ -51,14 +54,6 @@ public class TerraBiomeSource extends BiomeSource { @Override public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) { UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX << 2, biomeZ << 2); - return biomeRegistry.get(new Identifier("terra", TerraFabricPlugin.createBiomeID(pack, biome.getID()))); + return biomeRegistry.get(new Identifier("terra", FabricUtil.createBiomeID(pack, biome.getID()))); } - - - @Override - public boolean hasStructureFeature(StructureFeature feature) { - return false; - } - - } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraGeneratorType.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraGeneratorType.java new file mode 100644 index 000000000..fb842a330 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraGeneratorType.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.fabric.generation; + +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.event.BiomeRegistrationEvent; +import com.dfsek.terra.fabric.util.FabricUtil; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.world.GeneratorType; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.DynamicRegistryManager; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.GeneratorOptions; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; + +@Environment(EnvType.CLIENT) +public class TerraGeneratorType extends GeneratorType { + private final ConfigPack pack; + + public TerraGeneratorType(ConfigPack pack) { + super("terra." + pack.getTemplate().getID()); + this.pack = pack; + } + + @Override + public GeneratorOptions createDefaultOptions(DynamicRegistryManager.Impl registryManager, long seed, boolean generateStructures, boolean bonusChest) { + GeneratorOptions options = super.createDefaultOptions(registryManager, seed, generateStructures, bonusChest); + TerraFabricPlugin.getInstance().getEventManager().callEvent(new BiomeRegistrationEvent(registryManager)); // register biomes + return options; + } + + @Override + protected ChunkGenerator getChunkGenerator(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { + return new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java index 219968106..1f801f1d0 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java @@ -1,9 +1,13 @@ package com.dfsek.terra.fabric.handle; +import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.entity.EntityType; +import com.dfsek.terra.api.platform.entity.Player; import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.fabric.FabricAdapter; +import com.dfsek.terra.api.util.generic.pair.Pair; import com.dfsek.terra.fabric.block.FabricBlockData; +import com.dfsek.terra.fabric.util.FabricAdapter; +import com.dfsek.terra.fabric.util.WorldEditUtil; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.block.BlockState; @@ -33,4 +37,14 @@ public class FabricWorldHandle implements WorldHandle { if(identifier == null) identifier = Identifier.tryParse("minecraft:" + id.toLowerCase(Locale.ROOT)); return (EntityType) Registry.ENTITY_TYPE.get(identifier); } + + @Override + public Pair getSelectedLocation(Player player) { + try { + Class.forName("com.sk89q.worldedit.WorldEdit"); + } catch(ClassNotFoundException e) { + throw new IllegalStateException("WorldEdit is not installed."); + } + return WorldEditUtil.getSelection(player); + } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/CommandManagerMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/CommandManagerMixin.java new file mode 100644 index 000000000..2e98614df --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/CommandManagerMixin.java @@ -0,0 +1,86 @@ +package com.dfsek.terra.fabric.mixin; + +import com.dfsek.terra.api.command.exception.CommandException; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Entity; +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.LiteralText; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; + +@Mixin(CommandManager.class) +public abstract class CommandManagerMixin { + @Shadow + @Final + private CommandDispatcher dispatcher; + + @Inject(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/CommandDispatcher;findAmbiguities(Lcom/mojang/brigadier/AmbiguityConsumer;)V", remap = false)) + private void injectTerraCommands(CommandManager.RegistrationEnvironment environment, CallbackInfo ci) { + com.dfsek.terra.api.command.CommandManager manager = TerraFabricPlugin.getInstance().getManager(); + int max = manager.getMaxArgumentDepth(); + RequiredArgumentBuilder arg = argument("arg" + (max - 1), StringArgumentType.word()); + for(int i = 0; i < max; i++) { + RequiredArgumentBuilder next = argument("arg" + (max - i - 1), StringArgumentType.word()); + + arg = next.then(assemble(arg, manager)); + } + + dispatcher.register(literal("terra").executes(context -> 1).then(assemble(arg, manager))); + dispatcher.register(literal("te").executes(context -> 1).then(assemble(arg, manager))); + } + + private RequiredArgumentBuilder assemble(RequiredArgumentBuilder in, com.dfsek.terra.api.command.CommandManager manager) { + return in.suggests((context, builder) -> { + List args = parseCommand(context.getInput()); + CommandSender sender = (CommandSender) context.getSource(); + try { + sender = (Entity) context.getSource().getEntityOrThrow(); + } catch(CommandSyntaxException ignore) { + } + try { + manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest); + } catch(CommandException e) { + sender.sendMessage(e.getMessage()); + } + return builder.buildFuture(); + }).executes(context -> { + List args = parseCommand(context.getInput()); + CommandSender sender = (CommandSender) context.getSource(); + try { + sender = (Entity) context.getSource().getEntityOrThrow(); + } catch(CommandSyntaxException ignore) { + } + try { + manager.execute(args.remove(0), sender, args); + } catch(CommandException e) { + context.getSource().sendError(new LiteralText(e.getMessage())); + } + return 1; + }); + } + + private List parseCommand(String command) { + if(command.startsWith("/terra ")) command = command.substring("/terra ".length()); + else if(command.startsWith("/te ")) command = command.substring("/te ".length()); + List c = new ArrayList<>(Arrays.asList(command.split(" "))); + if(command.endsWith(" ")) c.add(""); + return c; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/ServerWorldMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/ServerWorldMixin.java new file mode 100644 index 000000000..b3d5d7c97 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/ServerWorldMixin.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.fabric.mixin; + +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.world.TerraWorld; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.WorldGenerationProgressListener; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.Spawner; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.level.ServerWorldProperties; +import net.minecraft.world.level.storage.LevelStorage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; +import java.util.concurrent.Executor; + +@Mixin(ServerWorld.class) +public abstract class ServerWorldMixin { + @Inject(method = "", at = @At(value = "RETURN")) + public void injectConstructor(MinecraftServer server, Executor workerExecutor, LevelStorage.Session session, ServerWorldProperties properties, RegistryKey registryKey, DimensionType dimensionType, WorldGenerationProgressListener worldGenerationProgressListener, ChunkGenerator chunkGenerator, boolean debugWorld, long l, List list, boolean bl, CallbackInfo ci) { + if(chunkGenerator instanceof FabricChunkGeneratorWrapper) { + TerraFabricPlugin.getInstance().getWorldMap().put(dimensionType, Pair.of((ServerWorld) (Object) this, new TerraWorld((com.dfsek.terra.api.platform.world.World) this, ((FabricChunkGeneratorWrapper) chunkGenerator).getPack(), TerraFabricPlugin.getInstance()))); + ((FabricChunkGeneratorWrapper) chunkGenerator).setDimensionType(dimensionType); + TerraFabricPlugin.getInstance().logger().info("Registered world " + this + " to dimension type " + dimensionType); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/StructureAccessorAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/StructureAccessorAccessor.java new file mode 100644 index 000000000..888c8cd83 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/StructureAccessorAccessor.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.fabric.mixin; + +import net.minecraft.world.WorldAccess; +import net.minecraft.world.gen.StructureAccessor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(StructureAccessor.class) +public interface StructureAccessorAccessor { + @Accessor + WorldAccess getWorld(); +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java index 4b7eb1f4f..e1d051d08 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java @@ -1,12 +1,14 @@ package com.dfsek.terra.fabric.mixin.access; import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.MobSpawnerLogic; +import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(MobSpawnerLogic.class) public interface MobSpawnerLogicAccessor { @Invoker("getEntityId") - Identifier callGetEntityId(); + Identifier callGetEntityId(World world, BlockPos blockPos); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java index ab3bff88a..4a928cbb6 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java @@ -3,11 +3,13 @@ package com.dfsek.terra.fabric.mixin.implementations; import net.minecraft.world.biome.Biome; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; @Mixin(Biome.class) @Implements(@Interface(iface = com.dfsek.terra.api.platform.world.Biome.class, prefix = "terra$", remap = Interface.Remap.NONE)) public abstract class BiomeMixin { + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ChunkGeneratorMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ChunkGeneratorMixin.java index b766f4692..cc7b82e80 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ChunkGeneratorMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ChunkGeneratorMixin.java @@ -3,11 +3,13 @@ package com.dfsek.terra.fabric.mixin.implementations; import net.minecraft.world.gen.chunk.ChunkGenerator; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; @Mixin(ChunkGenerator.class) @Implements(@Interface(iface = com.dfsek.terra.api.platform.world.generator.ChunkGenerator.class, prefix = "terra$", remap = Interface.Remap.NONE)) public abstract class ChunkGeneratorMixin { + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockEntityMixin.java index 8672f444d..5082204d9 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockEntityMixin.java @@ -3,20 +3,23 @@ package com.dfsek.terra.fabric.mixin.implementations.block; import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.fabric.FabricAdapter; import com.dfsek.terra.fabric.block.FabricBlock; +import com.dfsek.terra.fabric.util.FabricAdapter; import net.minecraft.block.entity.BlockEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(BlockEntity.class) @Implements(@Interface(iface = BlockState.class, prefix = "terra$", remap = Interface.Remap.NONE)) public abstract class BlockEntityMixin { + @Final @Shadow protected BlockPos pos; @Shadow @@ -29,6 +32,7 @@ public abstract class BlockEntityMixin { @Shadow public abstract boolean hasWorld(); + @Intrinsic public Object terra$getHandle() { return this; } @@ -54,7 +58,7 @@ public abstract class BlockEntityMixin { } public boolean terra$update(boolean applyPhysics) { - if(hasWorld()) world.getChunk(pos).setBlockEntity(pos, (BlockEntity) (Object) this); + if(hasWorld()) world.getChunk(pos).setBlockEntity((BlockEntity) (Object) this); return true; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java index 0875cab40..579b404f8 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java @@ -2,12 +2,13 @@ package com.dfsek.terra.fabric.mixin.implementations.block; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.fabric.FabricAdapter; +import com.dfsek.terra.fabric.util.FabricAdapter; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -17,6 +18,7 @@ public abstract class BlockMixin { @Shadow private BlockState defaultState; + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/LootableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/LootableContainerBlockEntityMixin.java index 9bb319856..f72957753 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/LootableContainerBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/LootableContainerBlockEntityMixin.java @@ -6,6 +6,7 @@ import com.dfsek.terra.fabric.mixin.implementations.block.BlockEntityMixin; import net.minecraft.block.entity.LootableContainerBlockEntity; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; @Mixin(LootableContainerBlockEntity.class) @@ -15,6 +16,7 @@ public abstract class LootableContainerBlockEntityMixin extends BlockEntityMixin return (Inventory) this; } + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/MobSpawnerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/MobSpawnerBlockEntityMixin.java index 8f664787e..f678ab0a7 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/MobSpawnerBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/MobSpawnerBlockEntityMixin.java @@ -5,9 +5,14 @@ import com.dfsek.terra.api.platform.block.state.SerialState; import com.dfsek.terra.api.platform.entity.EntityType; import com.dfsek.terra.fabric.TerraFabricPlugin; import com.dfsek.terra.fabric.mixin.access.MobSpawnerLogicAccessor; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.MobSpawnerBlockEntity; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; import net.minecraft.world.MobSpawnerLogic; +import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; @@ -16,12 +21,16 @@ import org.spongepowered.asm.mixin.Shadow; @Mixin(MobSpawnerBlockEntity.class) @Implements(@Interface(iface = MobSpawner.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class MobSpawnerBlockEntityMixin { +public abstract class MobSpawnerBlockEntityMixin extends BlockEntity { + private MobSpawnerBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + @Shadow public abstract MobSpawnerLogic getLogic(); public EntityType terra$getSpawnedType() { - return (EntityType) Registry.ENTITY_TYPE.get(((MobSpawnerLogicAccessor) getLogic()).callGetEntityId()); + return (EntityType) Registry.ENTITY_TYPE.get(((MobSpawnerLogicAccessor) getLogic()).callGetEntityId(world, pos)); } public void terra$setSpawnedType(@NotNull EntityType creatureType) { diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/SignBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/SignBlockEntityMixin.java index f8ab0ee3f..c9dd3f065 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/SignBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/SignBlockEntityMixin.java @@ -20,18 +20,18 @@ public abstract class SignBlockEntityMixin { @Shadow @Final - private Text[] text; + private Text[] texts; public @NotNull String[] terra$getLines() { - String[] lines = new String[text.length]; - for(int i = 0; i < text.length; i++) { - lines[i] = text[i].asString(); + String[] lines = new String[texts.length]; + for(int i = 0; i < texts.length; i++) { + lines[i] = texts[i].asString(); } return lines; } public @NotNull String terra$getLine(int index) throws IndexOutOfBoundsException { - return text[index].asString(); + return texts[index].asString(); } public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java index 55ebe0576..7912b2f2a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java @@ -7,6 +7,7 @@ import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.fabric.block.FabricBlock; import com.dfsek.terra.fabric.block.FabricBlockData; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.world.ChunkRegion; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Final; @@ -20,18 +21,14 @@ import org.spongepowered.asm.mixin.Shadow; public abstract class ChunkRegionMixin { @Final @Shadow - private int centerChunkX; - - @Final - @Shadow - private int centerChunkZ; + private ChunkPos centerPos; public int terra$getX() { - return centerChunkX; + return centerPos.x; } public int terra$getZ() { - return centerChunkZ; + return centerPos.z; } public World terra$getWorld() { @@ -39,7 +36,7 @@ public abstract class ChunkRegionMixin { } public Block terra$getBlock(int x, int y, int z) { - BlockPos pos = new BlockPos(x + (centerChunkX << 4), y, z + (centerChunkZ << 4)); + BlockPos pos = new BlockPos(x + (centerPos.x << 4), y, z + (centerPos.z << 4)); return new FabricBlock(pos, (ChunkRegion) (Object) this); } @@ -48,10 +45,8 @@ public abstract class ChunkRegionMixin { } public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { - ((ChunkRegion) (Object) this).setBlockState(new BlockPos(x + (centerChunkX << 4), y, z + (centerChunkZ << 4)), ((FabricBlockData) blockData).getHandle(), 0); + ((ChunkRegion) (Object) this).setBlockState(new BlockPos(x + (centerPos.x << 4), y, z + (centerPos.z << 4)), ((FabricBlockData) blockData).getHandle(), 0); } - public Object terra$getHandle() { - return this; - } + // getHandle already added in world/ChunkRegionMixin. } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java index c09e52dc3..56681d0ab 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java @@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -47,6 +48,7 @@ public abstract class WorldChunkMixin { ((net.minecraft.world.chunk.Chunk) this).setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false); } + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java index 15a862bed..2b2b87eb4 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java @@ -9,6 +9,7 @@ import net.minecraft.world.chunk.ProtoChunk; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -26,6 +27,7 @@ public abstract class ProtoChunkMixin { ((net.minecraft.world.chunk.Chunk) this).setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false); } + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java index 88d6bfbb6..d829f7fe3 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java @@ -2,13 +2,14 @@ package com.dfsek.terra.fabric.mixin.implementations.entity; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.fabric.FabricAdapter; +import com.dfsek.terra.fabric.util.FabricAdapter; import net.minecraft.entity.Entity; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -29,6 +30,7 @@ public abstract class EntityMixin { @Shadow public abstract void sendSystemMessage(Text message, UUID senderUuid); + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java index ee0cbc0cf..85ffb4c25 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java @@ -3,11 +3,13 @@ package com.dfsek.terra.fabric.mixin.implementations.entity; import net.minecraft.entity.EntityType; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; @Mixin(EntityType.class) @Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.EntityType.class, prefix = "terra$", remap = Interface.Remap.NONE)) public abstract class EntityTypeMixin { + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java index caf9b91f1..9b0593521 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java @@ -6,6 +6,7 @@ import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -19,6 +20,7 @@ public abstract class ServerCommandSourceMixin { sendFeedback(new LiteralText(message), true); } + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java index 1c14e2ab5..cff0892bb 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java @@ -6,11 +6,13 @@ import net.minecraft.block.entity.LockableContainerBlockEntity; import net.minecraft.item.Items; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; @Mixin(LockableContainerBlockEntity.class) @Implements(@Interface(iface = Inventory.class, prefix = "terra$", remap = Interface.Remap.NONE)) public class LockableContainerBlockEntityMixin { + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java index b8f7a9be1..b14939c1c 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java @@ -4,6 +4,7 @@ import com.dfsek.terra.api.platform.inventory.ItemStack; import net.minecraft.item.Item; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -13,6 +14,7 @@ public abstract class ItemMixin { @Shadow public abstract int getMaxDamage(); + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java index 55fe05f26..864e4724a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java @@ -3,7 +3,7 @@ package com.dfsek.terra.fabric.mixin.implementations.inventory.item; import com.dfsek.terra.api.platform.inventory.Item; import com.dfsek.terra.api.platform.inventory.item.ItemMeta; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; @@ -27,7 +27,7 @@ public abstract class ItemStackMixin { public abstract boolean isDamageable(); @Shadow - public abstract void setTag(@Nullable CompoundTag tag); + public abstract void setTag(@Nullable NbtCompound tag); public int terra$getAmount() { return getCount(); @@ -50,6 +50,7 @@ public abstract class ItemStackMixin { setTag(((ItemStack) (Object) meta).getTag()); } + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java index 5fd30638d..eb47a6498 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java @@ -5,6 +5,7 @@ import net.minecraft.enchantment.Enchantment; import net.minecraft.util.registry.Registry; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -19,6 +20,7 @@ public abstract class EnchantmentMixin { @Shadow public abstract boolean canCombine(Enchantment other); + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java index 56efedc53..5ddaca96a 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java @@ -3,8 +3,8 @@ package com.dfsek.terra.fabric.mixin.implementations.inventory.meta; import com.dfsek.terra.api.platform.inventory.item.Enchantment; import com.dfsek.terra.api.platform.inventory.item.ItemMeta; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtList; import net.minecraft.util.registry.Registry; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; @@ -23,11 +23,12 @@ public abstract class ItemStackMetaMixin { public abstract boolean hasEnchantments(); @Shadow - public abstract ListTag getEnchantments(); + public abstract NbtList getEnchantments(); @Shadow public abstract void addEnchantment(net.minecraft.enchantment.Enchantment enchantment, int level); + @Intrinsic public Object terra$getHandle() { return this; } @@ -38,7 +39,7 @@ public abstract class ItemStackMetaMixin { Map map = new HashMap<>(); getEnchantments().forEach(enchantment -> { - CompoundTag eTag = (CompoundTag) enchantment; + NbtCompound eTag = (NbtCompound) enchantment; map.put((Enchantment) Registry.ENCHANTMENT.get(eTag.getInt("id")), eTag.getInt("lvl")); }); return map; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java index d87799f57..0a2b05d57 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java @@ -34,7 +34,7 @@ public abstract class ChunkRegionMixin { private long seed; public int terra$getMaxHeight() { - return ((ChunkRegion) (Object) this).getDimensionHeight(); + return (((ChunkRegion) (Object) this).getBottomY()) + ((ChunkRegion) (Object) this).getHeight(); } @SuppressWarnings("deprecation") @@ -64,9 +64,10 @@ public abstract class ChunkRegionMixin { } public int terra$getMinHeight() { - return 0; + return ((ChunkRegion) (Object) this).getBottomY(); } + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java index 15a5c8138..71b6de5e8 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java @@ -13,6 +13,7 @@ import com.dfsek.terra.fabric.block.FabricBlock; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ChunkRegion; import net.minecraft.world.ServerWorldAccess; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; @@ -27,7 +28,7 @@ public abstract class ServerWorldMixin { public abstract long getSeed(); public int terra$getMaxHeight() { - return ((ServerWorld) (Object) this).getDimensionHeight(); + return (((ServerWorld) (Object) this).getBottomY()) + ((ServerWorld) (Object) this).getHeight(); } public ChunkGenerator terra$getGenerator() { @@ -55,9 +56,10 @@ public abstract class ServerWorldMixin { } public int terra$getMinHeight() { - return 0; + return ((ServerWorld) (Object) this).getBottomY(); } + @Intrinsic public Object terra$getHandle() { return this; } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java new file mode 100644 index 000000000..aa2a4aee1 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.fabric.mixin.lifecycle.client; + +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.event.GameInitializationEvent; +import com.dfsek.terra.fabric.generation.TerraGeneratorType; +import com.dfsek.terra.fabric.mixin.access.GeneratorTypeAccessor; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.RunArgs; +import net.minecraft.client.world.GeneratorType; +import net.minecraft.text.LiteralText; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin { + @Inject(method = "", at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/util/WindowProvider;createWindow(Lnet/minecraft/client/WindowSettings;Ljava/lang/String;Ljava/lang/String;)Lnet/minecraft/client/util/Window;", // sorta arbitrary position, after mod init, before window opens + shift = At.Shift.BEFORE)) + public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) { + TerraFabricPlugin.getInstance().getEventManager().callEvent(new GameInitializationEvent()); + TerraFabricPlugin.getInstance().getConfigRegistry().forEach(pack -> { + final GeneratorType generatorType = new TerraGeneratorType(pack); + //noinspection ConstantConditions + ((GeneratorTypeAccessor) generatorType).setTranslationKey(new LiteralText("Terra:" + pack.getTemplate().getID())); + GeneratorTypeAccessor.getValues().add(1, generatorType); + }); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java new file mode 100644 index 000000000..428f9772c --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java @@ -0,0 +1,4 @@ +/** + * Mixins that inject behavior into the client/server lifecycle. + */ +package com.dfsek.terra.fabric.mixin.lifecycle; \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorOptionsMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/GeneratorOptionsMixin.java similarity index 67% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorOptionsMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/GeneratorOptionsMixin.java index 3eafe5469..c665bb3c4 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/GeneratorOptionsMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/GeneratorOptionsMixin.java @@ -1,10 +1,13 @@ -package com.dfsek.terra.fabric.mixin; +package com.dfsek.terra.fabric.mixin.lifecycle.server; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.event.BiomeRegistrationEvent; import com.dfsek.terra.fabric.generation.TerraBiomeSource; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.util.FabricUtil; import com.google.common.base.MoreObjects; +import net.minecraft.util.Identifier; import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.SimpleRegistry; @@ -24,11 +27,13 @@ import java.util.Random; @Mixin(GeneratorOptions.class) public abstract class GeneratorOptionsMixin { @Inject(method = "fromProperties(Lnet/minecraft/util/registry/DynamicRegistryManager;Ljava/util/Properties;)Lnet/minecraft/world/gen/GeneratorOptions;", at = @At("HEAD"), cancellable = true) - private static void fromProperties(DynamicRegistryManager dynamicRegistryManager, Properties properties, CallbackInfoReturnable cir) { + private static void fromProperties(DynamicRegistryManager registryManager, Properties properties, CallbackInfoReturnable cir) { if(properties.get("level-type") == null) { return; } + TerraFabricPlugin main = TerraFabricPlugin.getInstance(); + String prop = properties.get("level-type").toString().trim(); if(prop.startsWith("Terra")) { String seed = (String) MoreObjects.firstNonNull(properties.get("level-seed"), ""); @@ -46,18 +51,20 @@ public abstract class GeneratorOptionsMixin { String generate_structures = (String) properties.get("generate-structures"); boolean generateStructures = generate_structures == null || Boolean.parseBoolean(generate_structures); - Registry dimensionTypes = dynamicRegistryManager.get(Registry.DIMENSION_TYPE_KEY); - Registry biomes = dynamicRegistryManager.get(Registry.BIOME_KEY); - Registry chunkGeneratorSettings = dynamicRegistryManager.get(Registry.NOISE_SETTINGS_WORLDGEN); - SimpleRegistry dimensionOptions = DimensionType.createDefaultDimensionOptions(dimensionTypes, biomes, chunkGeneratorSettings, l); + Registry dimensionTypes = registryManager.get(Registry.DIMENSION_TYPE_KEY); + Registry biomeRegistry = registryManager.get(Registry.BIOME_KEY); + Registry chunkGeneratorSettings = registryManager.get(Registry.CHUNK_GENERATOR_SETTINGS_KEY); + SimpleRegistry dimensionOptions = DimensionType.createDefaultDimensionOptions(dimensionTypes, biomeRegistry, chunkGeneratorSettings, l); prop = prop.substring(prop.indexOf(":") + 1); - ConfigPack pack = TerraFabricPlugin.getInstance().getConfigRegistry().get(prop); + ConfigPack config = main.getConfigRegistry().get(prop); - if(pack == null) throw new IllegalArgumentException("No such pack " + prop); + if(config == null) throw new IllegalArgumentException("No such pack " + prop); - cir.setReturnValue(new GeneratorOptions(l, generateStructures, false, GeneratorOptions.method_28608(dimensionTypes, dimensionOptions, new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomes, l, pack), l, pack)))); + main.getEventManager().callEvent(new BiomeRegistrationEvent(registryManager)); // register biomes + + cir.setReturnValue(new GeneratorOptions(l, generateStructures, false, GeneratorOptions.getRegistryWithReplacedOverworldGenerator(dimensionTypes, dimensionOptions, new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, l, config), l, config)))); } } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java new file mode 100644 index 000000000..b32f2e591 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.fabric.mixin.lifecycle.server; + +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.event.GameInitializationEvent; +import net.minecraft.server.Main; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Main.class) +public class ServerMainMixin { + @Inject(method = "main([Ljava/lang/String;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/DynamicRegistryManager;create()Lnet/minecraft/util/registry/DynamicRegistryManager$Impl;")) + private static void injectConstructor(String[] args, CallbackInfo ci) { + TerraFabricPlugin.getInstance().getEventManager().callEvent(new GameInitializationEvent()); // Load during MinecraftServer construction, after other mods have registered blocks and stuff + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAdapter.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java similarity index 99% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAdapter.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java index 62037173c..8c197d573 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAdapter.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.fabric; +package com.dfsek.terra.fabric.util; import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.platform.block.Axis; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java new file mode 100644 index 000000000..eb6bdee7d --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java @@ -0,0 +1,133 @@ +package com.dfsek.terra.fabric.util; + +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.config.builder.BiomeBuilder; +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.config.templates.BiomeTemplate; +import com.dfsek.terra.fabric.TerraFabricPlugin; +import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions; +import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.fabric.mixin.access.BiomeEffectsAccessor; +import com.mojang.serialization.Lifecycle; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.DynamicRegistryManager; +import net.minecraft.util.registry.MutableRegistry; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.BiomeEffects; +import net.minecraft.world.biome.GenerationSettings; +import net.minecraft.world.gen.GenerationStep; +import net.minecraft.world.gen.carver.ConfiguredCarver; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import net.minecraft.world.gen.feature.ConfiguredStructureFeature; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; +import java.util.function.Supplier; + +public final class FabricUtil { + public static String createBiomeID(ConfigPack pack, String biomeID) { + return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT); + } + + /** + * Clones a Vanilla biome and injects Terra data to create a Terra-vanilla biome delegate. + * + * @param biome The Terra BiomeBuilder. + * @param pack The ConfigPack this biome belongs to. + * @return The Minecraft delegate biome. + */ + public static Biome createBiome(BiomeBuilder biome, ConfigPack pack, DynamicRegistryManager registryManager) { + BiomeTemplate template = biome.getTemplate(); + Map colors = template.getColors(); + + TerraFabricPlugin.FabricAddon fabricAddon = TerraFabricPlugin.getInstance().getFabricAddon(); + + Registry biomeRegistry = registryManager.get(Registry.BIOME_KEY); + Biome vanilla = ((ProtoBiome) (new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0))).get(biomeRegistry); + + GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); + + generationSettings.surfaceBuilder(vanilla.getGenerationSettings().getSurfaceBuilder()); // It needs a surfacebuilder, even though we dont use it. + + generationSettings.feature(GenerationStep.Feature.VEGETAL_DECORATION, TerraFabricPlugin.POPULATOR_CONFIGURED_FEATURE); + + if(pack.getTemplate().vanillaCaves()) { + for(GenerationStep.Carver carver : GenerationStep.Carver.values()) { + for(Supplier> configuredCarverSupplier : vanilla.getGenerationSettings().getCarversForStep(carver)) { + generationSettings.carver(carver, configuredCarverSupplier.get()); + } + } + } + + Pair pair = fabricAddon.getTemplates().get(pack); + PreLoadCompatibilityOptions compatibilityOptions = pair.getLeft(); + PostLoadCompatibilityOptions postLoadCompatibilityOptions = pair.getRight(); + + TerraFabricPlugin.getInstance().getDebugLogger().info("Injecting Vanilla structures and features into Terra biome " + biome.getTemplate().getID()); + + Registry> configuredStructureFeatureRegistry = registryManager.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY); + for(Supplier> structureFeature : vanilla.getGenerationSettings().getStructureFeatures()) { + Identifier key = configuredStructureFeatureRegistry.getId(structureFeature.get()); + if(!compatibilityOptions.getExcludedBiomeStructures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeStructures().getOrDefault(biome, Collections.emptySet()).contains(key)) { + generationSettings.structureFeature(structureFeature.get()); + TerraFabricPlugin.getInstance().getDebugLogger().info("Injected structure " + key); + } + } + + if(compatibilityOptions.doBiomeInjection()) { + Registry> configuredFeatureRegistry = registryManager.get(Registry.CONFIGURED_FEATURE_KEY); + for(int step = 0; step < vanilla.getGenerationSettings().getFeatures().size(); step++) { + for(Supplier> featureSupplier : vanilla.getGenerationSettings().getFeatures().get(step)) { + Identifier key = configuredFeatureRegistry.getId(featureSupplier.get()); + if(!compatibilityOptions.getExcludedBiomeFeatures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeFeatures().getOrDefault(biome, Collections.emptySet()).contains(key)) { + generationSettings.feature(step, featureSupplier); + TerraFabricPlugin.getInstance().getDebugLogger().info("Injected feature " + key + " at stage " + step); + } + } + } + } + + BiomeEffectsAccessor accessor = (BiomeEffectsAccessor) vanilla.getEffects(); + BiomeEffects.Builder effects = new BiomeEffects.Builder() + .waterColor(colors.getOrDefault("water", accessor.getWaterColor())) + .waterFogColor(colors.getOrDefault("water-fog", accessor.getWaterFogColor())) + .fogColor(colors.getOrDefault("fog", accessor.getFogColor())) + .skyColor(colors.getOrDefault("sky", accessor.getSkyColor())) + .grassColorModifier(accessor.getGrassColorModifier()); + + if(colors.containsKey("grass")) { + effects.grassColor(colors.get("grass")); + } else { + accessor.getGrassColor().ifPresent(effects::grassColor); + } + if(colors.containsKey("foliage")) { + effects.foliageColor(colors.get("foliage")); + } else { + accessor.getFoliageColor().ifPresent(effects::foliageColor); + } + + return new Biome.Builder() + .precipitation(vanilla.getPrecipitation()) + .category(vanilla.getCategory()) + .depth(vanilla.getDepth()) + .scale(vanilla.getScale()) + .temperature(vanilla.getTemperature()) + .downfall(vanilla.getDownfall()) + .effects(effects.build()) + .spawnSettings(vanilla.getSpawnSettings()) + .generationSettings(generationSettings.build()) + .build(); + } + + public static void registerOrOverwrite(Registry registry, RegistryKey> key, Identifier identifier, T item) { + if(registry.containsId(identifier)) { + ((MutableRegistry) registry).set(registry.getRawId(registry.get(identifier)), RegistryKey.of(key, identifier), item, Lifecycle.stable()); + } else { + Registry.register(registry, identifier, item); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoBiome.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoBiome.java new file mode 100644 index 000000000..a7ff41ecd --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoBiome.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.fabric.util; + +import com.dfsek.terra.api.platform.world.Biome; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +public class ProtoBiome implements Biome { + private final Identifier identifier; + + public ProtoBiome(Identifier identifier) { + this.identifier = identifier; + } + + public net.minecraft.world.biome.Biome get(Registry registry) { + return registry.get(identifier); + } + + @Override + public Object getHandle() { + return identifier; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/WorldEditUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/WorldEditUtil.java new file mode 100644 index 000000000..159e4fbc8 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/WorldEditUtil.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.fabric.util; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.sk89q.worldedit.IncompleteRegionException; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.world.World; + +public final class WorldEditUtil { + public static Pair getSelection(Player player) { + WorldEdit worldEdit = WorldEdit.getInstance(); + try { + Region selection = worldEdit.getSessionManager() + .get(com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer((ServerPlayerEntity) player)) + .getSelection(com.sk89q.worldedit.fabric.FabricAdapter.adapt((World) player.getWorld())); + BlockVector3 min = selection.getMinimumPoint(); + BlockVector3 max = selection.getMaximumPoint(); + Location l1 = new Location(player.getWorld(), min.getBlockX(), min.getBlockY(), min.getBlockZ()); + Location l2 = new Location(player.getWorld(), max.getBlockX(), max.getBlockY(), max.getBlockZ()); + return Pair.of(l1, l2); + } catch(IncompleteRegionException e) { + throw new IllegalStateException("No selection has been made", e); + } + } +} diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json index d86abc872..cdc7b0742 100644 --- a/platforms/fabric/src/main/resources/fabric.mod.json +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -3,15 +3,16 @@ "id": "terra", "version": "@VERSION@", "name": "Terra", - "description": "An insanely powerful free & open-source data-driven world generator.", + "description": "@DESCRIPTION@", "authors": [ "dfsek" ], "contact": { - "homepage": "https://github.com/PolyhedralDev/Terra/wiki", - "sources": "https://github.com/PolyhedralDev/Terra" + "homepage": "@WIKI@", + "sources": "@SOURCE@", + "issues": "@ISSUES@" }, - "license": "GPL-3.0", + "license": "@LICENSE@", "icon": "assets/terra/icon.png", "environment": "*", "entrypoints": { @@ -24,8 +25,7 @@ ], "depends": { "fabricloader": ">=0.7.4", - "fabric": "*", - "minecraft": "1.16.x" + "minecraft": "1.17.x" }, "accessWidener": "terra.accesswidener" } \ No newline at end of file diff --git a/platforms/fabric/src/main/resources/terra.accesswidener b/platforms/fabric/src/main/resources/terra.accesswidener index f7a4eba9a..377aee552 100644 --- a/platforms/fabric/src/main/resources/terra.accesswidener +++ b/platforms/fabric/src/main/resources/terra.accesswidener @@ -1,3 +1,3 @@ accessWidener v1 named -extendable method net/minecraft/client/world/GeneratorType (Ljava/lang/String;)V \ No newline at end of file +extendable method net/minecraft/client/world/GeneratorType (Ljava/lang/String;)V diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index 394dd3742..f2f42900c 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -2,9 +2,11 @@ "required": true, "minVersion": "0.8", "package": "com.dfsek.terra.fabric.mixin", - "compatibilityLevel": "JAVA_8", + "compatibilityLevel": "JAVA_16", "mixins": [ - "GeneratorOptionsMixin", + "StructureAccessorAccessor", + "CommandManagerMixin", + "ServerWorldMixin", "access.BiomeEffectsAccessor", "access.MobSpawnerLogicAccessor", "access.StateAccessor", @@ -33,9 +35,13 @@ "implementations.world.ServerWorldMixin" ], "client": [ - "access.GeneratorTypeAccessor" + "access.GeneratorTypeAccessor", + "lifecycle.client.MinecraftClientMixin" + ], + "server": [ + "lifecycle.server.GeneratorOptionsMixin", + "lifecycle.server.ServerMainMixin" ], - "server": [], "injectors": { "defaultRequire": 1 }, diff --git a/platforms/forge/build.gradle.kts b/platforms/forge/build.gradle.kts.old similarity index 85% rename from platforms/forge/build.gradle.kts rename to platforms/forge/build.gradle.kts.old index 2bfb7ad0e..682981977 100644 --- a/platforms/forge/build.gradle.kts +++ b/platforms/forge/build.gradle.kts.old @@ -1,6 +1,6 @@ import com.dfsek.terra.configureCommon +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.minecraftforge.gradle.common.util.RunConfig -import net.minecraftforge.gradle.mcp.task.GenerateSRG import net.minecraftforge.gradle.userdev.UserDevExtension import net.minecraftforge.gradle.userdev.tasks.RenameJarInPlace @@ -55,11 +55,17 @@ if ("true" == System.getProperty("idea.sync.active")) { } } + +tasks.named("shadowJar") { + archiveBaseName.set(tasks.getByName("jar").archiveBaseName.orNull) // Pain. Agony, even. + archiveClassifier.set("") // Suffering, if you will. +} + afterEvaluate { - val reobf = extensions.getByName>("reobf") - reobf.maybeCreate("shadowJar").run { - group = "forge" - mappings = tasks.getByName("createMcpToSrg").output + tasks.named("reobfJar") { + val shadow = tasks.getByName("shadowJar"); + dependsOn(shadow) + input = shadow.archiveFile.orNull?.asFile } } @@ -71,7 +77,7 @@ configure { runs { val runConfig = Action { properties(mapOf( - "forge.logging.markers" to "SCAN,REGISTRIES,REGISTRYDUMP", + //"forge.logging.markers" to "SCAN,REGISTRIES,REGISTRYDUMP", "forge.logging.console.level" to "debug" )) arg("-mixin.config=terra.mixins.json") @@ -124,12 +130,12 @@ tasks.jar { } tasks.register("publishModrinthForge") { - dependsOn("reobfShadowJar") + dependsOn("reobfJar") group = "forge" token = System.getenv("MODRINTH_SECRET") projectId = "FIlZB9L0" versionNumber = "${project.version}-forge" - uploadFile = tasks.named("reobfShadowJar").get().input.absoluteFile + uploadFile = tasks.named("reobfJar").get().input.absoluteFile releaseType = "alpha" addGameVersion("1.16.5") addLoader("forge") diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAdapter.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAdapter.java new file mode 100644 index 000000000..6b9f585d3 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAdapter.java @@ -0,0 +1,90 @@ +package com.dfsek.terra.forge; + +import com.dfsek.terra.api.math.vector.Vector3; +import com.dfsek.terra.api.platform.block.BlockFace; +import com.dfsek.terra.api.platform.block.state.Container; +import com.dfsek.terra.api.platform.block.state.MobSpawner; +import com.dfsek.terra.api.platform.block.state.Sign; +import com.dfsek.terra.forge.block.ForgeBlockData; +import com.dfsek.terra.forge.block.data.ForgeDirectional; +import com.dfsek.terra.forge.block.data.ForgeMultipleFacing; +import com.dfsek.terra.forge.block.data.ForgeOrientable; +import com.dfsek.terra.forge.block.data.ForgeRotatable; +import com.dfsek.terra.forge.block.data.ForgeSlab; +import com.dfsek.terra.forge.block.data.ForgeStairs; +import com.dfsek.terra.forge.block.data.ForgeWaterlogged; +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.LockableLootTileEntity; +import net.minecraft.tileentity.MobSpawnerTileEntity; +import net.minecraft.tileentity.SignTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; + +import java.util.Arrays; + +public final class ForgeAdapter { + public static BlockPos adapt(Vector3 v) { + return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ()); + } + + public static Vector3 adapt(BlockPos pos) { + return new Vector3(pos.getX(), pos.getY(), pos.getZ()); + } + + public static ForgeBlockData adapt(BlockState state) { + if(state.hasProperty(BlockStateProperties.STAIRS_SHAPE)) return new ForgeStairs(state); + + if(state.hasProperty(BlockStateProperties.SLAB_TYPE)) return new ForgeSlab(state); + + if(state.hasProperty(BlockStateProperties.AXIS)) return new ForgeOrientable(state, BlockStateProperties.AXIS); + if(state.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) return new ForgeOrientable(state, BlockStateProperties.HORIZONTAL_AXIS); + + if(state.hasProperty(BlockStateProperties.ROTATION_16)) return new ForgeRotatable(state); + + if(state.hasProperty(BlockStateProperties.FACING)) return new ForgeDirectional(state, BlockStateProperties.FACING); + if(state.hasProperty(BlockStateProperties.FACING_HOPPER)) return new ForgeDirectional(state, BlockStateProperties.FACING_HOPPER); + if(state.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) + return new ForgeDirectional(state, BlockStateProperties.HORIZONTAL_FACING); + + if(state.getProperties().containsAll(Arrays.asList(BlockStateProperties.NORTH, BlockStateProperties.SOUTH, BlockStateProperties.EAST, BlockStateProperties.WEST))) + return new ForgeMultipleFacing(state); + if(state.hasProperty(BlockStateProperties.WATERLOGGED)) return new ForgeWaterlogged(state); + return new ForgeBlockData(state); + } + + public static com.dfsek.terra.api.platform.block.state.BlockState adapt(com.dfsek.terra.api.platform.block.Block block) { + IWorld worldAccess = (IWorld) block.getLocation().getWorld(); + + TileEntity entity = worldAccess.getBlockEntity(adapt(block.getLocation().toVector())); + if(entity instanceof SignTileEntity) { + return (Sign) entity; + } else if(entity instanceof MobSpawnerTileEntity) { + return (MobSpawner) entity; + } else if(entity instanceof LockableLootTileEntity) { + return (Container) entity; + } + return null; + } + + public static Direction adapt(BlockFace face) { + switch(face) { + case NORTH: + return Direction.NORTH; + case WEST: + return Direction.WEST; + case SOUTH: + return Direction.SOUTH; + case EAST: + return Direction.EAST; + case UP: + return Direction.UP; + case DOWN: + return Direction.DOWN; + default: + throw new IllegalArgumentException("Illegal direction: " + face); + } + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeUtil.java new file mode 100644 index 000000000..e7f77feec --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeUtil.java @@ -0,0 +1,109 @@ +package com.dfsek.terra.forge; + +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.config.builder.BiomeBuilder; +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.config.templates.BiomeTemplate; +import com.dfsek.terra.forge.config.PostLoadCompatibilityOptions; +import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.WorldGenRegistries; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.BiomeAmbience; +import net.minecraft.world.biome.BiomeGenerationSettings; +import net.minecraft.world.gen.GenerationStage; +import net.minecraft.world.gen.carver.ConfiguredCarver; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import net.minecraft.world.gen.feature.StructureFeature; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Locale; +import java.util.Map; +import java.util.function.Supplier; + +public final class ForgeUtil { + public static String createBiomeID(ConfigPack pack, String biomeID) { + return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT); + } + + public static Biome createBiome(BiomeBuilder biome, ConfigPack pack, TerraForgePlugin.ForgeAddon forgeAddon) { + BiomeTemplate template = biome.getTemplate(); + Map colors = template.getColors(); + + Biome vanilla = (Biome) (new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle(); + + BiomeGenerationSettings.Builder generationSettings = new BiomeGenerationSettings.Builder(); + + generationSettings.surfaceBuilder(vanilla.getGenerationSettings().getSurfaceBuilder()); // It needs a surfacebuilder, even though we dont use it. + + generationSettings.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, TerraForgePlugin.POPULATOR_CONFIGURED_FEATURE); + + if(pack.getTemplate().vanillaCaves()) { + for(GenerationStage.Carving carver : GenerationStage.Carving.values()) { + for(Supplier> configuredCarverSupplier : vanilla.getGenerationSettings().getCarvers(carver)) { + generationSettings.addCarver(carver, configuredCarverSupplier.get()); + } + } + } + + Pair pair = forgeAddon.getTemplates().get(pack); + PreLoadCompatibilityOptions compatibilityOptions = pair.getLeft(); + PostLoadCompatibilityOptions postLoadCompatibilityOptions = pair.getRight(); + + TerraForgePlugin.getInstance().getDebugLogger().info("Injecting Vanilla structures and features into Terra biome " + biome.getTemplate().getID()); + + for(Supplier> structureFeature : vanilla.getGenerationSettings().structures()) { + ResourceLocation key = WorldGenRegistries.CONFIGURED_STRUCTURE_FEATURE.getKey(structureFeature.get()); + if(!compatibilityOptions.getExcludedBiomeStructures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeStructures().getOrDefault(biome, Collections.emptySet()).contains(key)) { + generationSettings.addStructureStart(structureFeature.get()); + TerraForgePlugin.getInstance().getDebugLogger().info("Injected structure " + key); + } + } + + if(compatibilityOptions.doBiomeInjection()) { + for(int step = 0; step < vanilla.getGenerationSettings().features().size(); step++) { + for(Supplier> featureSupplier : vanilla.getGenerationSettings().features().get(step)) { + ResourceLocation key = WorldGenRegistries.CONFIGURED_FEATURE.getKey(featureSupplier.get()); + if(!compatibilityOptions.getExcludedBiomeFeatures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeFeatures().getOrDefault(biome, Collections.emptySet()).contains(key)) { + generationSettings.addFeature(step, featureSupplier); + TerraForgePlugin.getInstance().getDebugLogger().info("Injected feature " + key + " at stage " + step); + } + } + } + } + + BiomeAmbience vanillaEffects = vanilla.getSpecialEffects(); + BiomeAmbience.Builder effects = new BiomeAmbience.Builder() + .waterColor(colors.getOrDefault("water", vanillaEffects.getWaterColor())) + .waterFogColor(colors.getOrDefault("water-fog", vanillaEffects.getWaterFogColor())) + .fogColor(colors.getOrDefault("fog", vanillaEffects.getFogColor())) + .skyColor(colors.getOrDefault("sky", vanillaEffects.getSkyColor())) + .grassColorModifier(vanillaEffects.getGrassColorModifier()); + + if(colors.containsKey("grass")) { + effects.grassColorOverride(colors.get("grass")); + } else { + vanillaEffects.getGrassColorOverride().ifPresent(effects::grassColorOverride); + } + + if(colors.containsKey("foliage")) { + effects.foliageColorOverride(colors.get("foliage")); + } else { + vanillaEffects.getFoliageColorOverride().ifPresent(effects::foliageColorOverride); + } + + return new Biome.Builder() + .precipitation(vanilla.getPrecipitation()) + .biomeCategory(vanilla.getBiomeCategory()) + .depth(vanilla.getDepth()) + .scale(vanilla.getScale()) + .temperature(vanilla.getBaseTemperature()) + .downfall(vanilla.getDownfall()) + .specialEffects(effects.build()) + .mobSpawnSettings(vanilla.getMobSettings()) + .generationSettings(generationSettings.build()) + .build() + .setRegistryName("terra", createBiomeID(template.getPack(), template.getID())); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java index 92aaba20b..d624c53e6 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java @@ -1,5 +1,7 @@ package com.dfsek.terra.forge; +import com.dfsek.tectonic.exception.ConfigException; +import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.TypeRegistry; import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.addons.TerraAddon; @@ -8,15 +10,14 @@ import com.dfsek.terra.api.addons.annotations.Author; import com.dfsek.terra.api.addons.annotations.Version; import com.dfsek.terra.api.command.CommandManager; import com.dfsek.terra.api.command.TerraCommandManager; -import com.dfsek.terra.api.command.exception.CommandException; import com.dfsek.terra.api.command.exception.MalformedCommandException; import com.dfsek.terra.api.event.EventListener; import com.dfsek.terra.api.event.EventManager; import com.dfsek.terra.api.event.TerraEventManager; import com.dfsek.terra.api.event.annotations.Global; import com.dfsek.terra.api.event.annotations.Priority; +import com.dfsek.terra.api.event.events.config.ConfigPackPostLoadEvent; import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent; -import com.dfsek.terra.api.platform.CommandSender; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.handle.ItemHandle; import com.dfsek.terra.api.platform.handle.WorldHandle; @@ -24,67 +25,48 @@ import com.dfsek.terra.api.platform.world.Tree; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.registry.LockedRegistry; -import com.dfsek.terra.api.transform.NotNullValidator; import com.dfsek.terra.api.transform.Transformer; +import com.dfsek.terra.api.transform.Validator; import com.dfsek.terra.api.util.JarUtil; +import com.dfsek.terra.api.util.generic.pair.Pair; import com.dfsek.terra.api.util.logging.DebugLogger; -import com.dfsek.terra.api.util.mutable.MutableInteger; import com.dfsek.terra.commands.CommandUtil; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.builder.BiomeBuilder; import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.config.lang.Language; import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.forge.inventory.ForgeItemHandle; -import com.dfsek.terra.forge.world.ForgeAdapter; -import com.dfsek.terra.forge.world.ForgeBiome; -import com.dfsek.terra.forge.world.ForgeTree; -import com.dfsek.terra.forge.world.ForgeWorldHandle; -import com.dfsek.terra.forge.world.features.PopulatorFeature; -import com.dfsek.terra.forge.world.generator.ForgeChunkGenerator; -import com.dfsek.terra.forge.world.generator.ForgeChunkGeneratorWrapper; -import com.dfsek.terra.forge.world.generator.config.TerraLevelType; +import com.dfsek.terra.forge.config.PostLoadCompatibilityOptions; +import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.PopulatorFeature; +import com.dfsek.terra.forge.generation.TerraBiomeSource; +import com.dfsek.terra.forge.handle.ForgeItemHandle; +import com.dfsek.terra.forge.handle.ForgeWorldHandle; import com.dfsek.terra.profiler.Profiler; import com.dfsek.terra.profiler.ProfilerImpl; import com.dfsek.terra.registry.exception.DuplicateEntryException; import com.dfsek.terra.registry.master.AddonRegistry; import com.dfsek.terra.registry.master.ConfigRegistry; import com.dfsek.terra.world.TerraWorld; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import net.minecraft.block.Blocks; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.button.Button; -import net.minecraft.command.CommandSource; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.WorldGenRegistries; +import net.minecraft.world.DimensionType; +import net.minecraft.world.IWorld; import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.BiomeAmbience; -import net.minecraft.world.biome.BiomeGenerationSettings; -import net.minecraft.world.gen.GenerationStage; import net.minecraft.world.gen.feature.ConfiguredFeature; -import net.minecraft.world.gen.feature.Feature; import net.minecraft.world.gen.feature.Features; import net.minecraft.world.gen.feature.IFeatureConfig; import net.minecraft.world.gen.feature.NoFeatureConfig; import net.minecraft.world.gen.placement.DecoratedPlacement; import net.minecraft.world.gen.placement.NoPlacementConfig; -import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; -import net.minecraft.world.gen.surfacebuilders.SurfaceBuilderConfig; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.ForgeWorldTypeScreens; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.world.ForgeWorldType; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.event.RegistryEvent; +import net.minecraft.world.server.ServerWorld; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.ForgeRegistry; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.objectweb.asm.Type; @@ -94,20 +76,12 @@ import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; -import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; -import java.util.function.Consumer; import java.util.jar.JarFile; import java.util.zip.ZipFile; -import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; -import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument; - @Mod("terra") @Mod.EventBusSubscriber(modid = "terra", bus = Mod.EventBusSubscriber.Bus.MOD) public class TerraForgePlugin implements TerraPlugin { @@ -115,7 +89,7 @@ public class TerraForgePlugin implements TerraPlugin { public static final ConfiguredFeature POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configured(IFeatureConfig.NONE).decorated(DecoratedPlacement.NOPE.configured(NoPlacementConfig.INSTANCE)); private static TerraForgePlugin INSTANCE; - private final Map worldMap = new HashMap<>(); + private final Map> worldMap = new HashMap<>(); private final EventManager eventManager = new TerraEventManager(this); private final GenericLoaders genericLoaders = new GenericLoaders(this); private final Profiler profiler = new ProfilerImpl(); @@ -140,129 +114,51 @@ public class TerraForgePlugin implements TerraPlugin { logger.error(message); } }; + private final DebugLogger debugLogger = new DebugLogger(logger); private final ItemHandle itemHandle = new ForgeItemHandle(); private final WorldHandle worldHandle = new ForgeWorldHandle(); private final ConfigRegistry registry = new ConfigRegistry(); private final CheckedRegistry checkedRegistry = new CheckedRegistry<>(registry); - private final AddonRegistry addonRegistry = new AddonRegistry(new ForgeAddon(this), this); + + private final ForgeAddon addon = new ForgeAddon(this); + + private final AddonRegistry addonRegistry = new AddonRegistry(addon, this); private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); private final PluginConfig config = new PluginConfig(); private final Transformer biomeFixer = new Transformer.Builder() - .addTransform(id -> ForgeRegistries.BIOMES.getValue(ResourceLocation.tryParse(id)), new NotNullValidator<>()) - .addTransform(id -> ForgeRegistries.BIOMES.getValue(ResourceLocation.tryParse("minecraft:" + id.toLowerCase())), new NotNullValidator<>()).build(); - private File dataFolder; + .addTransform(id -> ForgeRegistries.BIOMES.getValue(ResourceLocation.tryParse(id)), Validator.notNull()) + .addTransform(id -> ForgeRegistries.BIOMES.getValue(ResourceLocation.tryParse("minecraft:" + id.toLowerCase())), Validator.notNull()).build(); + private final File dataFolder; public TerraForgePlugin() { if(INSTANCE != null) throw new IllegalStateException("Only one TerraPlugin instance may exist."); INSTANCE = this; - MinecraftForge.EVENT_BUS.register(ClientEvents.class); - MinecraftForge.EVENT_BUS.register(getClass()); - MinecraftForge.EVENT_BUS.register(ForgeEvents.class); + this.dataFolder = Paths.get("config", "Terra").toFile(); + saveDefaultConfig(); + config.load(this); + debugLogger.setDebug(config.isDebug()); + LangUtil.load(config.getLanguage(), this); + try { + CommandUtil.registerAll(manager); + } catch(MalformedCommandException e) { + e.printStackTrace(); // TODO do something here even though this should literally never happen + } } public static TerraForgePlugin getInstance() { return INSTANCE; } - public static String createBiomeID(ConfigPack pack, String biomeID) { - return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT); - } - - private static RequiredArgumentBuilder assemble(RequiredArgumentBuilder in, CommandManager manager) { - return in.suggests((context, builder) -> { - List args = parseCommand(context.getInput()); - CommandSender sender = ForgeAdapter.adapt(context.getSource()); - try { - manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest); - } catch(CommandException e) { - sender.sendMessage(e.getMessage()); - } - return builder.buildFuture(); - }).executes(context -> { - List args = parseCommand(context.getInput()); - try { - manager.execute(args.remove(0), ForgeAdapter.adapt(context.getSource()), args); - } catch(CommandException e) { - context.getSource().sendFailure(new StringTextComponent(e.getMessage())); - } - return 1; + @SubscribeEvent + public static void setupListener(FMLCommonSetupEvent event) { + event.enqueueWork(() -> { + Registry.register(Registry.BIOME_SOURCE, "terra:biome", TerraBiomeSource.CODEC); + Registry.register(Registry.CHUNK_GENERATOR, "terra:generator", ForgeChunkGeneratorWrapper.CODEC); }); } - private static List parseCommand(String command) { - if(command.startsWith("/terra ")) command = command.substring("/terra ".length()); - else if(command.startsWith("/te ")) command = command.substring("/te ".length()); - List c = new ArrayList<>(Arrays.asList(command.split(" "))); - if(command.endsWith(" ")) c.add(""); - return c; - } - - @SubscribeEvent - public static void register(RegistryEvent.Register event) { - INSTANCE.setup(); // Setup now because we need the biomes, and this event happens after blocks n stuff - INSTANCE.getConfigRegistry().forEach(pack -> pack.getRegistry(BiomeBuilder.class).forEach((id, biome) -> event.getRegistry().register(INSTANCE.createBiome(biome)))); // Register all Terra biomes. - } - - @SubscribeEvent - public static void registerLevels(RegistryEvent.Register event) { - INSTANCE.logger().info("Registering level types..."); - event.getRegistry().register(TerraLevelType.FORGE_WORLD_TYPE); - } - - @SubscribeEvent - public static void registerPop(RegistryEvent.Register> event) { - event.getRegistry().register(POPULATOR_FEATURE); - } - - public Biome createBiome(BiomeBuilder biome) { - BiomeTemplate template = biome.getTemplate(); - Map colors = template.getColors(); - - Biome vanilla = ((ForgeBiome) new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle(); - - BiomeGenerationSettings.Builder generationSettings = new BiomeGenerationSettings.Builder(); - generationSettings.surfaceBuilder(SurfaceBuilder.DEFAULT.configured(new SurfaceBuilderConfig(Blocks.GRASS_BLOCK.defaultBlockState(), Blocks.DIRT.defaultBlockState(), Blocks.GRAVEL.defaultBlockState()))); // It needs a surfacebuilder, even though we dont use it. - generationSettings.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, POPULATOR_CONFIGURED_FEATURE); - - BiomeAmbience vanillaEffects = vanilla.getSpecialEffects(); - BiomeAmbience.Builder effects = new BiomeAmbience.Builder() - .waterColor(colors.getOrDefault("water", vanillaEffects.getWaterColor())) - .waterFogColor(colors.getOrDefault("water-fog", vanillaEffects.getWaterFogColor())) - .fogColor(colors.getOrDefault("fog", vanillaEffects.getFogColor())) - .skyColor(colors.getOrDefault("sky", vanillaEffects.getSkyColor())) - .grassColorModifier(vanillaEffects.getGrassColorModifier()); - - if(colors.containsKey("grass")) { - effects.grassColorOverride(colors.get("grass")); - } else { - vanillaEffects.getGrassColorOverride().ifPresent(effects::grassColorOverride); - } - vanillaEffects.getFoliageColorOverride().ifPresent(effects::foliageColorOverride); - if(colors.containsKey("foliage")) { - effects.foliageColorOverride(colors.get("foliage")); - } else { - vanillaEffects.getFoliageColorOverride().ifPresent(effects::foliageColorOverride); - } - - return new Biome.Builder() - .precipitation(vanilla.getPrecipitation()) - .biomeCategory(vanilla.getBiomeCategory()) - .depth(vanilla.getDepth()) - .scale(vanilla.getScale()) - .temperature(vanilla.getBaseTemperature()) - .downfall(vanilla.getDownfall()) - .specialEffects(effects.build()) - .mobSpawnSettings(vanilla.getMobSettings()) - .generationSettings(generationSettings.build()) - .build().setRegistryName("terra", createBiomeID(template.getPack(), template.getID())); - } - - public void setup() { - this.dataFolder = Paths.get("config", "Terra").toFile(); - saveDefaultConfig(); - config.load(this); - LangUtil.load(config.getLanguage(), this); + public void init() { logger.info("Initializing Terra..."); if(!addonRegistry.loadAll()) { @@ -271,15 +167,11 @@ public class TerraForgePlugin implements TerraPlugin { logger.info("Loaded addons."); registry.loadAll(this); - logger.info("Loaded packs."); - - try { - CommandUtil.registerAll(manager); - } catch(MalformedCommandException e) { - e.printStackTrace(); // TODO do something here even though this should literally never happen - } + ((ForgeRegistry) ForgeRegistries.BIOMES).unfreeze(); // Evil + getConfigRegistry().forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> ForgeRegistries.BIOMES.register(ForgeUtil.createBiome(biome, pack, addon)))); // Register all Terra biomes. + ((ForgeRegistry) ForgeRegistries.BIOMES).freeze(); } @Override @@ -289,12 +181,22 @@ public class TerraForgePlugin implements TerraPlugin { @Override public TerraWorld getWorld(World world) { - return worldMap.computeIfAbsent(world.getSeed(), w -> { - logger.info("Loading world " + w); - return new TerraWorld(world, ((ForgeChunkGeneratorWrapper) ((ForgeChunkGenerator) world.getGenerator()).getHandle()).getPack(), this); - }); + return getWorld(((IWorld) world).dimensionType()); } + public TerraWorld getWorld(DimensionType type) { + TerraWorld world = worldMap.get(type).getRight(); + if(world == null) throw new IllegalArgumentException("No world exists with dimension type " + type); + return world; + } + + /** + * evil code brought to you by Forge Mod Loader + *

+ * Forge changes the JAR URI to something that cannot + * be resolved back to the original JAR, so we have to + * do this to get our JAR. + */ @Override public JarFile getModJar() throws URISyntaxException, IOException { File modsDir = new File("./mods"); @@ -311,12 +213,6 @@ public class TerraForgePlugin implements TerraPlugin { return JarUtil.getJarFile(); } - public TerraWorld getWorld(long seed) { - TerraWorld world = worldMap.get(seed); - if(world == null) throw new IllegalArgumentException("No world exists with seed " + seed); - return world; - } - @Override public com.dfsek.terra.api.util.logging.Logger logger() { return logger; @@ -332,6 +228,11 @@ public class TerraForgePlugin implements TerraPlugin { return dataFolder; } + @Override + public boolean isDebug() { + return config.isDebug(); + } + @Override public Language getLanguage() { return LangUtil.getLanguage(); @@ -352,14 +253,11 @@ public class TerraForgePlugin implements TerraPlugin { config.load(this); LangUtil.load(config.getLanguage(), this); // Load language. boolean succeed = registry.loadAll(this); - Map newMap = new HashMap<>(); - worldMap.forEach((seed, tw) -> { - tw.getConfig().getSamplerCache().clear(); - String packID = tw.getConfig().getTemplate().getID(); - newMap.put(seed, new TerraWorld(tw.getWorld(), registry.get(packID), this)); + worldMap.forEach((seed, pair) -> { + pair.getRight().getConfig().getSamplerCache().clear(); + String packID = pair.getRight().getConfig().getTemplate().getID(); + pair.setRight(new TerraWorld(pair.getRight().getWorld(), registry.get(packID), this)); }); - worldMap.clear(); - worldMap.putAll(newMap); return succeed; } @@ -393,7 +291,12 @@ public class TerraForgePlugin implements TerraPlugin { genericLoaders.register(registry); registry .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) - .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> new ForgeBiome(biomeFixer.translate((String) o))); + .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> biomeFixer.translate((String) o)) + .registerLoader(ResourceLocation.class, (t, o, l) -> { + ResourceLocation identifier = ResourceLocation.tryParse((String) o); + if(identifier == null) throw new LoadException("Invalid identifier: " + o); + return identifier; + }); } @Override @@ -406,28 +309,20 @@ public class TerraForgePlugin implements TerraPlugin { return profiler; } - @Mod.EventBusSubscriber(modid = "terra", bus = Mod.EventBusSubscriber.Bus.FORGE) - public static final class ForgeEvents { - @SuppressWarnings({"unchecked", "rawtypes"}) - @SubscribeEvent - public static void registerCommands(RegisterCommandsEvent event) { - int max = INSTANCE.manager.getMaxArgumentDepth(); - RequiredArgumentBuilder arg = argument("arg" + (max - 1), StringArgumentType.word()); - for(int i = 0; i < max; i++) { - RequiredArgumentBuilder next = argument("arg" + (max - i - 1), StringArgumentType.word()); + public CommandManager getManager() { + return manager; + } - arg = next.then(assemble(arg, INSTANCE.manager)); - } - - event.getDispatcher().register(literal("terra").executes(context -> 1).then((ArgumentBuilder) assemble(arg, INSTANCE.manager))); - event.getDispatcher().register(literal("te").executes(context -> 1).then((ArgumentBuilder) assemble(arg, INSTANCE.manager))); - } + public Map> getWorldMap() { + return worldMap; } @Addon("Terra-Forge") @Author("Terra") @Version("1.0.0") - private static final class ForgeAddon extends TerraAddon implements EventListener { + public static final class ForgeAddon extends TerraAddon implements EventListener { + + private final Map> templates = new HashMap<>(); private final TerraPlugin main; @@ -463,43 +358,51 @@ public class TerraForgePlugin implements TerraPlugin { injectTree(treeRegistry, "MEGA_SPRUCE", Features.MEGA_SPRUCE); injectTree(treeRegistry, "CRIMSON_FUNGUS", Features.CRIMSON_FUNGI); injectTree(treeRegistry, "WARPED_FUNGUS", Features.WARPED_FUNGI); + PreLoadCompatibilityOptions template = new PreLoadCompatibilityOptions(); + try { + event.loadTemplate(template); + } catch(ConfigException e) { + e.printStackTrace(); + } + + if(template.doRegistryInjection()) { + WorldGenRegistries.CONFIGURED_FEATURE.entrySet().forEach(entry -> { + if(!template.getExcludedRegistryFeatures().contains(entry.getKey().getRegistryName())) { + try { + event.getPack().getTreeRegistry().add(entry.getKey().getRegistryName().toString(), (Tree) entry.getValue()); + main.getDebugLogger().info("Injected ConfiguredFeature " + entry.getKey().getRegistryName() + " as Tree: " + entry.getValue()); + } catch(DuplicateEntryException ignored) { + } + } + }); + } + templates.put(event.getPack(), Pair.of(template, null)); + } + + @Priority(Priority.HIGHEST) + @Global + public void createInjectionOptions(ConfigPackPostLoadEvent event) { + PostLoadCompatibilityOptions template = new PostLoadCompatibilityOptions(); + + try { + event.loadTemplate(template); + } catch(ConfigException e) { + e.printStackTrace(); + } + + templates.get(event.getPack()).setRight(template); } private void injectTree(CheckedRegistry registry, String id, ConfiguredFeature tree) { try { - registry.add(id, new ForgeTree(tree, id, TerraForgePlugin.getInstance())); + registry.add(id, (Tree) tree); } catch(DuplicateEntryException ignore) { } } - } - @Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) - public static final class ClientEvents { - @SubscribeEvent - public static void register(FMLClientSetupEvent event) { - INSTANCE.logger.info("Client setup..."); - - ForgeWorldType world = TerraLevelType.FORGE_WORLD_TYPE; - ForgeWorldTypeScreens.registerFactory(world, (returnTo, dimensionGeneratorSettings) -> new Screen(world.getDisplayName()) { - private final MutableInteger num = new MutableInteger(0); - private final List packs = new ArrayList<>(); - private final Button toggle = new Button(0, 25, 120, 20, new StringTextComponent(""), button -> { - num.increment(); - if(num.get() >= packs.size()) num.set(0); - button.setMessage(new StringTextComponent("Pack: " + packs.get(num.get()).getTemplate().getID())); - }); - - @Override - protected void init() { - packs.clear(); - INSTANCE.registry.forEach((Consumer) packs::add); - addButton(new Button(0, 0, 120, 20, new StringTextComponent("Close"), btn -> Minecraft.getInstance().setScreen(returnTo))); - toggle.setMessage(new StringTextComponent("Pack: " + packs.get(num.get()).getTemplate().getID())); - addButton(toggle); - } - }); + public Map> getTemplates() { + return templates; } } - } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlock.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlock.java similarity index 89% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlock.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlock.java index 3d439d5d0..98ad4d61e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlock.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlock.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.forge.world.block; +package com.dfsek.terra.forge.block; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.block.Block; @@ -6,9 +6,8 @@ import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.BlockType; import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.forge.world.ForgeAdapter; -import com.dfsek.terra.forge.world.block.state.ForgeBlockState; -import com.dfsek.terra.forge.world.handles.world.ForgeWorldAccess; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.forge.ForgeAdapter; import net.minecraft.block.FlowingFluidBlock; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; @@ -35,7 +34,7 @@ public class ForgeBlock implements Block { @Override public BlockState getState() { - return ForgeBlockState.newInstance(this); + return ForgeAdapter.adapt(this); } @Override @@ -51,7 +50,7 @@ public class ForgeBlock implements Block { @Override public Location getLocation() { - return ForgeAdapter.adapt(delegate.position).toLocation(new ForgeWorldAccess(delegate.worldAccess)); + return ForgeAdapter.adapt(delegate.position).toLocation((World) delegate.worldAccess); } @Override diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockData.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlockData.java similarity index 94% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockData.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlockData.java index 1a4ddb4b5..1fb22ec35 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockData.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlockData.java @@ -1,8 +1,7 @@ -package com.dfsek.terra.forge.world.block; +package com.dfsek.terra.forge.block; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.forge.world.ForgeAdapter; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.state.Property; @@ -39,7 +38,7 @@ public class ForgeBlockData implements BlockData { @Override public BlockType getBlockType() { - return ForgeAdapter.adapt(delegate.getBlock()); + return (BlockType) delegate.getBlock(); } @Override diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeAnaloguePowerable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeAnaloguePowerable.java similarity index 84% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeAnaloguePowerable.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeAnaloguePowerable.java index ff59ff1be..f8455c5c7 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeAnaloguePowerable.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeAnaloguePowerable.java @@ -1,7 +1,7 @@ -package com.dfsek.terra.forge.world.block.data; +package com.dfsek.terra.forge.block.data; import com.dfsek.terra.api.platform.block.data.AnaloguePowerable; -import com.dfsek.terra.forge.world.block.ForgeBlockData; +import com.dfsek.terra.forge.block.ForgeBlockData; import net.minecraft.block.BlockState; /** diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeDirectional.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeDirectional.java similarity index 88% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeDirectional.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeDirectional.java index ec7c34242..c4cc15636 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeDirectional.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeDirectional.java @@ -1,9 +1,9 @@ -package com.dfsek.terra.forge.world.block.data; +package com.dfsek.terra.forge.block.data; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.data.Directional; -import com.dfsek.terra.forge.world.ForgeAdapter; -import com.dfsek.terra.forge.world.block.ForgeBlockData; +import com.dfsek.terra.forge.ForgeAdapter; +import com.dfsek.terra.forge.block.ForgeBlockData; import net.minecraft.block.BlockState; import net.minecraft.state.DirectionProperty; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeEnumAdapter.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeEnumAdapter.java similarity index 98% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeEnumAdapter.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeEnumAdapter.java index d01c59f37..16ba0bb8a 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeEnumAdapter.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeEnumAdapter.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.forge.world.block.data; +package com.dfsek.terra.forge.block.data; import com.dfsek.terra.api.platform.block.Axis; import com.dfsek.terra.api.platform.block.BlockFace; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeMultipleFacing.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeMultipleFacing.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeMultipleFacing.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeMultipleFacing.java index 4bfde3fcc..7e9510282 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeMultipleFacing.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeMultipleFacing.java @@ -1,12 +1,11 @@ -package com.dfsek.terra.forge.world.block.data; +package com.dfsek.terra.forge.block.data; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.data.MultipleFacing; -import com.dfsek.terra.forge.world.block.ForgeBlockData; +import com.dfsek.terra.forge.block.ForgeBlockData; import net.minecraft.block.BlockState; import net.minecraft.state.properties.BlockStateProperties; - import java.util.HashSet; import java.util.Set; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeOrientable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeOrientable.java similarity index 90% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeOrientable.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeOrientable.java index 39d3aa7f6..9f3e53f2d 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeOrientable.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeOrientable.java @@ -1,13 +1,12 @@ -package com.dfsek.terra.forge.world.block.data; +package com.dfsek.terra.forge.block.data; import com.dfsek.terra.api.platform.block.Axis; import com.dfsek.terra.api.platform.block.data.Orientable; -import com.dfsek.terra.forge.world.block.ForgeBlockData; +import com.dfsek.terra.forge.block.ForgeBlockData; import net.minecraft.block.BlockState; import net.minecraft.state.EnumProperty; import net.minecraft.util.Direction; - import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeRotatable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeRotatable.java similarity index 97% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeRotatable.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeRotatable.java index 70bc30111..b64727b59 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeRotatable.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeRotatable.java @@ -1,8 +1,8 @@ -package com.dfsek.terra.forge.world.block.data; +package com.dfsek.terra.forge.block.data; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.data.Rotatable; -import com.dfsek.terra.forge.world.block.ForgeBlockData; +import com.dfsek.terra.forge.block.ForgeBlockData; import net.minecraft.block.BlockState; import net.minecraft.state.properties.BlockStateProperties; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeSlab.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeSlab.java similarity index 92% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeSlab.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeSlab.java index 55c8daa2a..4f294604e 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeSlab.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeSlab.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.forge.world.block.data; +package com.dfsek.terra.forge.block.data; import com.dfsek.terra.api.platform.block.data.Slab; import net.minecraft.block.BlockState; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeStairs.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeStairs.java similarity index 96% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeStairs.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeStairs.java index 87fae372d..ef9c6e8ff 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeStairs.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeStairs.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.forge.world.block.data; +package com.dfsek.terra.forge.block.data; import com.dfsek.terra.api.platform.block.BlockFace; import com.dfsek.terra.api.platform.block.data.Stairs; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeWaterlogged.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeWaterlogged.java similarity index 85% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeWaterlogged.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeWaterlogged.java index c67aa0be0..ed6abffbe 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/data/ForgeWaterlogged.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeWaterlogged.java @@ -1,7 +1,7 @@ -package com.dfsek.terra.forge.world.block.data; +package com.dfsek.terra.forge.block.data; import com.dfsek.terra.api.platform.block.data.Waterlogged; -import com.dfsek.terra.forge.world.block.ForgeBlockData; +import com.dfsek.terra.forge.block.ForgeBlockData; import net.minecraft.block.BlockState; import net.minecraft.state.properties.BlockStateProperties; diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java new file mode 100644 index 000000000..7d0bd3e5b --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.forge.config; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.config.ConfigTemplate; +import com.dfsek.terra.config.builder.BiomeBuilder; +import net.minecraft.util.ResourceLocation; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +@SuppressWarnings("FieldMayBeFinal") +public class PostLoadCompatibilityOptions implements ConfigTemplate { + @Value("structures.inject-biome.exclude-biomes") + @Default + private Map> excludedPerBiomeStructures = new HashMap<>(); + + @Value("features.inject-biome.exclude-biomes") + @Default + private Map> excludedPerBiomeFeatures = new HashMap<>(); + + public Map> getExcludedPerBiomeFeatures() { + return excludedPerBiomeFeatures; + } + + public Map> getExcludedPerBiomeStructures() { + return excludedPerBiomeStructures; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java new file mode 100644 index 000000000..575327b59 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.forge.config; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.config.ConfigTemplate; +import net.minecraft.util.ResourceLocation; + +import java.util.HashSet; +import java.util.Set; + +@SuppressWarnings("FieldMayBeFinal") +public class PreLoadCompatibilityOptions implements ConfigTemplate { + @Value("features.inject-registry.enable") + @Default + private boolean doRegistryInjection = false; + + @Value("features.inject-biome.enable") + @Default + private boolean doBiomeInjection = false; + + @Value("features.inject-registry.excluded-features") + @Default + private Set excludedRegistryFeatures = new HashSet<>(); + + @Value("features.inject-biome.excluded-features") + @Default + private Set excludedBiomeFeatures = new HashSet<>(); + + @Value("structures.inject-biome.excluded-features") + @Default + private Set excludedBiomeStructures = new HashSet<>(); + + public boolean doBiomeInjection() { + return doBiomeInjection; + } + + public boolean doRegistryInjection() { + return doRegistryInjection; + } + + public Set getExcludedBiomeFeatures() { + return excludedBiomeFeatures; + } + + public Set getExcludedRegistryFeatures() { + return excludedRegistryFeatures; + } + + public Set getExcludedBiomeStructures() { + return excludedBiomeStructures; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGeneratorWrapper.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java similarity index 53% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGeneratorWrapper.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java index e9a5ce20d..3a34608b6 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGeneratorWrapper.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java @@ -1,37 +1,52 @@ -package com.dfsek.terra.forge.world.generator; +package com.dfsek.terra.forge.generation; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.api.platform.world.generator.ChunkData; import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; import com.dfsek.terra.api.util.FastRandom; +import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.generation.TerraChunkGenerator; +import com.dfsek.terra.api.world.locate.AsyncStructureFinder; import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.forge.ForgeAdapter; import com.dfsek.terra.forge.TerraForgePlugin; -import com.dfsek.terra.forge.world.TerraBiomeSource; -import com.dfsek.terra.forge.world.handles.world.ForgeSeededWorldAccess; import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; import com.dfsek.terra.world.generation.math.samplers.Sampler; +import com.dfsek.terra.world.population.items.TerraStructure; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.jafama.FastMath; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.util.SharedSeedRandom; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.registry.DynamicRegistries; +import net.minecraft.util.registry.Registry; import net.minecraft.world.Blockreader; +import net.minecraft.world.DimensionType; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; +import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.BiomeManager; -import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunk; import net.minecraft.world.gen.ChunkGenerator; import net.minecraft.world.gen.GenerationStage; import net.minecraft.world.gen.Heightmap; import net.minecraft.world.gen.WorldGenRegion; +import net.minecraft.world.gen.feature.structure.Structure; import net.minecraft.world.gen.feature.structure.StructureManager; import net.minecraft.world.gen.feature.template.TemplateManager; import net.minecraft.world.gen.settings.DimensionStructuresSettings; -import net.minecraft.world.gen.settings.StructureSpreadSettings; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.spawner.WorldEntitySpawner; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; public class ForgeChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { private final long seed; @@ -51,6 +66,8 @@ public class ForgeChunkGeneratorWrapper extends ChunkGenerator implements Genera return pack; } + private DimensionType dimensionType; + public ForgeChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) { super(biomeSource, new DimensionStructuresSettings(false)); this.pack = configPack; @@ -77,50 +94,72 @@ public class ForgeChunkGeneratorWrapper extends ChunkGenerator implements Genera } + @Nullable + @Override + public BlockPos findNearestMapFeature(@NotNull ServerWorld world, @NotNull Structure feature, @NotNull BlockPos center, int radius, boolean skipExistingChunks) { + if(!pack.getTemplate().disableStructures()) { + String name = Objects.requireNonNull(Registry.STRUCTURE_FEATURE.getKey(feature)).toString(); + TerraWorld terraWorld = TerraForgePlugin.getInstance().getWorld((World) world); + TerraStructure located = pack.getStructure(pack.getTemplate().getLocatable().get(name)); + if(located != null) { + CompletableFuture result = new CompletableFuture<>(); + AsyncStructureFinder finder = new AsyncStructureFinder(terraWorld.getBiomeProvider(), located, ForgeAdapter.adapt(center).toLocation((World) world), 0, 500, location -> { + result.complete(ForgeAdapter.adapt(location)); + }, TerraForgePlugin.getInstance()); + finder.run(); // Do this synchronously. + try { + return result.get(); + } catch(InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + } + return super.findNearestMapFeature(world, feature, center, radius, skipExistingChunks); + } + @Override public boolean hasStronghold(@NotNull ChunkPos p_235952_1_) { + if(pack.getTemplate().vanillaStructures()) return super.hasStronghold(p_235952_1_); return false; } @Override - public void createStructures(@NotNull DynamicRegistries p_242707_1_, @NotNull StructureManager p_242707_2_, @NotNull IChunk p_242707_3_, @NotNull TemplateManager p_242707_4_, long p_242707_5_) { - + public void createStructures(@NotNull DynamicRegistries dynamicRegistries, @NotNull StructureManager manager, @NotNull IChunk chunk, @NotNull TemplateManager templateManager, long p_242707_5_) { + if(pack.getTemplate().vanillaStructures()) super.createStructures(dynamicRegistries, manager, chunk, templateManager, p_242707_5_); } @Override - public void applyCarvers(long p_230350_1_, @NotNull BiomeManager p_230350_3_, @NotNull IChunk p_230350_4_, GenerationStage.@NotNull Carving p_230350_5_) { - // No caves + public void applyCarvers(long p_230350_1_, @NotNull BiomeManager biomeManager, @NotNull IChunk chunk, GenerationStage.@NotNull Carving carving) { + if(pack.getTemplate().vanillaCaves()) super.applyCarvers(p_230350_1_, biomeManager, chunk, carving); } @Override public void fillFromNoise(@NotNull IWorld world, @NotNull StructureManager p_230352_2_, @NotNull IChunk chunk) { - ForgeSeededWorldAccess worldAccess = new ForgeSeededWorldAccess(world, seed, this); - delegate.generateChunkData(worldAccess, new FastRandom(), chunk.getPos().x, chunk.getPos().z, new ForgeChunkData(chunk)); + delegate.generateChunkData((World) world, new FastRandom(), chunk.getPos().x, chunk.getPos().z, (ChunkData) chunk); } @Override public int getBaseHeight(int x, int z, Heightmap.@NotNull Type p_222529_3_) { - TerraWorld world = TerraForgePlugin.getInstance().getWorld(seed); + TerraWorld world = TerraForgePlugin.getInstance().getWorld(dimensionType); Sampler sampler = world.getConfig().getSamplerCache().getChunk(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16)); int cx = FastMath.floorMod(x, 16); int cz = FastMath.floorMod(z, 16); int height = world.getWorld().getMaxHeight(); - while (height >= 0 && sampler.sample(cx, height - 1, cz) < 0) { - height--; - } + while(height >= 0 && sampler.sample(cx, height - 1, cz) < 0) height--; return height; } @Override - public @NotNull IBlockReader getBaseColumn(int p_230348_1_, int p_230348_2_) { - int height = 64; // TODO: implementation + public @NotNull IBlockReader getBaseColumn(int x, int z) { + TerraWorld world = TerraForgePlugin.getInstance().getWorld(dimensionType); + int height = getBaseHeight(x, z, Heightmap.Type.WORLD_SURFACE); BlockState[] array = new BlockState[256]; for(int y = 255; y >= 0; y--) { if(y > height) { - if(y > getSeaLevel()) { + if(y > ((UserDefinedBiome) world.getBiomeProvider().getBiome(x, z)).getConfig().getSeaLevel()) { array[y] = Blocks.AIR.defaultBlockState(); } else { array[y] = Blocks.WATER.defaultBlockState(); @@ -133,9 +172,24 @@ public class ForgeChunkGeneratorWrapper extends ChunkGenerator implements Genera return new Blockreader(array); } + @Override + public void spawnOriginalMobs(WorldGenRegion region) { + if(pack.getTemplate().vanillaMobs()) { + int cx = region.getCenterX(); + int cy = region.getCenterZ(); + Biome biome = region.getBiome((new ChunkPos(cx, cy)).getWorldPosition()); + SharedSeedRandom chunkRandom = new SharedSeedRandom(); + chunkRandom.setDecorationSeed(region.getSeed(), cx << 4, cy << 4); + WorldEntitySpawner.spawnMobsForChunkGeneration(region, biome, cx, cy, chunkRandom); + } + } @Override public TerraChunkGenerator getHandle() { return delegate; } + + public void setDimensionType(DimensionType dimensionType) { + this.dimensionType = dimensionType; + } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/features/PopulatorFeature.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/PopulatorFeature.java similarity index 55% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/features/PopulatorFeature.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/generation/PopulatorFeature.java index 6082b4d4e..e586e82d4 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/features/PopulatorFeature.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/PopulatorFeature.java @@ -1,9 +1,7 @@ -package com.dfsek.terra.forge.world.features; +package com.dfsek.terra.forge.generation; -import com.dfsek.terra.forge.world.generator.ForgeChunkGenerator; -import com.dfsek.terra.forge.world.generator.ForgeChunkGeneratorWrapper; -import com.dfsek.terra.forge.world.handles.ForgeWorld; -import com.dfsek.terra.forge.world.handles.chunk.ForgeChunkWorldAccess; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; import com.mojang.serialization.Codec; import net.minecraft.util.math.BlockPos; import net.minecraft.world.ISeedReader; @@ -23,11 +21,9 @@ public class PopulatorFeature extends Feature { } @Override - public boolean place(@NotNull ISeedReader world, @NotNull ChunkGenerator generator, @NotNull Random random, BlockPos pos, @NotNull NoFeatureConfig config) { + public boolean place(@NotNull ISeedReader world, @NotNull ChunkGenerator generator, @NotNull Random random, @NotNull BlockPos pos, @NotNull NoFeatureConfig config) { ForgeChunkGeneratorWrapper gen = (ForgeChunkGeneratorWrapper) generator; - ForgeChunkWorldAccess chunk = new ForgeChunkWorldAccess(world, pos.getX() >> 4, pos.getZ() >> 4); - ForgeWorld world1 = new ForgeWorld(world.getLevel(), new ForgeChunkGenerator(generator)); - gen.getHandle().getPopulators().forEach(populator -> populator.populate(world1, chunk)); + gen.getHandle().getPopulators().forEach(populator -> populator.populate((World) world, (Chunk) world)); return true; } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/TerraBiomeSource.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java similarity index 94% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/TerraBiomeSource.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java index 5f87a10b1..3220cfd58 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/TerraBiomeSource.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java @@ -1,8 +1,9 @@ -package com.dfsek.terra.forge.world; +package com.dfsek.terra.forge.generation; import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.forge.ForgeUtil; import com.dfsek.terra.forge.TerraForgePlugin; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; @@ -51,6 +52,6 @@ public class TerraBiomeSource extends net.minecraft.world.biome.provider.BiomePr @Override public @NotNull Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ) { UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX << 2, biomeZ << 2); - return Objects.requireNonNull(biomeRegistry.get(new ResourceLocation("terra", TerraForgePlugin.createBiomeID(pack, biome.getID())))); + return Objects.requireNonNull(biomeRegistry.get(new ResourceLocation("terra", ForgeUtil.createBiomeID(pack, biome.getID())))); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraGeneratorType.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraGeneratorType.java new file mode 100644 index 000000000..91b8fc852 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraGeneratorType.java @@ -0,0 +1,24 @@ +package com.dfsek.terra.forge.generation; + +import com.dfsek.terra.config.pack.ConfigPack; +import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.DimensionSettings; +import org.jetbrains.annotations.NotNull; + +public class TerraGeneratorType extends BiomeGeneratorTypeScreens { + private final ConfigPack pack; + + public TerraGeneratorType(ConfigPack pack) { + super(new StringTextComponent("Terra:" + pack.getTemplate().getID())); + this.pack = pack; + } + + @Override + protected @NotNull ChunkGenerator generator(@NotNull Registry biomeRegistry, @NotNull Registry chunkGeneratorSettingsRegistry, long seed) { + return new ForgeChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java similarity index 69% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemHandle.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java index 6639b4a59..e2dc4185a 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemHandle.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java @@ -1,14 +1,12 @@ -package com.dfsek.terra.forge.inventory; +package com.dfsek.terra.forge.handle; import com.dfsek.terra.api.platform.handle.ItemHandle; import com.dfsek.terra.api.platform.inventory.Item; import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.dfsek.terra.forge.world.ForgeAdapter; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.command.arguments.ItemArgument; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.registry.Registry; import net.minecraftforge.registries.ForgeRegistries; import java.util.Set; @@ -19,7 +17,7 @@ public class ForgeItemHandle implements ItemHandle { @Override public Item createItem(String data) { try { - return ForgeAdapter.adapt(new ItemArgument().parse(new StringReader(data)).getItem()); + return (Item) new ItemArgument().parse(new StringReader(data)).getItem(); } catch(CommandSyntaxException e) { throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e); } @@ -27,11 +25,11 @@ public class ForgeItemHandle implements ItemHandle { @Override public Enchantment getEnchantment(String id) { - return ForgeAdapter.adapt(ForgeRegistries.ENCHANTMENTS.getValue(ResourceLocation.tryParse(id))); + return (Enchantment) ForgeRegistries.ENCHANTMENTS.getValue(ResourceLocation.tryParse(id)); } @Override public Set getEnchantments() { - return ForgeRegistries.ENCHANTMENTS.getEntries().stream().map(entry -> ForgeAdapter.adapt(entry.getValue())).collect(Collectors.toSet()); + return ForgeRegistries.ENCHANTMENTS.getEntries().stream().map(entry -> (Enchantment) entry.getValue()).collect(Collectors.toSet()); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeWorldHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java similarity index 84% rename from platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeWorldHandle.java rename to platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java index 8e4cfafe6..96c2e37fa 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeWorldHandle.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java @@ -1,14 +1,14 @@ -package com.dfsek.terra.forge.world; +package com.dfsek.terra.forge.handle; import com.dfsek.terra.api.platform.entity.EntityType; import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.forge.world.block.ForgeBlockData; +import com.dfsek.terra.forge.ForgeAdapter; +import com.dfsek.terra.forge.block.ForgeBlockData; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.block.BlockState; import net.minecraft.command.arguments.BlockStateParser; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.registry.Registry; import net.minecraftforge.registries.ForgeRegistries; import java.util.Locale; @@ -31,6 +31,6 @@ public class ForgeWorldHandle implements WorldHandle { public EntityType getEntity(String id) { ResourceLocation identifier = ResourceLocation.tryParse(id); if(identifier == null) identifier = ResourceLocation.tryParse("minecraft:" + id.toLowerCase(Locale.ROOT)); - return ForgeAdapter.adapt(ForgeRegistries.ENTITIES.getValue(identifier)); + return (EntityType) ForgeRegistries.ENTITIES.getValue(identifier); } } diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeEnchantment.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeEnchantment.java deleted file mode 100644 index 8517c7118..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeEnchantment.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dfsek.terra.forge.inventory; - -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.dfsek.terra.forge.world.ForgeAdapter; -import net.minecraft.util.registry.Registry; -import net.minecraftforge.registries.ForgeRegistries; - -import java.util.Objects; - -public class ForgeEnchantment implements Enchantment { - private final net.minecraft.enchantment.Enchantment enchantment; - - public ForgeEnchantment(net.minecraft.enchantment.Enchantment enchantment) { - this.enchantment = enchantment; - } - - @Override - public net.minecraft.enchantment.Enchantment getHandle() { - return enchantment; - } - - @Override - public boolean canEnchantItem(ItemStack itemStack) { - return enchantment.canEnchant(ForgeAdapter.adapt(itemStack)); - } - - @Override - public String getID() { - return Objects.requireNonNull(ForgeRegistries.ENCHANTMENTS.getKey(enchantment)).toString(); - } - - @Override - public boolean conflictsWith(Enchantment other) { - return !enchantment.isCompatibleWith(ForgeAdapter.adapt(other)); - } - - @Override - public int getMaxLevel() { - return enchantment.getMaxLevel(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeInventory.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeInventory.java deleted file mode 100644 index 3109b1498..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeInventory.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.forge.inventory; - -import com.dfsek.terra.api.platform.inventory.Inventory; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.forge.world.ForgeAdapter; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.Items; - -public class ForgeInventory implements Inventory { - private final net.minecraft.inventory.IInventory delegate; - - public ForgeInventory(IInventory delegate) { - this.delegate = delegate; - } - - @Override - public net.minecraft.inventory.IInventory getHandle() { - return delegate; - } - - @Override - public int getSize() { - return delegate.getContainerSize(); - } - - @Override - public ItemStack getItem(int slot) { - net.minecraft.item.ItemStack itemStack = delegate.getItem(slot); - return itemStack.getItem() == Items.AIR ? null : ForgeAdapter.adapt(itemStack); - } - - @Override - public void setItem(int slot, ItemStack newStack) { - delegate.setItem(slot, ForgeAdapter.adapt(newStack)); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItem.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItem.java deleted file mode 100644 index 2f332f768..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItem.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.forge.inventory; - -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.ItemStack; - -public class ForgeItem implements Item { - private final net.minecraft.item.Item delegate; - - public ForgeItem(net.minecraft.item.Item delegate) { - this.delegate = delegate; - } - - @Override - public net.minecraft.item.Item getHandle() { - return delegate; - } - - @Override - public ItemStack newItemStack(int amount) { - return new ForgeItemStack(new net.minecraft.item.ItemStack(delegate, amount)); - } - - @Override - public double getMaxDurability() { - return delegate.getMaxDamage(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemStack.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemStack.java deleted file mode 100644 index 01e186bdb..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/ForgeItemStack.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.forge.inventory; - -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; -import com.dfsek.terra.forge.inventory.meta.ForgeDamageable; -import com.dfsek.terra.forge.inventory.meta.ForgeItemMeta; - -public class ForgeItemStack implements ItemStack { - private net.minecraft.item.ItemStack delegate; - - public ForgeItemStack(net.minecraft.item.ItemStack delegate) { - this.delegate = delegate; - } - - @Override - public int getAmount() { - return delegate.getCount(); - } - - @Override - public void setAmount(int i) { - delegate.setCount(i); - } - - @Override - public Item getType() { - return new ForgeItem(delegate.getItem()); - } - - @Override - public ItemMeta getItemMeta() { - if(delegate.isDamageableItem()) return new ForgeDamageable(delegate.copy()); - return new ForgeItemMeta(delegate.copy()); - } - - @Override - public void setItemMeta(ItemMeta meta) { - this.delegate = ((ForgeItemMeta) meta).getHandle(); - } - - @Override - public net.minecraft.item.ItemStack getHandle() { - return delegate; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeDamageable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeDamageable.java deleted file mode 100644 index 6c0fab95d..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeDamageable.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.forge.inventory.meta; - -import com.dfsek.terra.api.platform.inventory.item.Damageable; -import net.minecraft.item.ItemStack; - -public class ForgeDamageable extends ForgeItemMeta implements Damageable { - public ForgeDamageable(ItemStack delegate) { - super(delegate); - } - - @Override - public int getDamage() { - return delegate.getDamageValue(); - } - - @Override - public void setDamage(int damage) { - delegate.setDamageValue(damage); - } - - @Override - public boolean hasDamage() { - return delegate.isDamaged(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeItemMeta.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeItemMeta.java deleted file mode 100644 index 7a28ade66..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/inventory/meta/ForgeItemMeta.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.dfsek.terra.forge.inventory.meta; - -import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; -import com.dfsek.terra.forge.world.ForgeAdapter; -import net.minecraft.command.arguments.NBTCompoundTagArgument; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.registry.Registry; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public class ForgeItemMeta implements ItemMeta { - protected final ItemStack delegate; - - public ForgeItemMeta(ItemStack delegate) { - this.delegate = delegate; - } - - @Override - public ItemStack getHandle() { - return delegate; - } - - @Override - public Map getEnchantments() { - if(!delegate.isEnchanted()) return Collections.emptyMap(); - Map map = new HashMap<>(); - - delegate.getEnchantmentTags().forEach(enchantment -> { - CompoundNBT eTag = (CompoundNBT) enchantment; - map.put(ForgeAdapter.adapt(Registry.ENCHANTMENT.byId(eTag.getInt("id"))), eTag.getInt("lvl")); - }); - return map; - } - - @Override - public void addEnchantment(Enchantment enchantment, int level) { - delegate.enchant(ForgeAdapter.adapt(enchantment), level); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/ForgeListener.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/ForgeListener.java new file mode 100644 index 000000000..35f0d9d63 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/ForgeListener.java @@ -0,0 +1,81 @@ +package com.dfsek.terra.forge.listener; + +import com.dfsek.terra.api.command.CommandManager; +import com.dfsek.terra.api.command.exception.CommandException; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Entity; +import com.dfsek.terra.forge.TerraForgePlugin; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.command.CommandSource; +import net.minecraft.util.text.StringTextComponent; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; +import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument; + +@Mod.EventBusSubscriber(modid = "terra", bus = Mod.EventBusSubscriber.Bus.FORGE) +public class ForgeListener { + private static final TerraForgePlugin INSTANCE = TerraForgePlugin.getInstance(); + + @SuppressWarnings({"unchecked", "rawtypes"}) + @SubscribeEvent + public static void registerCommands(RegisterCommandsEvent event) { + int max = INSTANCE.getManager().getMaxArgumentDepth(); + RequiredArgumentBuilder arg = argument("arg" + (max - 1), StringArgumentType.word()); + for(int i = 0; i < max; i++) { + RequiredArgumentBuilder next = argument("arg" + (max - i - 1), StringArgumentType.word()); + + arg = next.then(assemble(arg, INSTANCE.getManager())); + } + + event.getDispatcher().register(literal("terra").executes(context -> 1).then((ArgumentBuilder) assemble(arg, INSTANCE.getManager()))); + event.getDispatcher().register(literal("te").executes(context -> 1).then((ArgumentBuilder) assemble(arg, INSTANCE.getManager()))); + } + + public static RequiredArgumentBuilder assemble(RequiredArgumentBuilder in, CommandManager manager) { + return in.suggests((context, builder) -> { + List args = parseCommand(context.getInput()); + CommandSender sender = (CommandSender) context.getSource(); + try { + sender = (Entity) context.getSource().getEntityOrException(); + } catch(CommandSyntaxException ignore) { + } + try { + manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest); + } catch(CommandException e) { + sender.sendMessage(e.getMessage()); + } + return builder.buildFuture(); + }).executes(context -> { + List args = parseCommand(context.getInput()); + try { + CommandSender sender = (CommandSender) context.getSource(); + try { + sender = (Entity) context.getSource().getEntityOrException(); + } catch(CommandSyntaxException ignore) { + } + manager.execute(args.remove(0), sender, args); + } catch(CommandException e) { + context.getSource().sendFailure(new StringTextComponent(e.getMessage())); + } + return 1; + }); + } + + private static List parseCommand(String command) { + if(command.startsWith("/terra ")) command = command.substring("/terra ".length()); + else if(command.startsWith("/te ")) command = command.substring("/te ".length()); + List c = new ArrayList<>(Arrays.asList(command.split(" "))); + if(command.endsWith(" ")) c.add(""); + return c; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/RegistryListener.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/RegistryListener.java new file mode 100644 index 000000000..19847bf0a --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/RegistryListener.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.forge.listener; + +import com.dfsek.terra.forge.TerraForgePlugin; +import net.minecraft.world.gen.feature.Feature; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +public class RegistryListener { + @SubscribeEvent + public static void registerPop(RegistryEvent.Register> event) { + event.getRegistry().register(TerraForgePlugin.POPULATOR_FEATURE); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/DimensionGeneratorSettingsMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/DimensionGeneratorSettingsMixin.java new file mode 100644 index 000000000..ca899217a --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/DimensionGeneratorSettingsMixin.java @@ -0,0 +1,64 @@ +package com.dfsek.terra.forge.mixin; + +import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.forge.TerraForgePlugin; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; +import com.dfsek.terra.forge.generation.TerraBiomeSource; +import com.google.common.base.MoreObjects; +import net.minecraft.util.registry.DynamicRegistries; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.SimpleRegistry; +import net.minecraft.world.Dimension; +import net.minecraft.world.DimensionType; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.DimensionSettings; +import net.minecraft.world.gen.settings.DimensionGeneratorSettings; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Properties; +import java.util.Random; + +@Mixin(DimensionGeneratorSettings.class) +public abstract class DimensionGeneratorSettingsMixin { + @Inject(method = "create(Lnet/minecraft/util/registry/DynamicRegistries;Ljava/util/Properties;)Lnet/minecraft/world/gen/settings/DimensionGeneratorSettings;", at = @At("HEAD"), cancellable = true) + private static void fromProperties(DynamicRegistries dynamicRegistries, Properties properties, CallbackInfoReturnable cir) { + if(properties.get("level-type") == null) { + return; + } + + String prop = properties.get("level-type").toString().trim(); + if(prop.startsWith("Terra")) { + String seed = (String) MoreObjects.firstNonNull(properties.get("level-seed"), ""); + long l = new Random().nextLong(); + if(!seed.isEmpty()) { + try { + long m = Long.parseLong(seed); + if(m != 0L) { + l = m; + } + } catch(NumberFormatException exception) { + l = seed.hashCode(); + } + } + + String generate_structures = (String) properties.get("generate-structures"); + boolean generateStructures = generate_structures == null || Boolean.parseBoolean(generate_structures); + Registry dimensionTypes = dynamicRegistries.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); + Registry biomes = dynamicRegistries.registryOrThrow(Registry.BIOME_REGISTRY); + Registry chunkGeneratorSettings = dynamicRegistries.registryOrThrow(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY); + SimpleRegistry dimensionOptions = DimensionType.defaultDimensions(dimensionTypes, biomes, chunkGeneratorSettings, l); + + prop = prop.substring(prop.indexOf(":") + 1); + + ConfigPack pack = TerraForgePlugin.getInstance().getConfigRegistry().get(prop); + + if(pack == null) throw new IllegalArgumentException("No such pack " + prop); + + TerraForgePlugin.getInstance().logger().info("Using config pack " + pack.getTemplate().getID()); + cir.setReturnValue(new DimensionGeneratorSettings(l, generateStructures, false, DimensionGeneratorSettings.withOverworld(dimensionTypes, dimensionOptions, new ForgeChunkGeneratorWrapper(new TerraBiomeSource(biomes, l, pack), l, pack)))); + } + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/ServerWorldMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/ServerWorldMixin.java new file mode 100644 index 000000000..39cdce89d --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/ServerWorldMixin.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.forge.mixin; + +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.forge.TerraForgePlugin; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; +import com.dfsek.terra.world.TerraWorld; +import net.minecraft.world.DimensionType; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerChunkProvider; +import net.minecraft.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ServerWorld.class) +public abstract class ServerWorldMixin { + @Shadow + @Final + private ServerChunkProvider chunkSource; + + @Shadow + protected abstract void initCapabilities(); + + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;initCapabilities()V")) + public void injectConstructor(ServerWorld serverWorld) { + if(chunkSource.getGenerator() instanceof ForgeChunkGeneratorWrapper) { + ForgeChunkGeneratorWrapper chunkGeneratorWrapper = (ForgeChunkGeneratorWrapper) chunkSource.getGenerator(); + DimensionType dimensionType = ((World) (Object) this).dimensionType(); + TerraForgePlugin.getInstance().getWorldMap().put(dimensionType, Pair.of((ServerWorld) (Object) this, new TerraWorld((com.dfsek.terra.api.platform.world.World) this, chunkGeneratorWrapper.getPack(), TerraForgePlugin.getInstance()))); + chunkGeneratorWrapper.setDimensionType(dimensionType); + TerraForgePlugin.getInstance().logger().info("Registered world " + this + " to dimension type " + dimensionType); + } + initCapabilities(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/AbstractSpawnerAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/AbstractSpawnerAccessor.java new file mode 100644 index 000000000..5783c350f --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/AbstractSpawnerAccessor.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.forge.mixin.access; + +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.spawner.AbstractSpawner; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(AbstractSpawner.class) +public interface AbstractSpawnerAccessor { + @Invoker("getEntityId") + ResourceLocation callGetEntityId(); +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/BiomeGeneratorTypeScreensAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/BiomeGeneratorTypeScreensAccessor.java new file mode 100644 index 000000000..b7d7363b5 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/BiomeGeneratorTypeScreensAccessor.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.forge.mixin.access; + +import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens; +import net.minecraft.util.text.ITextComponent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(BiomeGeneratorTypeScreens.class) +public interface BiomeGeneratorTypeScreensAccessor { + @Accessor("PRESETS") + static List getPresets() { + throw new UnsupportedOperationException(); + } + + @Mutable + @Accessor + void setDescription(ITextComponent description); +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/BiomeMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/BiomeMixin.java new file mode 100644 index 000000000..317893290 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/BiomeMixin.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.forge.mixin.implementations; + +import net.minecraft.world.biome.Biome; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(Biome.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.world.Biome.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class BiomeMixin { + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ChunkGeneratorMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ChunkGeneratorMixin.java new file mode 100644 index 000000000..14fa0e2c5 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ChunkGeneratorMixin.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.forge.mixin.implementations; + +import net.minecraft.world.gen.ChunkGenerator; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ChunkGenerator.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.world.generator.ChunkGenerator.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ChunkGeneratorMixin { + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ConfiguredFeatureMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ConfiguredFeatureMixin.java new file mode 100644 index 000000000..f0e1d0b4a --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ConfiguredFeatureMixin.java @@ -0,0 +1,40 @@ +package com.dfsek.terra.forge.mixin.implementations; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.world.Tree; +import com.dfsek.terra.api.util.collections.MaterialSet; +import com.dfsek.terra.forge.TerraForgePlugin; +import com.dfsek.terra.profiler.ProfileFrame; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ISeedReader; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Random; + +@Mixin(ConfiguredFeature.class) +@Implements(@Interface(iface = Tree.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ConfiguredFeatureMixin { + + @Shadow + public abstract boolean place(ISeedReader p_242765_1_, ChunkGenerator p_242765_2_, Random p_242765_3_, BlockPos p_242765_4_); + + @SuppressWarnings({"try"}) + public boolean terra$plant(Location l, Random r) { + try(ProfileFrame ignore = TerraForgePlugin.getInstance().getProfiler().profile("forge_tree")) { + ISeedReader world = ((ISeedReader) l.getWorld()); + ChunkGenerator generatorWrapper = (ChunkGenerator) l.getWorld().getGenerator(); + return place(world, generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ())); + } + } + + public MaterialSet terra$getSpawnable() { + return MaterialSet.get(TerraForgePlugin.getInstance().getWorldHandle().createBlockData("minecraft:grass_block"), + TerraForgePlugin.getInstance().getWorldHandle().createBlockData("minecraft:podzol"), + TerraForgePlugin.getInstance().getWorldHandle().createBlockData("minecraft:mycelium")); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/BlockMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/BlockMixin.java new file mode 100644 index 000000000..ee4bf13ed --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/BlockMixin.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.forge.mixin.implementations.block; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.BlockType; +import com.dfsek.terra.forge.ForgeAdapter; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(Block.class) +@Implements(@Interface(iface = BlockType.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class BlockMixin { + @Shadow + private BlockState defaultBlockState; + + public Object terra$getHandle() { + return this; + } + + public BlockData terra$getDefaultData() { + return ForgeAdapter.adapt(defaultBlockState); + } + + public boolean terra$isSolid() { + return defaultBlockState.canOcclude(); + } + + @SuppressWarnings("ConstantConditions") + public boolean terra$isWater() { + return ((Object) this) == Blocks.WATER; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/TileEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/TileEntityMixin.java new file mode 100644 index 000000000..2f7bd3918 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/TileEntityMixin.java @@ -0,0 +1,63 @@ +package com.dfsek.terra.forge.mixin.implementations.block; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.block.state.BlockState; +import com.dfsek.terra.forge.ForgeAdapter; +import com.dfsek.terra.forge.block.ForgeBlock; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import javax.annotation.Nullable; + +@Mixin(TileEntity.class) +@Implements(@Interface(iface = BlockState.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class TileEntityMixin { + @Shadow + protected BlockPos worldPosition; + + @Shadow + @Nullable + protected World level; + + @Shadow + @Nullable + private net.minecraft.block.BlockState blockState; + + @Shadow + public abstract boolean hasLevel(); + + public Object terra$getHandle() { + return this; + } + + public Block terra$getBlock() { + return new ForgeBlock(worldPosition, level); + } + + public int terra$getX() { + return worldPosition.getX(); + } + + public int terra$getY() { + return worldPosition.getY(); + } + + public int terra$getZ() { + return worldPosition.getZ(); + } + + public BlockData terra$getBlockData() { + return ForgeAdapter.adapt(blockState); + } + + public boolean terra$update(boolean applyPhysics) { + if(hasLevel()) level.getChunk(worldPosition).setBlockEntity(worldPosition, (TileEntity) (Object) this); + return true; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/LockableLootTileEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/LockableLootTileEntityMixin.java new file mode 100644 index 000000000..977309616 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/LockableLootTileEntityMixin.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.forge.mixin.implementations.block.state; + +import com.dfsek.terra.api.platform.block.state.Container; +import com.dfsek.terra.api.platform.inventory.Inventory; +import com.dfsek.terra.forge.mixin.implementations.block.TileEntityMixin; +import net.minecraft.tileentity.LockableLootTileEntity; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(LockableLootTileEntity.class) +@Implements(@Interface(iface = Container.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class LockableLootTileEntityMixin extends TileEntityMixin { + public Inventory terra$getInventory() { + return (Inventory) this; + } + + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/MobSpawnerTileEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/MobSpawnerTileEntityMixin.java new file mode 100644 index 000000000..1f73b7583 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/MobSpawnerTileEntityMixin.java @@ -0,0 +1,120 @@ +package com.dfsek.terra.forge.mixin.implementations.block.state; + +import com.dfsek.terra.api.platform.block.state.MobSpawner; +import com.dfsek.terra.api.platform.block.state.SerialState; +import com.dfsek.terra.api.platform.entity.EntityType; +import com.dfsek.terra.forge.TerraForgePlugin; +import com.dfsek.terra.forge.mixin.access.AbstractSpawnerAccessor; +import com.dfsek.terra.forge.mixin.implementations.block.TileEntityMixin; +import net.minecraft.tileentity.MobSpawnerTileEntity; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.spawner.AbstractSpawner; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(MobSpawnerTileEntity.class) +@Implements(@Interface(iface = MobSpawner.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class MobSpawnerTileEntityMixin extends TileEntityMixin { + @Shadow + public abstract AbstractSpawner getSpawner(); + + public EntityType terra$getSpawnedType() { + return (EntityType) Registry.ENTITY_TYPE.get(((AbstractSpawnerAccessor) getSpawner()).callGetEntityId()); + } + + public void terra$setSpawnedType(@NotNull EntityType creatureType) { + getSpawner().setEntityId((net.minecraft.entity.EntityType) creatureType); + } + + public int terra$getDelay() { + return 0; + } + + public void terra$setDelay(int delay) { + + } + + public int terra$getMinSpawnDelay() { + return 0; + } + + public void terra$setMinSpawnDelay(int delay) { + + } + + public int terra$getMaxSpawnDelay() { + return 0; + } + + public void terra$setMaxSpawnDelay(int delay) { + + } + + public int terra$getSpawnCount() { + return 0; + } + + public void terra$setSpawnCount(int spawnCount) { + + } + + public int terra$getMaxNearbyEntities() { + return 0; + } + + public void terra$setMaxNearbyEntities(int maxNearbyEntities) { + + } + + public int terra$getRequiredPlayerRange() { + return 0; + } + + public void terra$setRequiredPlayerRange(int requiredPlayerRange) { + + } + + public int terra$getSpawnRange() { + return 0; + } + + public void terra$setSpawnRange(int spawnRange) { + + } + + public void terra$applyState(String state) { + SerialState.parse(state).forEach((k, v) -> { + switch(k) { + case "type": + terra$setSpawnedType(TerraForgePlugin.getInstance().getWorldHandle().getEntity(v)); + return; + case "delay": + terra$setDelay(Integer.parseInt(v)); + return; + case "min_delay": + terra$setMinSpawnDelay(Integer.parseInt(v)); + return; + case "max_delay": + terra$setMaxSpawnDelay(Integer.parseInt(v)); + return; + case "spawn_count": + terra$setSpawnCount(Integer.parseInt(v)); + return; + case "spawn_range": + terra$setSpawnRange(Integer.parseInt(v)); + return; + case "max_nearby": + terra$setMaxNearbyEntities(Integer.parseInt(v)); + return; + case "required_player_range": + terra$setRequiredPlayerRange(Integer.parseInt(v)); + return; + default: + throw new IllegalArgumentException("Invalid property: " + k); + } + }); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/SignTileEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/SignTileEntityMixin.java new file mode 100644 index 000000000..40ec0368c --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/SignTileEntityMixin.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.forge.mixin.implementations.block.state; + +import com.dfsek.terra.api.platform.block.state.SerialState; +import com.dfsek.terra.api.platform.block.state.Sign; +import net.minecraft.tileentity.SignTileEntity; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(SignTileEntity.class) +@Implements(@Interface(iface = Sign.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class SignTileEntityMixin { + @Shadow + @Final + private ITextComponent[] messages; + + @Shadow + public abstract void setMessage(int p_212365_1_, ITextComponent p_212365_2_); + + public @NotNull String[] terra$getLines() { + String[] lines = new String[messages.length]; + for(int i = 0; i < messages.length; i++) { + lines[i] = messages[i].getString(); + } + return lines; + } + + public @NotNull String terra$getLine(int index) throws IndexOutOfBoundsException { + + return messages[index].getString(); + } + + public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { + setMessage(index, new StringTextComponent(line)); + } + + public void terra$applyState(String state) { + SerialState.parse(state).forEach((k, v) -> { + if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); + terra$setLine(Integer.parseInt(k.substring(4)), v); + }); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/ChunkMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/ChunkMixin.java new file mode 100644 index 000000000..6d93b8cef --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/ChunkMixin.java @@ -0,0 +1,54 @@ +package com.dfsek.terra.forge.mixin.implementations.chunk; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.forge.block.ForgeBlock; +import com.dfsek.terra.forge.block.ForgeBlockData; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.IChunk; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(net.minecraft.world.chunk.Chunk.class) +@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ChunkMixin { + + @Shadow + @Final + private net.minecraft.world.World level; + + public int terra$getX() { + return ((IChunk) this).getPos().x; + } + + public int terra$getZ() { + return ((IChunk) this).getPos().z; + } + + public World terra$getWorld() { + return (World) level; + } + + public Block terra$getBlock(int x, int y, int z) { + BlockPos pos = new BlockPos(x + (terra$getX() << 4), y, z + (terra$getZ() << 4)); + return new ForgeBlock(pos, level); + } + + public @NotNull BlockData terra$getBlockData(int x, int y, int z) { + return terra$getBlock(x, y, z).getBlockData(); + } + + public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { + ((IChunk) this).setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false); + } + + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/WorldGenRegionMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/WorldGenRegionMixin.java new file mode 100644 index 000000000..7844a9637 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/WorldGenRegionMixin.java @@ -0,0 +1,57 @@ +package com.dfsek.terra.forge.mixin.implementations.chunk; + +import com.dfsek.terra.api.platform.block.Block; +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.world.Chunk; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.forge.block.ForgeBlock; +import com.dfsek.terra.forge.block.ForgeBlockData; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.WorldGenRegion; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(WorldGenRegion.class) +@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class WorldGenRegionMixin { + @Final + @Shadow + private int x; + + @Final + @Shadow + private int z; + + public int terra$getX() { + return x; + } + + public int terra$getZ() { + return z; + } + + public World terra$getWorld() { + return (World) this; + } + + public Block terra$getBlock(int x, int y, int z) { + BlockPos pos = new BlockPos(x + (this.x << 4), y, z + (this.z << 4)); + return new ForgeBlock(pos, (WorldGenRegion) (Object) this); + } + + public @NotNull BlockData terra$getBlockData(int x, int y, int z) { + return terra$getBlock(x, y, z).getBlockData(); + } + + public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { + ((WorldGenRegion) (Object) this).setBlock(new BlockPos(x + (this.x << 4), y, z + (this.z << 4)), ((ForgeBlockData) blockData).getHandle(), 0); + } + + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/data/ChunkPrimerMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/data/ChunkPrimerMixin.java new file mode 100644 index 000000000..5e5404406 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/data/ChunkPrimerMixin.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.forge.mixin.implementations.chunk.data; + +import com.dfsek.terra.api.platform.block.BlockData; +import com.dfsek.terra.api.platform.world.generator.ChunkData; +import com.dfsek.terra.forge.block.ForgeBlockData; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.ChunkPrimer; +import net.minecraft.world.chunk.IChunk; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ChunkPrimer.class) +@Implements(@Interface(iface = ChunkData.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ChunkPrimerMixin { + @Shadow + public abstract BlockState getBlockState(BlockPos pos); + + public @NotNull BlockData terra$getBlockData(int x, int y, int z) { + return new ForgeBlockData(getBlockState(new BlockPos(x, y, z))); + } + + public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { + ((IChunk) this).setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false); + } + + public Object terra$getHandle() { + return this; + } + + public int terra$getMaxHeight() { + return 255; // TODO: 1.17 - Implement dynamic height. + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/CommandSourceMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/CommandSourceMixin.java new file mode 100644 index 000000000..83df7b48c --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/CommandSourceMixin.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.forge.mixin.implementations.entity; + +import com.dfsek.terra.api.platform.CommandSender; +import net.minecraft.command.CommandSource; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(CommandSource.class) +@Implements(@Interface(iface = CommandSender.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class CommandSourceMixin { + @Shadow + public abstract void sendSuccess(ITextComponent p_197030_1_, boolean p_197030_2_); + + public void terra$sendMessage(String message) { + sendSuccess(new StringTextComponent(message), true); + } + + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityMixin.java new file mode 100644 index 000000000..7cc684c35 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityMixin.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.forge.mixin.implementations.entity; + +import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.world.World; +import com.dfsek.terra.forge.ForgeAdapter; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.UUID; + +@Mixin(Entity.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.Entity.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class EntityMixin { + @Shadow + public net.minecraft.world.World level; + + @Shadow + private BlockPos blockPosition; + + @Shadow + public abstract void teleportTo(double destX, double destY, double destZ); + + + @Shadow + public abstract void sendMessage(ITextComponent p_145747_1_, UUID p_145747_2_); + + public Object terra$getHandle() { + return this; + } + + public Location terra$getLocation() { + return new Location((World) level, ForgeAdapter.adapt(blockPosition)); + } + + public void terra$setLocation(Location location) { + teleportTo(location.getX(), location.getY(), location.getZ()); + } + + public World terra$getWorld() { + return (World) level; + } + + public void terra$sendMessage(String message) { + sendMessage(new StringTextComponent(message), UUID.randomUUID()); // TODO: look into how this actually works and make it less jank + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityTypeMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityTypeMixin.java new file mode 100644 index 000000000..e7bb15a70 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityTypeMixin.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.forge.mixin.implementations.entity; + +import net.minecraft.entity.EntityType; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(EntityType.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.EntityType.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class EntityTypeMixin { + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/PlayerEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/PlayerEntityMixin.java new file mode 100644 index 000000000..7ee5d6731 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/PlayerEntityMixin.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.forge.mixin.implementations.entity; + +import com.dfsek.terra.api.platform.entity.Player; +import net.minecraft.entity.player.PlayerEntity; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(PlayerEntity.class) +@Implements(@Interface(iface = Player.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class PlayerEntityMixin extends EntityMixin { + +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/LockableTileEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/LockableTileEntityMixin.java new file mode 100644 index 000000000..06a279ed3 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/LockableTileEntityMixin.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.forge.mixin.implementations.inventory; + +import com.dfsek.terra.api.platform.inventory.Inventory; +import com.dfsek.terra.api.platform.inventory.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.tileentity.LockableTileEntity; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(LockableTileEntity.class) +@Implements(@Interface(iface = Inventory.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public class LockableTileEntityMixin { + public Object terra$getHandle() { + return this; + } + + public int terra$getSize() { + return ((LockableTileEntity) (Object) this).getContainerSize(); + } + + @SuppressWarnings("ConstantConditions") + public ItemStack terra$getItem(int slot) { + net.minecraft.item.ItemStack itemStack = ((LockableTileEntity) (Object) this).getItem(slot); + return itemStack.getItem() == Items.AIR ? null : (ItemStack) (Object) itemStack; + } + + @SuppressWarnings("ConstantConditions") + public void terra$setItem(int slot, ItemStack newStack) { + ((LockableTileEntity) (Object) this).setItem(slot, (net.minecraft.item.ItemStack) (Object) newStack); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemMixin.java new file mode 100644 index 000000000..a7efd1706 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemMixin.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.forge.mixin.implementations.inventory.item; + +import com.dfsek.terra.api.platform.inventory.ItemStack; +import net.minecraft.item.Item; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(Item.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.Item.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ItemMixin { + @Shadow + public abstract int getMaxDamage(); + + public Object terra$getHandle() { + return this; + } + + @SuppressWarnings("ConstantConditions") + public ItemStack terra$newItemStack(int amount) { + return (ItemStack) (Object) new net.minecraft.item.ItemStack((Item) (Object) this, amount); + } + + public double terra$getMaxDurability() { + return getMaxDamage(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemStackMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemStackMixin.java new file mode 100644 index 000000000..714dcab02 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemStackMixin.java @@ -0,0 +1,62 @@ +package com.dfsek.terra.forge.mixin.implementations.inventory.item; + +import com.dfsek.terra.api.platform.inventory.Item; +import com.dfsek.terra.api.platform.inventory.item.ItemMeta; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ItemStack.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.ItemStack.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ItemStackMixin { + @Shadow + public abstract int getCount(); + + @Shadow + public abstract void setCount(int count); + + @Shadow + public abstract net.minecraft.item.Item getItem(); + + + @Shadow + public abstract boolean isDamageableItem(); + + @Shadow + public abstract void setTag(@Nullable CompoundNBT p_77982_1_); + + public int terra$getAmount() { + return getCount(); + } + + public void terra$setAmount(int i) { + setCount(i); + } + + public Item terra$getType() { + return (Item) getItem(); + } + + public ItemMeta terra$getItemMeta() { + return (ItemMeta) this; + } + + @SuppressWarnings("ConstantConditions") + public void terra$setItemMeta(ItemMeta meta) { + setTag(((ItemStack) (Object) meta).getTag()); + } + + public Object terra$getHandle() { + return this; + } + + @Intrinsic + public boolean terra$isDamageable() { + return isDamageableItem(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/EnchantmentMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/EnchantmentMixin.java new file mode 100644 index 000000000..69bbfecaa --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/EnchantmentMixin.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.forge.mixin.implementations.inventory.meta; + +import com.dfsek.terra.api.platform.inventory.ItemStack; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Objects; + +@Mixin(Enchantment.class) +@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.item.Enchantment.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class EnchantmentMixin { + + @Shadow + public abstract boolean isCompatibleWith(Enchantment p_191560_1_); + + @Shadow + public abstract boolean canEnchant(net.minecraft.item.ItemStack p_92089_1_); + + public Object terra$getHandle() { + return this; + } + + @SuppressWarnings("ConstantConditions") + public boolean terra$canEnchantItem(ItemStack itemStack) { + return canEnchant((net.minecraft.item.ItemStack) (Object) itemStack); + } + + public String terra$getID() { + return Objects.requireNonNull(Registry.ENCHANTMENT.getId((Enchantment) (Object) this)).toString(); + } + + public boolean terra$conflictsWith(com.dfsek.terra.api.platform.inventory.item.Enchantment other) { + return !isCompatibleWith((Enchantment) other); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java new file mode 100644 index 000000000..8a1b438f5 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.forge.mixin.implementations.inventory.meta; + +import com.dfsek.terra.api.platform.inventory.item.Damageable; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ItemStack.class) +@Implements(@Interface(iface = Damageable.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ItemStackDamageableMixin { + @Shadow + public abstract boolean isDamaged(); + + @Shadow + public abstract int getDamageValue(); + + @Shadow + public abstract void setDamageValue(int p_196085_1_); + + public boolean terra$hasDamage() { + return isDamaged(); + } + + @Intrinsic + public void terra$setDamage(int damage) { + setDamageValue(damage); + } + + @Intrinsic + public int terra$getDamage() { + return getDamageValue(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackMetaMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackMetaMixin.java new file mode 100644 index 000000000..aa9b2a41b --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackMetaMixin.java @@ -0,0 +1,50 @@ +package com.dfsek.terra.forge.mixin.implementations.inventory.meta; + +import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.api.platform.inventory.item.ItemMeta; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +@Mixin(ItemStack.class) +@Implements(@Interface(iface = ItemMeta.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ItemStackMetaMixin { + @Shadow + public abstract ListNBT getEnchantmentTags(); + + @Shadow + public abstract boolean isEnchanted(); + + @Shadow + public abstract void enchant(net.minecraft.enchantment.Enchantment p_77966_1_, int p_77966_2_); + + public Object terra$getHandle() { + return this; + } + + @Intrinsic(displace = true) + public Map terra$getEnchantments() { + if(!isEnchanted()) return Collections.emptyMap(); + Map map = new HashMap<>(); + + getEnchantmentTags().forEach(enchantment -> { + CompoundNBT eTag = (CompoundNBT) enchantment; + map.put((Enchantment) Registry.ENCHANTMENT.byId(eTag.getInt("id")), eTag.getInt("lvl")); + }); + return map; + } + + public void terra$addEnchantment(Enchantment enchantment, int level) { + enchant((net.minecraft.enchantment.Enchantment) enchantment, level); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/package-info.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/package-info.java new file mode 100644 index 000000000..0fae9920e --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/package-info.java @@ -0,0 +1,5 @@ +/** + * Mixins in this package implement Terra + * interfaces in Minecraft classes. + */ +package com.dfsek.terra.forge.mixin.implementations; \ No newline at end of file diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/ServerWorldMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/ServerWorldMixin.java new file mode 100644 index 000000000..024b4970d --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/ServerWorldMixin.java @@ -0,0 +1,86 @@ +package com.dfsek.terra.forge.mixin.implementations.world; + +import com.dfsek.terra.api.math.vector.Location; +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.Chunk; +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 com.dfsek.terra.api.world.generation.TerraChunkGenerator; +import com.dfsek.terra.forge.block.ForgeBlock; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IServerWorld; +import net.minecraft.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ServerWorld.class) +@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class ServerWorldMixin { + @Shadow + public abstract long getSeed(); + + public int terra$getMaxHeight() { + return ((ServerWorld) (Object) this).getMaxBuildHeight(); + } + + public ChunkGenerator terra$getGenerator() { + return (ChunkGenerator) ((ServerWorld) (Object) this).getChunkSource().getGenerator(); + } + + public Chunk terra$getChunkAt(int x, int z) { + return (Chunk) ((ServerWorld) (Object) this).getChunk(x, z); + } + + public Block terra$getBlockAt(int x, int y, int z) { + return new ForgeBlock(new BlockPos(x, y, z), ((ServerWorld) (Object) this)); + } + + public Entity terra$spawnEntity(Location location, EntityType entityType) { + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(((ServerWorld) (Object) this)); + entity.setPos(location.getX(), location.getY(), location.getZ()); + ((ServerWorld) (Object) this).addFreshEntity(entity); + return (Entity) entity; + } + + @Intrinsic + public long terra$getSeed() { + return getSeed(); + } + + public int terra$getMinHeight() { + return 0; + } + + public Object terra$getHandle() { + return this; + } + + public boolean terra$isTerraWorld() { + return terra$getGenerator() instanceof GeneratorWrapper; + } + + public TerraChunkGenerator terra$getTerraGenerator() { + return ((ForgeChunkGeneratorWrapper) terra$getGenerator()).getHandle(); + } + + /** + * Overridden in the same manner as {@link WorldGenRegionMixin#hashCode()} + * + * @param other Another object + * @return Whether this world is the same as other. + * @see WorldGenRegionMixin#hashCode() + */ + @SuppressWarnings("ConstantConditions") + @Override + public boolean equals(Object other) { + if(!(other instanceof IServerWorld)) return false; + return (IServerWorld) this == (((IServerWorld) other).getLevel()); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/WorldGenRegionMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/WorldGenRegionMixin.java new file mode 100644 index 000000000..0b162b591 --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/WorldGenRegionMixin.java @@ -0,0 +1,108 @@ +package com.dfsek.terra.forge.mixin.implementations.world; + +import com.dfsek.terra.api.math.vector.Location; +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.Chunk; +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 com.dfsek.terra.api.world.generation.TerraChunkGenerator; +import com.dfsek.terra.forge.block.ForgeBlock; +import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.WorldGenRegion; +import net.minecraft.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(WorldGenRegion.class) +@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE)) +public abstract class WorldGenRegionMixin { + @Shadow + @Final + private ServerWorld level; + + @Shadow + @Final + private long seed; + + public int terra$getMaxHeight() { + return ((WorldGenRegion) (Object) this).getMaxBuildHeight(); + } + + @SuppressWarnings("deprecation") + public ChunkGenerator terra$getGenerator() { + return (ChunkGenerator) ((WorldGenRegion) (Object) this).getLevel().getChunkSource().getGenerator(); + } + + public Chunk terra$getChunkAt(int x, int z) { + return (Chunk) ((WorldGenRegion) (Object) this).getChunk(x, z); + } + + public Block terra$getBlockAt(int x, int y, int z) { + return new ForgeBlock(new BlockPos(x, y, z), ((WorldGenRegion) (Object) this)); + } + + @SuppressWarnings("deprecation") + public Entity terra$spawnEntity(Location location, EntityType entityType) { + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(((WorldGenRegion) (Object) this).getLevel()); + entity.setPos(location.getX(), location.getY(), location.getZ()); + ((WorldGenRegion) (Object) this).addFreshEntity(entity); + return (Entity) entity; + } + + @Intrinsic + public long terra$getSeed() { + return seed; + } + + public int terra$getMinHeight() { + return 0; + } + + public Object terra$getHandle() { + return this; + } + + public boolean terra$isTerraWorld() { + return terra$getGenerator() instanceof GeneratorWrapper; + } + + public TerraChunkGenerator terra$getTerraGenerator() { + return ((ForgeChunkGeneratorWrapper) terra$getGenerator()).getHandle(); + } + + /** + * We need regions delegating to the same world + * to have the same hashcode. This + * minimizes cache misses. + *

+ * This is sort of jank, but shouldn't(tm) + * break any other mods, unless they're doing + * something they really shouldn't, since + * ChunkRegions are not supposed to persist. + */ + @Override + public int hashCode() { + return level.hashCode(); + } + + /** + * Overridden in the same manner as {@link #hashCode()} + * + * @param other Another object + * @return Whether this world is the same as other. + * @see #hashCode() + */ + @Override + public boolean equals(Object other) { + if(!(other instanceof WorldGenRegion)) return false; + return level.equals(((WorldGenRegion) other).getLevel()); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftClientMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftClientMixin.java new file mode 100644 index 000000000..84245b37e --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftClientMixin.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.forge.mixin.init; + +import com.dfsek.terra.forge.TerraForgePlugin; +import com.dfsek.terra.forge.generation.TerraGeneratorType; +import com.dfsek.terra.forge.mixin.access.BiomeGeneratorTypeScreensAccessor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens; +import net.minecraft.resources.ResourcePackList; +import net.minecraft.util.text.StringTextComponent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(Minecraft.class) +public abstract class MinecraftClientMixin { + @Redirect(method = "", at = @At(value = "INVOKE", + target = "Lnet/minecraft/resources/ResourcePackList;reload()V" // sorta arbitrary position, after mod init, before window opens + )) + public void injectConstructor(ResourcePackList resourcePackList) { + TerraForgePlugin.getInstance().init(); // Load during MinecraftClient construction, after other mods have registered blocks and stuff + TerraForgePlugin.getInstance().getConfigRegistry().forEach(pack -> { + final BiomeGeneratorTypeScreens generatorType = new TerraGeneratorType(pack); + //noinspection ConstantConditions + ((BiomeGeneratorTypeScreensAccessor) generatorType).setDescription(new StringTextComponent("Terra:" + pack.getTemplate().getID())); + BiomeGeneratorTypeScreensAccessor.getPresets().add(1, generatorType); + }); + resourcePackList.reload(); + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftServerMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftServerMixin.java new file mode 100644 index 000000000..d8fed32cf --- /dev/null +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftServerMixin.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.forge.mixin.init; + +import com.dfsek.terra.forge.TerraForgePlugin; +import net.minecraft.server.Main; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Main.class) +public class MinecraftServerMixin { + @Inject(method = "main([Ljava/lang/String;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/DynamicRegistries;builtin()Lnet/minecraft/util/registry/DynamicRegistries$Impl;")) + private static void injectConstructor(String[] args, CallbackInfo ci) { + TerraForgePlugin.getInstance().init(); // Load during MinecraftServer construction, after other mods have registered blocks and stuff + } +} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeAdapter.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeAdapter.java deleted file mode 100644 index 1d34cdf03..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeAdapter.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.dfsek.terra.forge.world; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.dfsek.terra.forge.inventory.ForgeEnchantment; -import com.dfsek.terra.forge.inventory.ForgeItem; -import com.dfsek.terra.forge.inventory.ForgeItemStack; -import com.dfsek.terra.forge.world.block.ForgeBlockData; -import com.dfsek.terra.forge.world.block.ForgeBlockType; -import com.dfsek.terra.forge.world.block.data.ForgeDirectional; -import com.dfsek.terra.forge.world.block.data.ForgeMultipleFacing; -import com.dfsek.terra.forge.world.block.data.ForgeOrientable; -import com.dfsek.terra.forge.world.block.data.ForgeRotatable; -import com.dfsek.terra.forge.world.block.data.ForgeSlab; -import com.dfsek.terra.forge.world.block.data.ForgeStairs; -import com.dfsek.terra.forge.world.block.data.ForgeWaterlogged; -import com.dfsek.terra.forge.world.entity.ForgeCommandSender; -import com.dfsek.terra.forge.world.entity.ForgeEntityType; -import com.dfsek.terra.forge.world.entity.ForgePlayer; -import com.dfsek.terra.forge.world.handles.world.ForgeWorldHandle; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.command.CommandSource; -import net.minecraft.command.ICommandSource; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IWorld; - -import java.util.Arrays; - -public final class ForgeAdapter { - public static BlockPos adapt(Vector3 v) { - return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ()); - } - - public static Vector3 adapt(BlockPos pos) { - return new Vector3(pos.getX(), pos.getY(), pos.getZ()); - } - - public static ForgeBlockData adapt(BlockState state) { - if(state.hasProperty(BlockStateProperties.STAIRS_SHAPE)) return new ForgeStairs(state); - - if(state.hasProperty(BlockStateProperties.SLAB_TYPE)) return new ForgeSlab(state); - - if(state.hasProperty(BlockStateProperties.AXIS)) return new ForgeOrientable(state, BlockStateProperties.AXIS); - if(state.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) return new ForgeOrientable(state, BlockStateProperties.HORIZONTAL_AXIS); - - if(state.hasProperty(BlockStateProperties.ROTATION_16)) return new ForgeRotatable(state); - - if(state.hasProperty(BlockStateProperties.FACING)) return new ForgeDirectional(state, BlockStateProperties.FACING); - if(state.hasProperty(BlockStateProperties.FACING_HOPPER)) return new ForgeDirectional(state, BlockStateProperties.FACING_HOPPER); - if(state.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) return new ForgeDirectional(state, BlockStateProperties.HORIZONTAL_FACING); - - if(state.getProperties().containsAll(Arrays.asList(BlockStateProperties.NORTH, BlockStateProperties.SOUTH, BlockStateProperties.EAST, BlockStateProperties.WEST))) - return new ForgeMultipleFacing(state); - if(state.hasProperty(BlockStateProperties.WATERLOGGED)) return new ForgeWaterlogged(state); - return new ForgeBlockData(state); - } - - public static CommandSender adapt(CommandSource serverCommandSource) { - if(serverCommandSource.getEntity() instanceof PlayerEntity) return new ForgePlayer((PlayerEntity) serverCommandSource.getEntity()); - return new ForgeCommandSender(serverCommandSource); - } - - public static Direction adapt(BlockFace face) { - switch(face) { - case NORTH: - return Direction.NORTH; - case WEST: - return Direction.WEST; - case SOUTH: - return Direction.SOUTH; - case EAST: - return Direction.EAST; - case UP: - return Direction.UP; - case DOWN: - return Direction.DOWN; - default: - throw new IllegalArgumentException("Illegal direction: " + face); - } - } - - public static BlockType adapt(Block block) { - return new ForgeBlockType(block); - } - - public static EntityType adapt(net.minecraft.entity.EntityType entityType) { - return new ForgeEntityType(entityType); - } - - public static net.minecraft.entity.EntityType adapt(EntityType entityType) { - return ((ForgeEntityType) entityType).getHandle(); - } - - public static ItemStack adapt(com.dfsek.terra.api.platform.inventory.ItemStack itemStack) { - return ((ForgeItemStack) itemStack).getHandle(); - } - - public static com.dfsek.terra.api.platform.inventory.ItemStack adapt(ItemStack itemStack) { - return new ForgeItemStack(itemStack); - } - - public static com.dfsek.terra.api.platform.inventory.Item adapt(Item item) { - return new ForgeItem(item); - } - - public static Enchantment adapt(net.minecraft.enchantment.Enchantment enchantment) { - return new ForgeEnchantment(enchantment); - } - - public static net.minecraft.enchantment.Enchantment adapt(Enchantment enchantment) { - return ((ForgeEnchantment) enchantment).getHandle(); - } - - public IWorld adapt(ForgeWorldHandle worldHandle) { - return worldHandle.getWorld(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeBiome.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeBiome.java deleted file mode 100644 index cfddb6e88..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeBiome.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.forge.world; - -import com.dfsek.terra.api.platform.world.Biome; - -public class ForgeBiome implements Biome { - private final net.minecraft.world.biome.Biome delegate; - - public ForgeBiome(net.minecraft.world.biome.Biome delegate) { - this.delegate = delegate; - } - - - @Override - public net.minecraft.world.biome.Biome getHandle() { - return delegate; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeTree.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeTree.java deleted file mode 100644 index c94b85a29..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/ForgeTree.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dfsek.terra.forge.world; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.forge.world.generator.ForgeChunkGenerator; -import com.dfsek.terra.forge.world.handles.world.ForgeWorldAccess; -import com.dfsek.terra.profiler.ProfileFrame; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.ISeedReader; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.feature.ConfiguredFeature; - -import java.util.Locale; -import java.util.Random; - -public class ForgeTree implements Tree { - private final ConfiguredFeature delegate; - private final String id; - private final TerraPlugin main; - - public ForgeTree(ConfiguredFeature delegate, String id, TerraPlugin main) { - this.delegate = delegate; - this.id = id; - this.main = main; - } - - @Override - public boolean plant(Location l, Random r) { - try(ProfileFrame ignore = main.getProfiler().profile("fabric_tree:" + id.toLowerCase(Locale.ROOT))) { - ForgeWorldAccess fabricWorldAccess = ((ForgeWorldAccess) l.getWorld()); - ChunkGenerator generatorWrapper = ((ForgeChunkGenerator) fabricWorldAccess.getGenerator()).getHandle(); - return delegate.place((ISeedReader) fabricWorldAccess.getHandle(), generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ())); - } - } - - @Override - public MaterialSet getSpawnable() { - return MaterialSet.get(main.getWorldHandle().createBlockData("minecraft:grass_block"), - main.getWorldHandle().createBlockData("minecraft:podzol"), - main.getWorldHandle().createBlockData("minecraft:mycelium")); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockType.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockType.java deleted file mode 100644 index 05c87167a..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/ForgeBlockType.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.forge.world.block; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.forge.world.ForgeAdapter; -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; - -public class ForgeBlockType implements BlockType { - private final Block delegate; - - public ForgeBlockType(Block delegate) { - this.delegate = delegate; - } - - @Override - public Block getHandle() { - return delegate; - } - - @Override - public BlockData getDefaultData() { - return ForgeAdapter.adapt(delegate.defaultBlockState()); - } - - @Override - public boolean isSolid() { - return delegate.defaultBlockState().canOcclude(); - } - - @Override - public boolean isWater() { - return delegate == Blocks.WATER; - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof ForgeBlockType)) return false; - return ((ForgeBlockType) obj).delegate == delegate; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeBlockState.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeBlockState.java deleted file mode 100644 index 1ad7a6098..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeBlockState.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.dfsek.terra.forge.world.block.state; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.forge.world.ForgeAdapter; -import com.dfsek.terra.forge.world.block.ForgeBlock; -import com.dfsek.terra.forge.world.handles.world.ForgeWorldHandle; -import net.minecraft.tileentity.LockableLootTileEntity; -import net.minecraft.tileentity.MobSpawnerTileEntity; -import net.minecraft.tileentity.SignTileEntity; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.IWorld; - -public class ForgeBlockState implements BlockState { - protected final TileEntity blockEntity; - private final IWorld worldAccess; - - public ForgeBlockState(TileEntity blockEntity, IWorld worldAccess) { - this.blockEntity = blockEntity; - this.worldAccess = worldAccess; - } - - public static ForgeBlockState newInstance(Block block) { - IWorld worldAccess = ((ForgeWorldHandle) block.getLocation().getWorld()).getWorld(); - - TileEntity entity = worldAccess.getBlockEntity(ForgeAdapter.adapt(block.getLocation().toVector())); - if(entity instanceof SignTileEntity) { - return new ForgeSign((SignTileEntity) entity, worldAccess); - } else if(entity instanceof MobSpawnerTileEntity) { - return new ForgeMobSpawner((MobSpawnerTileEntity) entity, worldAccess); - } else if(entity instanceof LockableLootTileEntity) { - return new ForgeContainer((LockableLootTileEntity) entity, worldAccess); - } - return null; - } - - @Override - public TileEntity getHandle() { - return blockEntity; - } - - @Override - public Block getBlock() { - return new ForgeBlock(blockEntity.getBlockPos(), blockEntity.getLevel()); - } - - @Override - public int getX() { - return blockEntity.getBlockPos().getX(); - } - - @Override - public int getY() { - return blockEntity.getBlockPos().getY(); - } - - @Override - public int getZ() { - return blockEntity.getBlockPos().getZ(); - } - - @Override - public BlockData getBlockData() { - return ForgeAdapter.adapt(blockEntity.getBlockState()); - } - - @Override - public boolean update(boolean applyPhysics) { - worldAccess.getChunk(blockEntity.getBlockPos()).setBlockEntity(blockEntity.getBlockPos(), blockEntity); - return true; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeContainer.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeContainer.java deleted file mode 100644 index c10c9ef03..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeContainer.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.forge.world.block.state; - -import com.dfsek.terra.api.platform.block.state.Container; -import com.dfsek.terra.api.platform.inventory.Inventory; -import com.dfsek.terra.forge.inventory.ForgeInventory; -import net.minecraft.tileentity.LockableLootTileEntity; -import net.minecraft.world.IWorld; - -public class ForgeContainer extends ForgeBlockState implements Container { - public ForgeContainer(LockableLootTileEntity blockEntity, IWorld worldAccess) { - super(blockEntity, worldAccess); - } - - @Override - public Inventory getInventory() { - return new ForgeInventory(((LockableLootTileEntity) blockEntity)); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeMobSpawner.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeMobSpawner.java deleted file mode 100644 index 95ca3d941..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeMobSpawner.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.dfsek.terra.forge.world.block.state; - -import com.dfsek.terra.api.platform.block.state.MobSpawner; -import com.dfsek.terra.api.platform.block.state.SerialState; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.forge.TerraForgePlugin; -import com.dfsek.terra.forge.world.ForgeAdapter; -import net.minecraft.tileentity.MobSpawnerTileEntity; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.IWorld; -import net.minecraftforge.registries.ForgeRegistries; -import org.jetbrains.annotations.NotNull; - -public class ForgeMobSpawner extends ForgeBlockState implements MobSpawner { // TODO: finish implementation / refactor API because bukkit doesnt expose most of the stuff spawners can do - - - public ForgeMobSpawner(MobSpawnerTileEntity blockEntity, IWorld worldAccess) { - super(blockEntity, worldAccess); - } - - @Override - public EntityType getSpawnedType() { - return ForgeAdapter.adapt(ForgeRegistries.ENTITIES.getValue(((MobSpawnerTileEntity) blockEntity).getSpawner().getSpawnerEntity().getType().getRegistryName())); - } - - @Override - public void setSpawnedType(@NotNull EntityType creatureType) { - ((MobSpawnerTileEntity) blockEntity).getSpawner().setEntityId(ForgeAdapter.adapt(creatureType)); - } - - @Override - public int getDelay() { - return 0; - } - - @Override - public void setDelay(int delay) { - - } - - @Override - public int getMinSpawnDelay() { - return 0; - } - - @Override - public void setMinSpawnDelay(int delay) { - - } - - @Override - public int getMaxSpawnDelay() { - return 0; - } - - @Override - public void setMaxSpawnDelay(int delay) { - - } - - @Override - public int getSpawnCount() { - return 0; - } - - @Override - public void setSpawnCount(int spawnCount) { - - } - - @Override - public int getMaxNearbyEntities() { - return 0; - } - - @Override - public void setMaxNearbyEntities(int maxNearbyEntities) { - - } - - @Override - public int getRequiredPlayerRange() { - return 0; - } - - @Override - public void setRequiredPlayerRange(int requiredPlayerRange) { - - } - - @Override - public int getSpawnRange() { - return 0; - } - - @Override - public void setSpawnRange(int spawnRange) { - - } - - @Override - public void applyState(String state) { - SerialState.parse(state).forEach((k, v) -> { - switch(k) { - case "type": - setSpawnedType(TerraForgePlugin.getInstance().getWorldHandle().getEntity(v)); - return; - case "delay": - setDelay(Integer.parseInt(v)); - return; - case "min_delay": - setMinSpawnDelay(Integer.parseInt(v)); - return; - case "max_delay": - setMaxSpawnDelay(Integer.parseInt(v)); - return; - case "spawn_count": - setSpawnCount(Integer.parseInt(v)); - return; - case "spawn_range": - setSpawnRange(Integer.parseInt(v)); - return; - case "max_nearby": - setMaxNearbyEntities(Integer.parseInt(v)); - return; - case "required_player_range": - setRequiredPlayerRange(Integer.parseInt(v)); - return; - default: - throw new IllegalArgumentException("Invalid property: " + k); - } - }); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeSign.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeSign.java deleted file mode 100644 index 899fe900e..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/block/state/ForgeSign.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dfsek.terra.forge.world.block.state; - -import com.dfsek.terra.api.platform.block.state.SerialState; -import com.dfsek.terra.api.platform.block.state.Sign; -import net.minecraft.tileentity.SignTileEntity; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.world.IWorld; -import org.jetbrains.annotations.NotNull; - -public class ForgeSign extends ForgeBlockState implements Sign { - public ForgeSign(SignTileEntity blockEntity, IWorld worldAccess) { - super(blockEntity, worldAccess); - } - - @Override - public @NotNull String[] getLines() { - SignTileEntity sign = (SignTileEntity) blockEntity; - - return new String[] { - sign.getMessage(0).getString(), - sign.getMessage(1).getString(), - sign.getMessage(2).getString(), - sign.getMessage(3).getString() - }; - } - - @Override - public @NotNull String getLine(int index) throws IndexOutOfBoundsException { - return ((SignTileEntity) blockEntity).getMessage(index).getString(); - } - - @Override - public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { - ((SignTileEntity) blockEntity).setMessage(index, new StringTextComponent(line)); - } - - @Override - public void applyState(String state) { - SerialState.parse(state).forEach((k, v) -> { - if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); - setLine(Integer.parseInt(k.substring(4)), v); - }); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeCommandSender.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeCommandSender.java deleted file mode 100644 index 042efbae3..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeCommandSender.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dfsek.terra.forge.world.entity; - -import com.dfsek.terra.api.platform.CommandSender; -import net.minecraft.command.CommandSource; -import net.minecraft.util.text.StringTextComponent; - -public class ForgeCommandSender implements CommandSender { - private final CommandSource delegate; - - public ForgeCommandSender(CommandSource delegate) { - this.delegate = delegate; - } - - @Override - public void sendMessage(String message) { - delegate.sendSuccess(new StringTextComponent(message), true); - } - - @Override - public Object getHandle() { - return delegate; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntity.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntity.java deleted file mode 100644 index df35af7fb..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntity.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.dfsek.terra.forge.world.entity; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.forge.world.ForgeAdapter; -import com.dfsek.terra.forge.world.handles.world.ForgeWorldAccess; -import com.dfsek.terra.forge.world.handles.world.ForgeWorldHandle; -import net.minecraft.world.server.ServerWorld; - -public class ForgeEntity implements Entity { - private final net.minecraft.entity.Entity delegate; - - public ForgeEntity(net.minecraft.entity.Entity delegate) { - this.delegate = delegate; - } - - @Override - public void sendMessage(String message) { - - } - - @Override - public Object getHandle() { - return null; - } - - @Override - public Location getLocation() { - return new Location(new ForgeWorldAccess(delegate.level), ForgeAdapter.adapt(delegate.blockPosition())); - } - - @Override - public void setLocation(Location location) { - delegate.teleportTo(location.getX(), location.getY(), location.getZ()); - delegate.setLevel((ServerWorld) ((ForgeWorldHandle) location).getWorld()); - } - - @Override - public World getWorld() { - return new ForgeWorldAccess(delegate.level); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntityType.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntityType.java deleted file mode 100644 index 42ad0e91d..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgeEntityType.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.forge.world.entity; - -import com.dfsek.terra.api.platform.entity.EntityType; - -public class ForgeEntityType implements EntityType { - private final net.minecraft.entity.EntityType type; - - public ForgeEntityType(net.minecraft.entity.EntityType type) { - this.type = type; - } - - @Override - public net.minecraft.entity.EntityType getHandle() { - return type; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgePlayer.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgePlayer.java deleted file mode 100644 index 87ea1ebc1..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/entity/ForgePlayer.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dfsek.terra.forge.world.entity; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.forge.world.ForgeAdapter; -import com.dfsek.terra.forge.world.handles.world.ForgeWorldAccess; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.text.StringTextComponent; - -public class ForgePlayer implements Player { - private final PlayerEntity delegate; - - public ForgePlayer(PlayerEntity delegate) { - this.delegate = delegate; - } - - @Override - public void sendMessage(String message) { - delegate.displayClientMessage(new StringTextComponent(message), false); - } - - @Override - public Object getHandle() { - return delegate; - } - - @Override - public Location getLocation() { - return ForgeAdapter.adapt(delegate.blockPosition()).toLocation(new ForgeWorldAccess(delegate.level)); - } - - @Override - public World getWorld() { - return new ForgeWorldAccess(delegate.level); - } - - @Override - public void setLocation(Location location) { - delegate.teleportTo(location.getX(), location.getY(), location.getZ()); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkData.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkData.java deleted file mode 100644 index 14415feed..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkData.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.dfsek.terra.forge.world.generator; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.generator.ChunkData; -import com.dfsek.terra.forge.world.block.ForgeBlockData; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.IChunk; -import org.jetbrains.annotations.NotNull; - -public class ForgeChunkData implements ChunkData { - private final IChunk handle; - - public ForgeChunkData(IChunk handle) { - this.handle = handle; - } - - @Override - public IChunk getHandle() { - return handle; - } - - @Override - public int getMaxHeight() { - return handle.getMaxBuildHeight(); - } - - @Override - public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { - handle.setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false); - } - - @Override - public @NotNull BlockData getBlockData(int x, int y, int z) { - return new ForgeBlockData(handle.getBlockState(new BlockPos(x, y, z))); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGenerator.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGenerator.java deleted file mode 100644 index dad4fe98b..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/ForgeChunkGenerator.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.forge.world.generator; - -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; - -public class ForgeChunkGenerator implements ChunkGenerator { - private final net.minecraft.world.gen.ChunkGenerator delegate; - - public ForgeChunkGenerator(net.minecraft.world.gen.ChunkGenerator delegate) { - this.delegate = delegate; - } - - @Override - public net.minecraft.world.gen.ChunkGenerator getHandle() { - return delegate; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/config/TerraLevelType.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/config/TerraLevelType.java deleted file mode 100644 index 2d8503af7..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/generator/config/TerraLevelType.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.dfsek.terra.forge.world.generator.config; - -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.forge.TerraForgePlugin; -import com.dfsek.terra.forge.world.TerraBiomeSource; -import com.dfsek.terra.forge.world.generator.ForgeChunkGeneratorWrapper; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.DimensionSettings; -import net.minecraftforge.common.world.ForgeWorldType; - -public class TerraLevelType implements ForgeWorldType.IChunkGeneratorFactory { - public static final TerraLevelType TERRA_LEVEL_TYPE = new TerraLevelType(); - public static final ForgeWorldType FORGE_WORLD_TYPE = new ForgeWorldType(TERRA_LEVEL_TYPE).setRegistryName("terra", "world"); - @Override - public ChunkGenerator createChunkGenerator(Registry biomeRegistry, Registry dimensionSettingsRegistry, long seed, String generatorSettings) { - System.out.println(generatorSettings); - dimensionSettingsRegistry.forEach(System.out::println); - ConfigPack pack = TerraForgePlugin.getInstance().getConfigRegistry().get("DEFAULT"); - TerraForgePlugin.getInstance().logger().info("Creating generator for config pack " + pack.getTemplate().getID()); - return new ForgeChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/ForgeWorld.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/ForgeWorld.java deleted file mode 100644 index a4bfa54e2..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/ForgeWorld.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.dfsek.terra.forge.world.handles; - -import com.dfsek.terra.api.math.vector.Location; -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.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.forge.world.ForgeAdapter; -import com.dfsek.terra.forge.world.block.ForgeBlock; -import com.dfsek.terra.forge.world.entity.ForgeEntity; -import com.dfsek.terra.forge.world.handles.chunk.ForgeChunk; -import com.dfsek.terra.forge.world.handles.world.ForgeWorldHandle; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IServerWorld; -import net.minecraft.world.server.ServerWorld; - -public class ForgeWorld implements World, ForgeWorldHandle { - - private final Handle delegate; - - public ForgeWorld(ServerWorld world, ChunkGenerator generator) { - this.delegate = new Handle(world, generator); - } - - @Override - public long getSeed() { - return delegate.world.getSeed(); - } - - @Override - public int getMaxHeight() { - return delegate.world.getHeight(); - } - - @Override - public ChunkGenerator getGenerator() { - return delegate.generator; - } - - @Override - public Chunk getChunkAt(int x, int z) { - return new ForgeChunk(delegate.world.getChunk(x, z)); - } - - @Override - public Block getBlockAt(int x, int y, int z) { - BlockPos pos = new BlockPos(x, y, z); - return new ForgeBlock(pos, delegate.world); - } - - @Override - public int hashCode() { - return ((IServerWorld) delegate.world).getLevel().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof ForgeWorld)) return false; - return ((IServerWorld) ((ForgeWorld) obj).delegate.world).getLevel().equals(((IServerWorld) delegate.world).getLevel()); - } - - @Override - public Entity spawnEntity(Location location, EntityType entityType) { - net.minecraft.entity.Entity entity = ForgeAdapter.adapt(entityType).create(delegate.world); - entity.setPos(location.getX(), location.getY(), location.getZ()); - delegate.world.addFreshEntity(entity); - return new ForgeEntity(entity); - } - - @Override - public int getMinHeight() { - return 0; - } - - @Override - public Handle getHandle() { - return null; - } - - @Override - public ServerWorld getWorld() { - return delegate.getWorld(); - } - - public static final class Handle { - private final ServerWorld world; - private final ChunkGenerator generator; - - private Handle(ServerWorld world, ChunkGenerator generator) { - this.world = world; - this.generator = generator; - } - - public ChunkGenerator getGenerator() { - return generator; - } - - public ServerWorld getWorld() { - return world; - } - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunk.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunk.java deleted file mode 100644 index da28514f9..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunk.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.forge.world.handles.chunk; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.forge.world.block.ForgeBlockData; -import net.minecraft.util.math.BlockPos; -import org.jetbrains.annotations.NotNull; - -public class ForgeChunk implements Chunk { - private final net.minecraft.world.chunk.Chunk chunk; - - public ForgeChunk(net.minecraft.world.chunk.Chunk chunk) { - this.chunk = chunk; - } - - @Override - public int getX() { - return chunk.getPos().x; - } - - @Override - public int getZ() { - return chunk.getPos().z; - } - - @Override - public World getWorld() { - return null; - } - - @Override - public Block getBlock(int x, int y, int z) { - return null; - } - - @Override - public net.minecraft.world.chunk.Chunk getHandle() { - return chunk; - } - - @Override - public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { - chunk.setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false); - } - - @Override - public @NotNull BlockData getBlockData(int x, int y, int z) { - return getBlock(x, y, z).getBlockData(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunkWorldAccess.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunkWorldAccess.java deleted file mode 100644 index a405910c4..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/chunk/ForgeChunkWorldAccess.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.dfsek.terra.forge.world.handles.chunk; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.forge.world.block.ForgeBlock; -import com.dfsek.terra.forge.world.block.ForgeBlockData; -import com.dfsek.terra.forge.world.handles.world.ForgeWorldAccess; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IWorld; -import org.jetbrains.annotations.NotNull; - -public class ForgeChunkWorldAccess implements Chunk { - private final IWorld chunkRegion; - private final int x; - private final int z; - - public ForgeChunkWorldAccess(IWorld chunkRegion, int x, int z) { - this.chunkRegion = chunkRegion; - this.x = x << 4; - this.z = z << 4; - } - - @Override - public int getX() { - return x >> 4; - } - - @Override - public int getZ() { - return z >> 4; - } - - @Override - public World getWorld() { - return new ForgeWorldAccess(chunkRegion); - } - - @Override - public Block getBlock(int x, int y, int z) { - BlockPos pos = new BlockPos(x + this.x, y, z + this.z); - return new ForgeBlock(pos, chunkRegion); - } - - @Override - public IWorld getHandle() { - return chunkRegion; - } - - @Override - public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { - chunkRegion.setBlock(new BlockPos(x + this.x, y, z + this.z), ((ForgeBlockData) blockData).getHandle(), 0); - } - - @Override - public @NotNull BlockData getBlockData(int x, int y, int z) { - return getBlock(x, y, z).getBlockData(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeSeededWorldAccess.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeSeededWorldAccess.java deleted file mode 100644 index bbc5aa411..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeSeededWorldAccess.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.dfsek.terra.forge.world.handles.world; - -import com.dfsek.terra.api.math.vector.Location; -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.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.forge.world.ForgeAdapter; -import com.dfsek.terra.forge.world.block.ForgeBlock; -import com.dfsek.terra.forge.world.entity.ForgeEntity; -import com.dfsek.terra.forge.world.generator.ForgeChunkGenerator; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IServerWorld; -import net.minecraft.world.IWorld; -import net.minecraft.world.server.ServerWorld; - -public class ForgeSeededWorldAccess implements World, ForgeWorldHandle { - - private final Handle handle; - - public ForgeSeededWorldAccess(IWorld access, long seed, net.minecraft.world.gen.ChunkGenerator generator) { - this.handle = new Handle(access, seed, generator); - } - - @Override - public long getSeed() { - return handle.getSeed(); - } - - @Override - public int getMaxHeight() { - return handle.getWorldAccess().getMaxBuildHeight(); - } - - @Override - public ChunkGenerator getGenerator() { - return new ForgeChunkGenerator(handle.getGenerator()); - } - - @Override - public Chunk getChunkAt(int x, int z) { - return null; - } - - @Override - public Block getBlockAt(int x, int y, int z) { - BlockPos pos = new BlockPos(x, y, z); - return new ForgeBlock(pos, handle.worldAccess); - } - - @Override - public Entity spawnEntity(Location location, EntityType entityType) { - net.minecraft.entity.Entity entity = ForgeAdapter.adapt(entityType).create((ServerWorld) handle.worldAccess); - entity.setPos(location.getX(), location.getY(), location.getZ()); - handle.worldAccess.addFreshEntity(entity); - return new ForgeEntity(entity); - } - - @Override - public int getMinHeight() { - return 0; - } - - @Override - public int hashCode() { - return ((IServerWorld) handle.worldAccess).getLevel().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof ForgeSeededWorldAccess)) return false; - return ((IServerWorld) ((ForgeSeededWorldAccess) obj).handle.worldAccess).getLevel().equals(((IServerWorld) handle.worldAccess).getLevel()); - } - - @Override - public Handle getHandle() { - return handle; - } - - @Override - public IWorld getWorld() { - return handle.worldAccess; - } - - public static class Handle { - private final IWorld worldAccess; - private final long seed; - private final net.minecraft.world.gen.ChunkGenerator generator; - - public Handle(IWorld worldAccess, long seed, net.minecraft.world.gen.ChunkGenerator generator) { - this.worldAccess = worldAccess; - this.seed = seed; - this.generator = generator; - } - - public net.minecraft.world.gen.ChunkGenerator getGenerator() { - return generator; - } - - public long getSeed() { - return seed; - } - - public IWorld getWorldAccess() { - return worldAccess; - } - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldAccess.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldAccess.java deleted file mode 100644 index 8a061d49b..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldAccess.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.dfsek.terra.forge.world.handles.world; - -import com.dfsek.terra.api.math.vector.Location; -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.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.forge.world.ForgeAdapter; -import com.dfsek.terra.forge.world.block.ForgeBlock; -import com.dfsek.terra.forge.world.entity.ForgeEntity; -import com.dfsek.terra.forge.world.generator.ForgeChunkGenerator; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.ISeedReader; -import net.minecraft.world.IServerWorld; -import net.minecraft.world.IWorld; - -public class ForgeWorldAccess implements World, ForgeWorldHandle { - private final IWorld delegate; - - public ForgeWorldAccess(IWorld delegate) { - this.delegate = delegate; - } - - @Override - public long getSeed() { - return ((ISeedReader) delegate).getSeed(); - } - - @Override - public int getMaxHeight() { - return delegate.getHeight(); - } - - @Override - public ChunkGenerator getGenerator() { - return new ForgeChunkGenerator(((IServerWorld) delegate).getLevel().getChunkSource().getGenerator()); - } - - @Override - public Chunk getChunkAt(int x, int z) { - return null; - } - - @Override - public Block getBlockAt(int x, int y, int z) { - BlockPos pos = new BlockPos(x, y, z); - return new ForgeBlock(pos, delegate); - } - - @Override - public Entity spawnEntity(Location location, EntityType entityType) { - net.minecraft.entity.Entity entity = ForgeAdapter.adapt(entityType).create(((IServerWorld) delegate).getLevel()); - entity.setPos(location.getX(), location.getY(), location.getZ()); - delegate.addFreshEntity(entity); - return new ForgeEntity(entity); - } - - @Override - public int getMinHeight() { - return 0; - } - - @Override - public IWorld getHandle() { - return delegate; - } - - @Override - public IWorld getWorld() { - return delegate; - } - - @Override - public int hashCode() { - return ((IServerWorld) delegate).getLevel().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof ForgeWorldAccess)) return false; - return ((IServerWorld) ((ForgeWorldAccess) obj).delegate).getLevel().equals(((IServerWorld) delegate).getLevel()); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldHandle.java deleted file mode 100644 index a0790e276..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/world/handles/world/ForgeWorldHandle.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.forge.world.handles.world; - -import net.minecraft.world.IWorld; - -public interface ForgeWorldHandle { - IWorld getWorld(); -} diff --git a/platforms/forge/src/main/resources/META-INF/mods.toml b/platforms/forge/src/main/resources/META-INF/mods.toml index 15baa899e..a306898d9 100644 --- a/platforms/forge/src/main/resources/META-INF/mods.toml +++ b/platforms/forge/src/main/resources/META-INF/mods.toml @@ -1,17 +1,17 @@ -modLoader="javafml" -loaderVersion="[36,)" -license="GNU General Public License, version 3.0" -issueTrackerURL="https://github.com/PolyhedralDev/Terra/issues/" +modLoader = "javafml" +loaderVersion = "[36,)" +license = "@LICENSE@" +issueTrackerURL = "@ISSUES@" [[mods]] -modId="terra" -version="@VERSION@" -displayName="Terra" -displayURL="https://github.com/PolyhedralDev/Terra/" -authors="dfsek & Terra contributors" -description="Data-driven world generator" +modId = "terra" +version = "@VERSION@" +displayName = "Terra" +displayURL = "@WIKI@" +authors = "dfsek & Terra contributors" +description = "@DESCRIPTION@" [[dependencies.terra]] - modId="forge" - mandatory=true - versionRange="[36,)" - ordering="NONE" - side="BOTH" \ No newline at end of file +modId = "forge" +mandatory = true +versionRange = "[36,)" +ordering = "NONE" +side = "BOTH" \ No newline at end of file diff --git a/platforms/forge/src/main/resources/terra.mixins.json b/platforms/forge/src/main/resources/terra.mixins.json index c18783888..5aefcf5f0 100644 --- a/platforms/forge/src/main/resources/terra.mixins.json +++ b/platforms/forge/src/main/resources/terra.mixins.json @@ -4,8 +4,39 @@ "compatibilityLevel": "JAVA_8", "refmap": "terra-refmap.json", "mixins": [ + "DimensionGeneratorSettingsMixin", + "ServerWorldMixin", + "access.AbstractSpawnerAccessor", + "access.BiomeGeneratorTypeScreensAccessor", + "implementations.BiomeMixin", + "implementations.ChunkGeneratorMixin", + "implementations.ConfiguredFeatureMixin", + "implementations.block.BlockMixin", + "implementations.block.TileEntityMixin", + "implementations.block.state.LockableLootTileEntityMixin", + "implementations.block.state.MobSpawnerTileEntityMixin", + "implementations.block.state.SignTileEntityMixin", + "implementations.chunk.ChunkMixin", + "implementations.chunk.WorldGenRegionMixin", + "implementations.chunk.data.ChunkPrimerMixin", + "implementations.entity.CommandSourceMixin", + "implementations.entity.EntityMixin", + "implementations.entity.EntityTypeMixin", + "implementations.entity.PlayerEntityMixin", + "implementations.inventory.LockableTileEntityMixin", + "implementations.inventory.item.ItemMixin", + "implementations.inventory.item.ItemStackMixin", + "implementations.inventory.meta.EnchantmentMixin", + "implementations.inventory.meta.ItemStackDamageableMixin", + "implementations.inventory.meta.ItemStackMetaMixin", + "implementations.world.ServerWorldMixin", + "implementations.world.WorldGenRegionMixin" ], "client": [ + "init.MinecraftClientMixin" + ], + "server": [ + "init.MinecraftServerMixin" ], "injectors": { "defaultRequire": 1