diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 08a7feb..920dbe0 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
- Please fill out the sections below to help identify and fix the bug
+ Please fill out the sections below to help identify and fix the bug.
- type: textarea
id: description
attributes:
diff --git a/.github/ISSUE_TEMPLATE/feature_request_template.yml b/.github/ISSUE_TEMPLATE/feature_request_template.yml
new file mode 100644
index 0000000..c1b507e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request_template.yml
@@ -0,0 +1,26 @@
+name: Feature Request
+description: Suggest a new feature for Sit!
+title: '[Feature Request]: '
+body:
+ - type: textarea
+ id: description
+ attributes:
+ label: Description
+ description: A description of the problem or missing capability
+ validations:
+ required: true
+ - type: textarea
+ id: solution
+ attributes:
+ label: Describe a solution
+ description: If you have a solution in mind, please describe it.
+ - type: textarea
+ id: alternatives
+ attributes:
+ label: Describe alternatives
+ description: Have you considered any alternative solutions or workarounds?
+ - type: markdown
+ attributes:
+ value: >-
+ This template was generated with [Issue Forms
+ Creator](https://issue-forms-creator.netlify.app)
\ No newline at end of file
diff --git a/.github/workflows/crowdin-download-workflow.yml b/.github/workflows/crowdin-download-workflow.yml
new file mode 100644
index 0000000..b769f5f
--- /dev/null
+++ b/.github/workflows/crowdin-download-workflow.yml
@@ -0,0 +1,125 @@
+name: Crowdin Download Action
+
+permissions:
+ contents: write
+ pull-requests: write
+
+on:
+ workflow_dispatch:
+ inputs:
+ localization_branch_name:
+ description: 'The branch to create for the translations PR.'
+ required: true
+ default: 'crowdin/translations'
+ pull_request_base_branch:
+ description: 'The base branch for the pull request.'
+ required: true
+ default: 'dev'
+
+jobs:
+ download-translations:
+ runs-on: ubuntu-latest
+ steps:
+ # Checkout the BASE branch first. The PR branch will be created later.
+ - name: Checkout Base Branch
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.inputs.pull_request_base_branch }}
+
+ - name: Configure Git User
+ run: |
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+
+ - name: Synchronize with Crowdin (Download Only)
+ uses: crowdin/github-action@v2
+ with:
+ upload_sources: false
+ upload_translations: false
+ download_translations: true
+ create_pull_request: false
+ localization_branch_name: ${{ github.event.inputs.localization_branch_name }}
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
+ CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
+
+ rename-files:
+ needs: download-translations
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Localization Branch
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.inputs.localization_branch_name }}
+
+ - name: Configure Git User
+ run: |
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+
+ - name: Rename JSON Files to Lowercase
+ env:
+ TARGET_DIR: "src/main/resources/assets/sit-oth3r/lang/"
+ run: |
+ echo "Starting renaming process for JSON files within $TARGET_DIR..."
+ if [ ! -d "$TARGET_DIR" ]; then
+ echo "Warning: Target directory '$TARGET_DIR' does not exist. Skipping rename."
+ exit 0
+ fi
+ find "$TARGET_DIR" -type f -name '*[A-Z]*.json' | while IFS= read -r file; do
+ original_path="$file"
+ dir_name=$(dirname "$original_path")
+ base_name=$(basename "$original_path")
+ new_base_name=$(echo "$base_name" | tr '[:upper:]' '[:lower:]')
+ new_path="$dir_name/$new_base_name"
+ if [ "$original_path" != "$new_path" ]; then
+ if [ -e "$new_path" ] && [ ! "$(readlink -f "$original_path")" = "$(readlink -f "$new_path")" ]; then
+ echo "::warning file=$original_path::Cannot rename '$original_path' to '$new_path' because it already exists. Skipping."
+ else
+ git mv "$original_path" "$new_path"
+ fi
+ fi
+ done
+ echo "JSON file renaming complete."
+
+ - name: Commit Renamed Files
+ run: |
+ echo "Committing renamed files..."
+ git add -A
+ git commit -m "Rename JSON translation files to lowercase for consistency"
+ echo "Renames committed."
+
+ - name: Push Changes to Localization Branch
+ run: |
+ echo "Pushing combined changes to ${{ github.event.inputs.localization_branch_name }}..."
+ git push origin ${{ github.event.inputs.localization_branch_name }}
+
+ create-pr:
+ needs: [ download-translations, rename-files ]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout branch
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.inputs.localization_branch_name }}
+
+ - name: Set up Git config
+ run: |
+ git config user.name "github-actions"
+ git config user.email "github-actions@github.com"
+
+ - name: Install GitHub CLI
+ run: sudo apt-get install gh -y
+
+ - name: Authenticate GitHub CLI
+ run: echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token
+
+ - name: Create Pull Request
+ run: |
+ gh pr create \
+ --title "Update translations from Crowdin" \
+ --body "This PR includes:\n- New translations from Crowdin\n- Renamed translation files to lowercase" \
+ --head ${{ github.event.inputs.localization_branch_name }} \
+ --base ${{ github.event.inputs.pull_request_base_branch }} \
+ --label "localization"
\ No newline at end of file
diff --git a/.github/workflows/crowdin-upload-workflow.yml b/.github/workflows/crowdin-upload-workflow.yml
new file mode 100644
index 0000000..5516194
--- /dev/null
+++ b/.github/workflows/crowdin-upload-workflow.yml
@@ -0,0 +1,24 @@
+name: Crowdin Upload Action
+
+on:
+ push:
+ paths: [ "src/main/resources/assets/sit-oth3r/lang/en_us.json"]
+ branches: [ dev ]
+ workflow_dispatch:
+
+jobs:
+ crowdin-upload:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Crowdin push
+ uses: crowdin/github-action@v2
+ with:
+ upload_sources: true
+ upload_translations: false
+ download_translations: false
+ env:
+ CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
+ CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
\ No newline at end of file
diff --git a/README.md b/README.md
index 4f01e02..47fbea2 100644
--- a/README.md
+++ b/README.md
@@ -1,46 +1,68 @@
-# Sit!
-[](https://github.com/Oth3r/Sit/releases) [](https://crowdin.com/project/oth3r-sit) [](https://discord.gg/Mec6yNQ9B7)
+
+
+[](https://github.com/Oth3r/Sit/releases) [](https://crowdin.com/project/oth3r-sit) [](https://www.oth3r.one/discord)
[](https://modrinth.com/mod/sit!) [](https://www.curseforge.com/minecraft/mc-mods/Sit1)
-**Sit!** is a minecraft mod that adds sitting in vanilla minecraft.
-Sit on **stairs**, **slabs**, **carpets** by default, and sit on everything else using the config!
-You can also customize hand restrictions to stop accidentally sitting down!
-The mod also has full Geyser support! Enjoy sitting with everyone, weather they are on Bedrock or Java!
+
+### **Sit!** is a vanilla+ mod that adds sitting in minecraft.
+* Sit on **stairs**, **slabs**, **carpets** by default, and sit on everything else by tweaking the config!
+* You can also customize **hand restrictions** to stop accidentally sitting down!
+* The mod also has full **Geyser** support! Enjoy sitting with everyone, whether they are on Bedrock or Java!
+* If Sit! clients join a Sit! server they can use **their own hand settings** to sit.
### Where to install?
-**Sit!** works on the server (singleplayer included), also with support for clients that join in to use their own settings to sit.
+**Sit!** works on the server, without the players needing to install the mod *(singleplayer included!)*.
+\
+[Fabric API](https://modrinth.com/mod/fabric-api) and [OtterLib](https://modrinth.com/mod/otterlib) is required to for the mod to load.
-## Help localize Sit! on [Crowdin](https://crowdin.com/project/oth3r-sit)!
-
+### Help localize Sit! on [Crowdin](https://crowdin.com/project/oth3r-sit)!
+Sit! is currently in English, Traditional Chinese, Italian, Brazilian Portuguese, and Turkish! Help expand this list via Crowdin so reach more people!
## Check out my other Projects!
-[](https://modrinth.com/mod/caligo)
-[](https://modrinth.com/mod/directionhud)
-[](https://modrinth.com/plugin/directionhud-plugin)
+
+
+
+
+
+
+
+
+
+
# Features
-### Hand Restrictions
+### 🤚 Hand Restrictions
Don't want to accidentally sit down? Set custom restrictions for each hand in the config!
+\
+Use **player unique** hand restrictions when connecting to a `Sit!` server on a `Sit!` Client!
-* Per player hand restrictions when connecting to a `Sit!` server on a `Sit!` Client!
+
-
+### 🟩 Custom Blocks
+Want to sit on _**EVERY**_ block? With the config you can add more sitting options!
+\
+With the new config system, block tags and custom blockstates can be used to mass select blocks at ease.
-### Custom Blocks
-Want to sit on _**EVERY**_ block? With the config you can add more options to sit on! Custom block states are also supported.
+
-
+### ⌨️ Keybinds
+Don't want to sit with the **just** the hand? Use a keybind or type a command to sit instead!
-### Customizable Config
-Configure to your hearts desire with the in-game config with **[ModMenu](https://modrinth.com/mod/modmenu)** & **[YetAnotherConfigLib](https://modrinth.com/mod/yacl)**, or use the provided config file for servers!
+
-
-
+### 📃 Customizable Config
+Don't like the default settings? Go wild in the config for yourself or your players!
+
## Future Goals
- * Forge Port (probably NeoForge 1.21)
- * Custom dismounting logic
- * better config (coming soon!)
- * keybindings (next update)
+ * NeoForge Port
+ * Full config via [OtterLib](https://modrinth.com/mod/otterlib)
diff --git a/build.gradle b/build.gradle
index c23d6f0..bc9db2d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,8 +1,7 @@
plugins {
- id 'fabric-loom' version '1.10-SNAPSHOT'
+ id 'fabric-loom' version "1.10-SNAPSHOT"
id 'maven-publish'
- id 'com.modrinth.minotaur' version '2.+'
- id 'net.darkhax.curseforgegradle' version '1.1.+'
+ id "me.modmuss50.mod-publish-plugin" version "0.8.4"
id 'co.uzzu.dotenv.gradle' version '4.0.0'
}
@@ -14,6 +13,7 @@ base {
}
repositories {
+ mavenLocal()
maven { url = "https://maven.terraformersmc.com/releases/" }
maven { url = "https://maven.isxander.dev/releases" }
}
@@ -30,6 +30,8 @@ dependencies {
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
+
+ modImplementation "one.oth3r:otterlib:${project.otterlib_version}"
}
processResources {
@@ -39,6 +41,9 @@ processResources {
version : project.version,
minecraft_version : minecraft_version,
min_minecraft_version : min_minecraft_version,
+ max_minecraft_version : max_minecraft_version,
+ otterlib_version : otterlib_version,
+ otterlib_max_version : otterlib_max_version,
loader_version : loader_version
]
@@ -85,33 +90,35 @@ publishing {
}
}
-import com.modrinth.minotaur.dependencies.ModDependency
-
-modrinth {
- token = env.fetchOrNull('MODRINTH')
- projectId = 'EsYqsGV4'
- versionNumber = project.mod_version
- versionName = "v${project.mod_version} [Fabric]"
- versionType = "release"
- uploadFile = remapJar
- gameVersions = [project.minecraft_version]
- loaders = ['fabric', 'quilt']
- dependencies = [
- new ModDependency('P7dR8mSH', 'required'),
- new ModDependency('mOgUt4GM', 'optional')
- ]
+publishMods {
changelog = file('changelog.md').text
-}
+ type = STABLE
-import net.darkhax.curseforgegradle.TaskPublishCurseForge
+ file = remapJar.archiveFile
+ modLoaders.add("fabric")
+ modLoaders.add("quilt")
-tasks.register('publishCurseForge', TaskPublishCurseForge) {
- apiToken = env.fetchOrNull('CURSEFORGE')
+ version = mod_version
+ displayName = "v${mod_version} [Fabric]"
- def mainFile = upload(892424, remapJar)
- mainFile.changelog = file('changelog.md')
- mainFile.displayName = "v${project.mod_version} [Fabric]"
- mainFile.addModLoader("fabric", 'quilt')
- mainFile.releaseType = "release"
- mainFile.addEnvironment("client", "server")
+ curseforge {
+ accessToken = env.fetchOrNull('CURSEFORGE')
+ projectId = "892424"
+ projectSlug = "sit1"
+ minecraftVersions.addAll(minecraft_versions.split(",").toList())
+
+ requires("fabric-api", "otterlib")
+
+ announcementTitle = "Download from CurseForge"
+ }
+
+ modrinth {
+ accessToken = env.fetchOrNull('MODRINTH')
+ projectId = "EsYqsGV4"
+ minecraftVersions.addAll(minecraft_versions.split(",").toList())
+
+ requires("fabric-api", "otterlib")
+
+ announcementTitle = "Download from Modrinth"
+ }
}
\ No newline at end of file
diff --git a/changelog.md b/changelog.md
index 05b85df..cb30a6d 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,2 +1,18 @@
-# v1.2.3
-* fixed not being able to sit when the Y level was below 0
\ No newline at end of file
+# v1.2.4.3
+* added a max OtterLib version as the beta will have breaking changes between major versions
+
+# v1.2.4.2
+* fixed language file not loading (reverted uppercase locales)
+* fixed block checking having a hardcoded player reach - now uses player reach (1.20.6+)
+* fixed block and item tag check logic for cases with only not(!) tags
+
+# v1.2.4.1
+* removed unused assets
+* enabled file logging for easier debugging
+
+# v1.2.4.0
+Small changelog but big update!
+\
+Switching to OtterLib will allow for a simplified main mod and lead to more unified mod development across my projects! Download OtterLib today: [Link](https://modrinth.com/mod/otterlib)
+* make sitting via hand execute the `/sit` command, to allow for universal sitting permission control
+* switch to using OtterLib for file management, config screen management, and more to come
\ No newline at end of file
diff --git a/crowdin.yml b/crowdin.yml
new file mode 100644
index 0000000..bb81024
--- /dev/null
+++ b/crowdin.yml
@@ -0,0 +1,12 @@
+"project_id_env": "CROWDIN_PROJECT_ID"
+"api_token_env": "CROWDIN_PERSONAL_TOKEN"
+"base_path": "."
+"base_url": "https://api.crowdin.com"
+"preserve_hierarchy": true
+
+files: [
+ {
+ "source": "src/main/resources/assets/sit-oth3r/lang/en_us.json",
+ "translation": "src/main/resources/assets/sit-oth3r/lang/%locale_with_underscore%.json",
+ }
+]
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 57b8e78..19808a0 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -4,16 +4,21 @@ org.gradle.parallel=true
# Fabric Properties
# check these on https://fabricmc.net/develop
-min_minecraft_version=1.20.4
-minecraft_version=1.20.4
-yarn_mappings=1.20.4+build.3
-loader_version=0.15.11
+min_minecraft_version=1.21.6
+max_minecraft_version=1.21.6
+minecraft_versions=1.21.6
+
+minecraft_version=1.21.6
+yarn_mappings=1.21.6+build.1
+loader_version=0.16.14
# Mod Properties
-mod_version=1.2.3+1.20.4
+mod_version=1.2.4.3+1.21.6
maven_group=one.oth3r
file_name=sit!
# Dependencies
-fabric_version=0.97.1+1.20.4
-modmenu_version=9.0.0
+fabric_version=0.127.0+1.21.6
+modmenu_version=15.0.0-beta.1
+otterlib_version=0.1.2.1+1.21.6-fabric
+otterlib_max_version=0.2.0.0+1.21.6-fabric
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..a4b76b9
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cea7a79
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/src/main/java/one/oth3r/sit/SitClient.java b/src/main/java/one/oth3r/sit/SitClient.java
index 43833dc..c39fbba 100644
--- a/src/main/java/one/oth3r/sit/SitClient.java
+++ b/src/main/java/one/oth3r/sit/SitClient.java
@@ -1,8 +1,18 @@
package one.oth3r.sit;
import net.fabricmc.api.ClientModInitializer;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.util.Identifier;
+import one.oth3r.otterlib.client.screen.ConfigScreen;
+import one.oth3r.otterlib.client.screen.utl.CustomImage;
+import one.oth3r.otterlib.client.screen.utl.SimpleButton;
+import one.oth3r.sit.file.FileData;
import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Events;
+import one.oth3r.sit.utl.Utl;
+
+import java.net.URI;
+import java.util.List;
public class SitClient implements ClientModInitializer {
@@ -12,5 +22,18 @@ public class SitClient implements ClientModInitializer {
Events.registerClient();
}
-
+ public static Screen getConfigScreen(Screen parent) {
+ return new ConfigScreen(parent, Utl.lang("sit!.screen.config"),
+ new CustomImage(Identifier.of(Data.MOD_ID, "textures/gui/banner.png"),128, 72),
+ List.of(
+ SimpleButton.Templates.fileEditor(Utl.lang("config.server"), FileData.getServerConfig(), new CustomImage(Identifier.of(Data.MOD_ID, "server_button"),246,26)).build(),
+ SimpleButton.Templates.fileEditor(Utl.lang("config.sitting"), FileData.getSittingConfig(), new CustomImage(Identifier.of(Data.MOD_ID, "sitting_button"), 246, 26)).build()
+ ),
+ List.of(
+ SimpleButton.Templates.warning(Utl.lang("sit!.gui.button.issues")).openLink("https://github.com/Oth3r/Sit/issues").build(),
+ new SimpleButton.Builder(Utl.lang("sit!.gui.button.website")).openLink("https://modrinth.com/mod/sit!").build(),
+ SimpleButton.Templates.done(Utl.lang("gui.done")).build(),
+ SimpleButton.Templates.donate(Utl.lang("sit!.gui.button.donate")).openLink(URI.create("https://ko-fi.com/oth3r")).build()
+ ));
+ }
}
diff --git a/src/main/java/one/oth3r/sit/command/SitCommand.java b/src/main/java/one/oth3r/sit/command/SitCommand.java
index 0c80ed4..7abd2f3 100644
--- a/src/main/java/one/oth3r/sit/command/SitCommand.java
+++ b/src/main/java/one/oth3r/sit/command/SitCommand.java
@@ -14,6 +14,7 @@ import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Logic;
import one.oth3r.sit.utl.Utl;
+import java.awt.*;
import java.util.concurrent.CompletableFuture;
public class SitCommand {
@@ -49,7 +50,7 @@ public class SitCommand {
if (player == null) {
if (args[0].equalsIgnoreCase("reload")) {
Logic.reload();
- Data.LOGGER.info(Utl.lang("sit!.chat.reloaded").getString());
+ Data.LOGGER.info(Utl.lang("sit!.chat.reloaded").toString());
}
return 1;
}
@@ -75,7 +76,7 @@ public class SitCommand {
if (args[0].equalsIgnoreCase("reload")) {
Logic.reload();
- player.sendMessage(Utl.messageTag().append(Utl.lang("sit!.chat.reloaded").formatted(Formatting.GREEN)));
+ player.sendMessage(Utl.messageTag().append(Utl.lang("sit!.chat.reloaded").color(Color.GREEN)).b());
}
if (args[0].equalsIgnoreCase("purgeChairEntities")) Utl.Entity.purge(player,true);
diff --git a/src/main/java/one/oth3r/sit/file/CustomBlock.java b/src/main/java/one/oth3r/sit/file/CustomBlock.java
index 8f8bf68..4940f70 100644
--- a/src/main/java/one/oth3r/sit/file/CustomBlock.java
+++ b/src/main/java/one/oth3r/sit/file/CustomBlock.java
@@ -9,6 +9,7 @@ import net.minecraft.util.Identifier;
import one.oth3r.sit.utl.Utl;
import java.util.ArrayList;
+import java.util.Objects;
public class CustomBlock {
@@ -90,18 +91,38 @@ public class CustomBlock {
}
// a boolean to check if one of the blocks are in a filtered tag
- boolean tagCheck = false;
+ // & a switch for if there is only not(!) tags
+ boolean tagCheck = false, hasPositiveTags = false;
- // for all the entered tags
for (String tag : blockTags) {
// substring to remove # and if needed, !
- // if there is a math for the NOT(!) tag, return false
- if (tag.startsWith("!") && blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), new Identifier(tag.substring(2))))) return false;
- // if there is a match, return true
- if (blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse(tag.substring(1))))) tagCheck = true;
+ if (tag.startsWith("!")) {
+ // if there is a match for the NOT(!) tag, return false
+ Identifier id = Identifier.tryParse(tag.substring(2));
+ if (id != null && blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), id))) return false;
+ } else {
+ // flip the hasPositiveTags boolean
+ hasPositiveTags = true;
+ // if there is a match, return true
+ Identifier id = Identifier.tryParse(tag.substring(1));
+ if (id != null && blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), id))) tagCheck = true;
+ }
}
- // not returning true in the loop because there might be a (!) not tag that the block might fall into, after the block was already in another tag
- return tagCheck;
+ // if there were any required tags, return whether we matched one
+ // if there were only not(!) tags, and we didn't violate any, return true
+ return hasPositiveTags? tagCheck : true;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) return false;
+ CustomBlock that = (CustomBlock) o;
+ return Objects.equals(blockIds, that.blockIds) && Objects.equals(blockTags, that.blockTags) && Objects.equals(blockStates, that.blockStates);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(blockIds, blockTags, blockStates);
}
}
diff --git a/src/main/java/one/oth3r/sit/file/CustomFile.java b/src/main/java/one/oth3r/sit/file/CustomFile.java
deleted file mode 100644
index eab2d74..0000000
--- a/src/main/java/one/oth3r/sit/file/CustomFile.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package one.oth3r.sit.file;
-
-import net.fabricmc.loader.api.FabricLoader;
-import one.oth3r.sit.utl.Data;
-import one.oth3r.sit.utl.Utl;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-
-public interface CustomFile > {
-
- void reset();
-
- /**
- * saves the current instance to file
- */
- default void save() {
- if (!getFile().exists()) {
- Data.LOGGER.info(String.format("Creating new `%s`", getFile().getName()));
- }
- try (BufferedWriter writer = Files.newBufferedWriter(getFile().toPath(), StandardCharsets.UTF_8)) {
- writer.write(Utl.getGson().toJson(this));
- } catch (Exception e) {
- Data.LOGGER.error(String.format("ERROR SAVING '%s`: %s", getFile().getName(), e.getMessage()));
- }
- }
-
- /**
- * loads the file to the current instance using updateFromReader()
- */
- default void load() {
- File file = getFile();
- if (!file.exists()) fileNotExist();
- // try reading the file
- try (BufferedReader reader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
- updateFromReader(reader);
- } catch (Exception e) {
- Data.LOGGER.error(String.format("ERROR LOADING '%s`: %s", file.getName(),e.getMessage()));
- }
- }
-
- default void updateFromReader(BufferedReader reader) {
- // try to read the json
- T file;
- try {
- file = Utl.getGson().fromJson(reader, getFileClass());
- } catch (Exception e) {
- throw new NullPointerException();
- }
- // throw null if the fileData is null or version is null
- if (file == null) throw new NullPointerException();
-
- // update the instance
- file.update();
- // load the file to the current object
- loadFileData(file);
- }
-
- @NotNull
- Class getFileClass();
-
- /**
- * loads the data from the file object into the current object
- * @param newFile the file to take the properties from
- */
- void loadFileData(T newFile);
-
- /**
- * updates the file based on the version number of the current instance
- */
- void update();
-
- /**
- * logic for the file not existing when loading, defaults to saving
- */
- default void fileNotExist() {
- // try to make the config directory
- try {
- Files.createDirectories(Paths.get(getDirectory()));
- } catch (Exception e) {
- Data.LOGGER.error("Failed to create config directory. Canceling all config loading...");
- return;
- }
- save();
- }
-
- String getFileName();
-
- default String getDirectory() {
- return FabricLoader.getInstance().getConfigDir().toFile()+"/";
- }
-
- default File getFile() {
- return new File(getDirectory()+getFileName());
- }
-}
diff --git a/src/main/java/one/oth3r/sit/file/CustomItem.java b/src/main/java/one/oth3r/sit/file/CustomItem.java
index 05515f6..4e4680d 100644
--- a/src/main/java/one/oth3r/sit/file/CustomItem.java
+++ b/src/main/java/one/oth3r/sit/file/CustomItem.java
@@ -7,6 +7,7 @@ import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier;
import java.util.ArrayList;
+import java.util.Objects;
public class CustomItem {
@SerializedName("item-ids")
@@ -21,6 +22,11 @@ public class CustomItem {
this.itemTags = itemTags;
}
+ public CustomItem(CustomItem customItem) {
+ this.itemIDs = new ArrayList<>(customItem.itemIDs);
+ this.itemTags = new ArrayList<>(customItem.itemTags);
+ }
+
public ArrayList getItemIDs() {
return itemIDs;
}
@@ -45,21 +51,38 @@ public class CustomItem {
}
// a boolean to check if one of the items are in a filtered tag
- boolean tagCheck = false;
+ // & a switch for if there is only not(!) tags
+ boolean tagCheck = false, hasPositiveTags = false;
- // check the custom item tags
for (String tag : itemTags) {
// substring to remove # and if needed, "!"
- // if a NOT tag
if (tag.startsWith("!")) {
// if there is a math for the NOT(!) tag, return false
- if (itemStack.isIn(TagKey.of(Registries.ITEM.getKey(), new Identifier(tag.substring(2))))) return false;
+ Identifier id = Identifier.tryParse(tag.substring(2));
+ if (id != null && itemStack.isIn(TagKey.of(Registries.ITEM.getKey(), id))) return false;
+ } else {
+ // flip the hasPositiveTags boolean
+ hasPositiveTags = true;
+ // else (normal tag), if there is a match, set tagCheck to true
+ Identifier id = Identifier.tryParse(tag.substring(1));
+ if (id != null && itemStack.isIn(TagKey.of(Registries.ITEM.getKey(), id))) tagCheck = true;
}
- // else (normal tag), if there is a match, set tagCheck to true
- else if (itemStack.isIn(TagKey.of(Registries.ITEM.getKey(), new Identifier(tag.substring(1))))) tagCheck = true;
}
- // not returning true in the loop because there might be a (!) not tag that the item might fall into, after the item was already in another tag
- return tagCheck;
+ // if there were any required tags, return whether we matched one
+ // if there were only not(!) tags, and we didn't violate any, return true
+ return hasPositiveTags? tagCheck : true;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) return false;
+ CustomItem that = (CustomItem) o;
+ return Objects.equals(itemIDs, that.itemIDs) && Objects.equals(itemTags, that.itemTags);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(itemIDs, itemTags);
}
}
diff --git a/src/main/java/one/oth3r/sit/file/HandSetting.java b/src/main/java/one/oth3r/sit/file/HandSetting.java
index b0c5527..86c9214 100644
--- a/src/main/java/one/oth3r/sit/file/HandSetting.java
+++ b/src/main/java/one/oth3r/sit/file/HandSetting.java
@@ -3,6 +3,7 @@ package one.oth3r.sit.file;
import com.google.gson.annotations.SerializedName;
import java.util.Arrays;
+import java.util.Objects;
import java.util.stream.Collectors;
public class HandSetting {
@@ -21,6 +22,11 @@ public class HandSetting {
this.filter = filter;
}
+ public HandSetting(HandSetting handSetting) {
+ this.sittingRequirement = handSetting.sittingRequirement;
+ this.filter = new Filter(handSetting.filter);
+ }
+
public SittingRequirement getSittingRequirement() {
return sittingRequirement;
}
@@ -52,6 +58,12 @@ public class HandSetting {
this.customItems = customItems;
}
+ public Filter(Filter filter) {
+ this.invert = filter.invert;
+ this.presets = new Presets(filter.presets);
+ this.customItems = new CustomItem(filter.customItems);
+ }
+
public Boolean isInverted() {
return invert;
}
@@ -80,6 +92,12 @@ public class HandSetting {
this.usable = usable;
}
+ public Presets(Presets presets) {
+ this.block = presets.block;
+ this.food = presets.food;
+ this.usable = presets.usable;
+ }
+
public boolean isBlock() {
return block;
}
@@ -91,6 +109,42 @@ public class HandSetting {
public boolean isUsable() {
return usable;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) return false;
+ Presets presets = (Presets) o;
+ return block == presets.block && food == presets.food && usable == presets.usable;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(block, food, usable);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) return false;
+ Filter filter = (Filter) o;
+ return Objects.equals(invert, filter.invert) && Objects.equals(presets, filter.presets) && Objects.equals(customItems, filter.customItems);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(invert, presets, customItems);
}
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) return false;
+ HandSetting that = (HandSetting) o;
+ return sittingRequirement == that.sittingRequirement && Objects.equals(sittingRequirementOptions, that.sittingRequirementOptions) && Objects.equals(filter, that.filter);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(sittingRequirement, sittingRequirementOptions, filter);
+ }
}
diff --git a/src/main/java/one/oth3r/sit/file/LangReader.java b/src/main/java/one/oth3r/sit/file/LangReader.java
index bcafcb2..d9fdaff 100644
--- a/src/main/java/one/oth3r/sit/file/LangReader.java
+++ b/src/main/java/one/oth3r/sit/file/LangReader.java
@@ -4,6 +4,7 @@ import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
+import one.oth3r.otterlib.chat.CTxT;
import one.oth3r.sit.Sit;
import one.oth3r.sit.utl.Data;
@@ -20,14 +21,19 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LangReader {
+ private static final Map defaultLangMap = new HashMap<>();
private static final Map languageMap = new HashMap<>();
+
private final String translationKey;
+
private final Object[] placeholders;
+
public LangReader(String translationKey, Object... placeholders) {
this.translationKey = translationKey;
this.placeholders = placeholders;
}
- public MutableText getTxT() {
+
+ public CTxT getTxT() {
String translated = getLanguageValue(translationKey);
if (placeholders != null && placeholders.length > 0) {
//removed all double \\ and replaces with \
@@ -35,7 +41,8 @@ public class LangReader {
String regex = "%\\d*\\$?[dfs]";
Matcher anyMatch = Pattern.compile(regex).matcher(translated);
Matcher endMatch = Pattern.compile(regex+"$").matcher(translated);
- //Arraylist with all the %(#$)[dfs]
+
+ // Arraylist with all the %(#$)[dfs]
ArrayList matches = new ArrayList<>();
while (anyMatch.find()) {
String match = anyMatch.group();
@@ -51,7 +58,7 @@ public class LangReader {
}
//if there are placeholders specified, and the split is more than 1, it will replace %(dfs) with the placeholder objects
if (parts.length > 1) {
- MutableText txt = Text.empty();
+ CTxT txt = new CTxT("");
int i = 0;
for (String match : matches) {
int get = i;
@@ -62,47 +69,56 @@ public class LangReader {
}
if (parts.length != i) txt.append(parts[i]);
//convert the obj into txt
- Object obj = placeholders[get];
- if (obj instanceof Text) txt.append((Text) obj);
- else txt.append(String.valueOf(obj));
+ txt.append(getTxTFromObj(placeholders[get]));
i++;
}
if (parts.length != i) txt.append(parts[i]);
- return txt;
+ return new CTxT(txt);
}
}
- return Text.empty().append(translated);
+ return new CTxT(translated);
}
+
+ private CTxT getTxTFromObj(Object obj) {
+ if (obj instanceof CTxT) return (((CTxT) obj));
+ else if (obj instanceof Text) return new CTxT((MutableText) obj);
+ else return new CTxT(String.valueOf(obj));
+ }
+
public static LangReader of(String translationKey, Object... placeholders) {
return new LangReader(translationKey, placeholders);
}
public static void loadLanguageFile() {
- ClassLoader classLoader = Sit.class.getClassLoader();
+ Type tToken = new TypeToken