Compare commits

..

No commits in common. "85cc76a022f201786089cc69f26ab30a852968eb" and "62fd879d0d6751ea643e22d4ce60169497366520" have entirely different histories.

52 changed files with 367 additions and 292 deletions

View file

@ -3,123 +3,31 @@ name: Crowdin Download Action
permissions:
contents: write
pull-requests: write
actions: read
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:
crowdin:
runs-on: ubuntu-latest
steps:
# Checkout the BASE branch first. The PR branch will be created later.
- name: Checkout Base Branch
- name: Checkout
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)
- name: Synchronize with Crowdin
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 }}
localization_branch_name: crowdin_translations
create_pull_request: true
pull_request_title: 'Updated Crowdin translations'
pull_request_body: 'New Crowdin pull request with translations'
pull_request_base_branch_name: 'dev'
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"

View file

@ -2,7 +2,7 @@ name: Crowdin Upload Action
on:
push:
paths: [ "src/main/resources/assets/sit-oth3r/lang/en_us.json"]
paths: [ "src/main/resources/assets/sit-oth3r/lang/en_US.json"]
branches: [ dev ]
workflow_dispatch:

View file

@ -1,68 +1,46 @@
<img src="https://github.com/Oth3r/oth3r.github.io/blob/main/mod_data/Sit!/media/banner.png?raw=true" width="50%" style="margin-bottom: 10px; max-width:400px;">
# Sit!
[![github](https://img.shields.io/github/issues/oth3r/Sit?logo=github?label=Issues)](https://github.com/Oth3r/Sit/releases) [![Crowdin](https://badges.crowdin.net/oth3r-sit/localized.svg)](https://crowdin.com/project/oth3r-sit) [![discord](https://dcbadge.vercel.app/api/server/https://discord.gg/AVSTHCAUvn?style=flat)](https://www.oth3r.one/discord)
[![modrinth](https://img.shields.io/modrinth/dt/sit!?label=Modrinth&logo=modrinth)](https://modrinth.com/mod/sit!) [![curseforge](https://cf.way2muchnoise.eu/892424.svg)](https://www.curseforge.com/minecraft/mc-mods/Sit1)
### **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.
**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!
### Where to install?
**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.
**Sit!** works on the server (singleplayer included), also with support for clients that join in to use their own settings to 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!
## Help localize Sit! on [Crowdin](https://crowdin.com/project/oth3r-sit)!
![overview](https://github.com/Oth3r/Sit/blob/master/media/overview.gif?raw=true)
## Check out my other Projects!
<a href="https://modrinth.com/mod/caligo">
<img src="https://github.com/Oth3r/Caligo/blob/master/media/promo_badge.png?raw=true" alt="Caligo badge"
style="margin-right: 5px;">
</a>
<a href="https://modrinth.com/mod/directionhud">
<img src="https://github.com/Oth3r/DirectionHUD/blob/master/media/mod-badge.png?raw=true" alt="Directionhud badge"
style="margin-right: 5px;">
</a>
<a href="https://modrinth.com/mod/more-heart-types">
<img src="https://github.com/Oth3r/MoreHeartTypes/blob/master/media/Badge.png?raw=true" alt="More Heart Types badge"
style="">
</a>
[![Caligo badge](https://github.com/Oth3r/Caligo/blob/master/media/promo_badge.png?raw=true)](https://modrinth.com/mod/caligo)
[![DirectionHUD badge](https://github.com/Oth3r/DirectionHUD/blob/master/media/mod-badge.png?raw=true)](https://modrinth.com/mod/directionhud)
[![DirectionHUD Spigot badge](https://github.com/Oth3r/DirectionHUD/blob/master/media/plugin-badge.png?raw=true)](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!
<img src="https://github.com/Oth3r/oth3r.github.io/blob/main/mod_data/Sit!/media/desc/hand_restrictions.gif?raw=true" width="100%" style="margin-bottom: 10px;max-width:600px;"
alt="per player hand restriction showcase">
* 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.
![hand restrictions](https://github.com/Oth3r/Sit/blob/master/media/hand-restrictions.gif?raw=true)
<img src="https://github.com/Oth3r/oth3r.github.io/blob/main/mod_data/Sit!/media/desc/custom_blocks.gif?raw=true" width="100%" style="margin-bottom: 10px; max-width:600px;"
alt="players sitting on a vast range of blocks">
### 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!
![custom blocks](https://github.com/Oth3r/Sit/blob/master/media/custom-blocks.gif?raw=true)
<img src="https://github.com/Oth3r/oth3r.github.io/blob/main/mod_data/Sit!/media/desc/keybinds.gif?raw=true" width="100%" style="margin-bottom: 10px; max-width:600px;"
alt="setting keybinds for the sit mod, and sitting by using them">
### 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!
<img src="https://github.com/Oth3r/oth3r.github.io/blob/main/mod_data/Sit!/media/desc/config.gif?raw=true" width="100%" style="margin-bottom: 10px; max-width:600px;"
alt="the Sit! config wiki page">
![config](https://github.com/Oth3r/Sit/blob/master/media/config.gif?raw=true)
![custom blocks config](https://github.com/Oth3r/Sit/blob/master/media/custom-blocks-config.png?raw=true)
## Future Goals
* NeoForge Port
* Full config via [OtterLib](https://modrinth.com/mod/otterlib)
* Forge Port (probably NeoForge 1.21)
* Custom dismounting logic
* better config (coming soon!)
* keybindings (next update)

View file

@ -43,7 +43,6 @@ processResources {
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
]

View file

@ -1,11 +1,3 @@
# 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

View file

@ -6,7 +6,7 @@
files: [
{
"source": "src/main/resources/assets/sit-oth3r/lang/en_us.json",
"source": "src/main/resources/assets/sit-oth3r/lang/en_US.json",
"translation": "src/main/resources/assets/sit-oth3r/lang/%locale_with_underscore%.json",
}
]

View file

@ -13,7 +13,7 @@ yarn_mappings=1.21.5+build.1
loader_version=0.16.14
# Mod Properties
mod_version=1.2.4.3+1.21.5
mod_version=1.2.4.1+1.21.5
maven_group=one.oth3r
file_name=sit!
@ -21,4 +21,3 @@ file_name=sit!
fabric_version=0.124.0+1.21.5
modmenu_version=14.0.0-rc.2
otterlib_version=0.1.2.1+1.21.5-fabric
otterlib_max_version=0.2.0.0+1.21.5-fabric

View file

@ -7,9 +7,9 @@ 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.Chat;
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;
@ -23,17 +23,17 @@ public class SitClient implements ClientModInitializer {
}
public static Screen getConfigScreen(Screen parent) {
return new ConfigScreen(parent, Chat.lang("sit!.screen.config"),
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(Chat.lang("config.server"), FileData.getServerConfig(), new CustomImage(Identifier.of(Data.MOD_ID, "server_button"),246,26)).build(),
SimpleButton.Templates.fileEditor(Chat.lang("config.sitting"), FileData.getSittingConfig(), new CustomImage(Identifier.of(Data.MOD_ID, "sitting_button"), 246, 26)).build()
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(Chat.lang("sit!.gui.button.issues")).openLink("https://github.com/Oth3r/Sit/issues").build(),
new SimpleButton.Builder(Chat.lang("sit!.gui.button.website")).openLink("https://modrinth.com/mod/sit!").build(),
SimpleButton.Templates.done(Chat.lang("gui.done")).build(),
SimpleButton.Templates.donate(Chat.lang("sit!.gui.button.donate")).openLink(URI.create("https://ko-fi.com/oth3r")).build()
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()
));
}
}

View file

@ -8,8 +8,8 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.BlockPos;
import one.oth3r.sit.utl.Chat;
import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Logic;
import one.oth3r.sit.utl.Utl;
@ -50,7 +50,7 @@ public class SitCommand {
if (player == null) {
if (args[0].equalsIgnoreCase("reload")) {
Logic.reload();
Data.LOGGER.info(Chat.lang("sit!.chat.reloaded").toString());
Data.LOGGER.info(Utl.lang("sit!.chat.reloaded").toString());
}
return 1;
}
@ -76,7 +76,7 @@ public class SitCommand {
if (args[0].equalsIgnoreCase("reload")) {
Logic.reload();
player.sendMessage(Chat.tag().append(Chat.lang("sit!.chat.reloaded").color(Color.GREEN)).b());
player.sendMessage(Utl.messageTag().append(Utl.lang("sit!.chat.reloaded").color(Color.GREEN)).b());
}
if (args[0].equalsIgnoreCase("purgeChairEntities")) Utl.Entity.purge(player,true);

View file

@ -91,27 +91,19 @@ public class CustomBlock {
}
// a boolean to check if one of the blocks are in a filtered tag
// & a switch for if there is only not(!) tags
boolean tagCheck = false, hasPositiveTags = false;
boolean tagCheck = false;
// for all the entered tags
for (String tag : blockTags) {
// substring to remove # and if needed, !
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 math for the NOT(!) tag, return false
if (tag.startsWith("!") && blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.of(tag.substring(2))))) return false;
// 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;
}
if (blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse(tag.substring(1))))) tagCheck = true;
}
// 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;
// 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;
}
@Override

View file

@ -51,27 +51,22 @@ public class CustomItem {
}
// a boolean to check if one of the items are in a filtered tag
// & a switch for if there is only not(!) tags
boolean tagCheck = false, hasPositiveTags = false;
boolean tagCheck = 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
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;
if (itemStack.isIn(TagKey.of(Registries.ITEM.getKey(), Identifier.of(tag.substring(2))))) return false;
}
// else (normal tag), if there is a match, set tagCheck to true
else if (itemStack.isIn(TagKey.of(Registries.ITEM.getKey(), Identifier.of(tag.substring(1))))) tagCheck = true;
}
// 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;
// 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;
}
@Override

View file

@ -1,15 +1,9 @@
package one.oth3r.sit.file;
import net.minecraft.server.network.ServerPlayerEntity;
import one.oth3r.otterlib.file.LanguageReader;
import one.oth3r.sit.Sit;
import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Utl;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -62,21 +56,11 @@ public class FileData {
return playerSettings.getOrDefault(player, sittingConfig);
}
/// the language / text system for the mod
private static final LanguageReader langReader = new LanguageReader(
getLangPath(),Path.of(Data.CONFIG_DIR),"en_us","en_us");
public static LanguageReader getLangReader() {
return langReader;
}
/**
* loads all config files to memory
*/
public static void loadFiles() {
getServerConfig().load();
// load the language reader
langReader.updateLanguage(getServerConfig().getLang());
getSittingConfig().load();
// if loading file and is on supported server on client, send the new settings over
@ -93,20 +77,6 @@ public class FileData {
getServerConfig().save();
}
private static Path getLangPath() {
ClassLoader classLoader = Sit.class.getClassLoader();
URL resource = classLoader.getResource("assets/sit-oth3r/lang/");
if (resource == null) {
throw new RuntimeException("Language file not found.");
}
try {
return Paths.get(resource.toURI());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
public static class Defaults {
public static final ArrayList<SittingBlock> SITTING_BLOCKS = new ArrayList<>(Arrays.asList(
new SittingBlock(new ArrayList<>(),new ArrayList<>(Arrays.asList("#minecraft:campfires")), new ArrayList<>(Arrays.asList("lit=false")),.437),

View file

@ -0,0 +1,124 @@
package one.oth3r.sit.file;
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;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LangReader {
private static final Map<String, String> defaultLangMap = new HashMap<>();
private static final Map<String, String> languageMap = new HashMap<>();
private final String translationKey;
private final Object[] placeholders;
public LangReader(String translationKey, Object... placeholders) {
this.translationKey = translationKey;
this.placeholders = placeholders;
}
public CTxT getTxT() {
String translated = getLanguageValue(translationKey);
if (placeholders != null && placeholders.length > 0) {
//removed all double \\ and replaces with \
translated = translated.replaceAll("\\\\\\\\", "\\\\");
String regex = "%\\d*\\$?[dfs]";
Matcher anyMatch = Pattern.compile(regex).matcher(translated);
Matcher endMatch = Pattern.compile(regex+"$").matcher(translated);
// Arraylist with all the %(#$)[dfs]
ArrayList<String> matches = new ArrayList<>();
while (anyMatch.find()) {
String match = anyMatch.group();
matches.add(match);
}
//SPLITS the text at each regex and remove the regex
String[] parts = translated.split(regex);
//if the last element of the array ends with regex, remove it and add an empty string to the end of the array
if (endMatch.find()) {
String[] newParts = Arrays.copyOf(parts, parts.length + 1);
newParts[parts.length] = "";
parts = newParts;
}
//if there are placeholders specified, and the split is more than 1, it will replace %(dfs) with the placeholder objects
if (parts.length > 1) {
CTxT txt = new CTxT("");
int i = 0;
for (String match : matches) {
int get = i;
//if the match is numbered, change GET to the number it wants
if (match.contains("$")) {
match = match.substring(1,match.indexOf('$'));
get = Integer.parseInt(match)-1;
}
if (parts.length != i) txt.append(parts[i]);
//convert the obj into txt
txt.append(getTxTFromObj(placeholders[get]));
i++;
}
if (parts.length != i) txt.append(parts[i]);
return new CTxT(txt);
}
}
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() {
Type tToken = new TypeToken<Map<String, String>>(){}.getType();
try {
// load the config language
Reader selectionReader = new InputStreamReader(getInputStream(false), StandardCharsets.UTF_8);
languageMap.putAll(new Gson().fromJson(selectionReader, tToken));
// load the default language as well (fallback)
Reader defaultReader = new InputStreamReader(getInputStream(true), StandardCharsets.UTF_8);
defaultLangMap.putAll(new Gson().fromJson(defaultReader, tToken));
} catch (Exception e) {
Data.LOGGER.info("ERROR WITH LANGUAGE FILE - PLEASE REPORT WITH THE ERROR LOG");
Data.LOGGER.info(e.getMessage());
}
}
private static InputStream getInputStream(boolean english) {
ClassLoader classLoader = Sit.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("assets/sit-oth3r/lang/"+FileData.getServerConfig().getLang()+".json");
// make null if english
if (english) inputStream = null;
// if it cant read (null), try again, but with the english file
if (inputStream == null) inputStream = classLoader.getResourceAsStream("assets/sit-oth3r/lang/"+new ServerConfig().getLang()+".json");
// if null after that, throw an exception
if (inputStream == null) throw new IllegalArgumentException("CANT LOAD THE LANGUAGE FILE. SIT! WILL BREAK.");
return inputStream;
}
public static String getLanguageValue(String key) {
return languageMap.getOrDefault(key, defaultLangMap.getOrDefault(key, key));
}
}

View file

@ -1,14 +1,15 @@
package one.oth3r.sit.file;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import net.minecraft.util.Hand;
import one.oth3r.otterlib.base.Num;
import one.oth3r.otterlib.file.CustomFile;
import one.oth3r.otterlib.file.FileSettings;
import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Utl;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@ -26,12 +27,12 @@ import java.util.stream.Collectors;
public class ServerConfig implements CustomFile<ServerConfig> {
@SerializedName("version")
private Double version = 2.3;
private Double version = 2.2;
@SerializedName("lang")
private String lang = "en_us";
private String lang = "en_US";
@SerializedName("lang-options")
private final String langOptions = "en_us, it_it, pt_br, tr_tr, zh_tw, zh_ch, de_de";
private final String langOptions = "en_US, it_IT, pt_BR, tr_TR, zh_TW, zh_CH, de_DE";
@SerializedName("keep-active")
private Boolean keepActive = true;
@ -263,18 +264,18 @@ public class ServerConfig implements CustomFile<ServerConfig> {
this.interactionBlocks = newFile.interactionBlocks.stream().map(CustomBlock::new).collect(Collectors.toCollection(ArrayList::new));
}
/**
* updates the file based on the version number of the current instance
*
* @param json
*/
@Override
public void updateInstance() {
public void update(JsonElement json) {
/// update to 2.1, just a new list, nothing to change
/// update to 2.2, new settings, no changes
if (version >= 2.0 && version <= 2.1) {
version = 2.2;
}
if (version == 2.2) {
// make sure that the lang is all lowercase
version = 2.3;
this.lang = this.lang.substring(0,3)+this.lang.substring(3).toLowerCase();
}
}
@Override
@ -335,7 +336,7 @@ public class ServerConfig implements CustomFile<ServerConfig> {
loadVersion(properties,Double.parseDouble(ver));
} catch (Exception e) {
Data.LOGGER.error("Error loading legacy config file: %s", e.getMessage());
Data.LOGGER.error("Error loading legacy config file: {}", e.getMessage());
}
// delete the old file
@ -370,7 +371,7 @@ public class ServerConfig implements CustomFile<ServerConfig> {
// skip if not the right size
if (split.length < 3 || split.length > 4) continue;
// if the other entries aren't correct, skip
if (!Num.isNum(split[2])) continue;
if (!Utl.Num.isNum(split[2])) continue;
// make the block states list if possible
ArrayList<String> blockstates = new ArrayList<>();
@ -497,7 +498,7 @@ public class ServerConfig implements CustomFile<ServerConfig> {
serverConfig.save();
sittingConfig.save();
} catch (Exception e) {
Data.LOGGER.error("Error loading legacy config: %s", e.getMessage());
Data.LOGGER.error("Error loading legacy config: {}", e.getMessage());
}
}
}

View file

@ -101,7 +101,7 @@ public class SittingConfig implements CustomFile<SittingConfig> {
}
@Override
public void updateInstance() {
public void update(JsonElement jsonElement) {
}

View file

@ -5,9 +5,10 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ReloadCommand;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import one.oth3r.sit.utl.Chat;
import net.minecraft.util.Formatting;
import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Logic;
import one.oth3r.sit.utl.Utl;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -28,7 +29,7 @@ public class ReloadCommandMixin {
// send a reloaded message to all players with permissions
for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) {
if (player.isCreativeLevelTwoOp()) {
player.sendMessage(Chat.tag().append(Chat.lang("sit!.chat.reloaded").color(Color.GREEN)).b());
player.sendMessage(Utl.messageTag().append(Utl.lang("sit!.chat.reloaded").color(Color.GREEN)).b());
}
}
}

View file

@ -1,16 +0,0 @@
package one.oth3r.sit.utl;
import one.oth3r.otterlib.chat.CTxT;
import one.oth3r.sit.file.FileData;
import java.awt.*;
public class Chat {
public static CTxT tag() {
return new CTxT("Sit!").btn(true).color(Color.decode("#c400ff")).append(" ");
}
public static CTxT lang(String key, Object... args) {
return FileData.getLangReader().dynamicTranslatable(key, args);
}
}

View file

@ -4,13 +4,14 @@ import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import one.oth3r.otterlib.base.OtterLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
public class Data {
public static final String MOD_ID = "sit-oth3r";
public static final OtterLogger LOGGER = new OtterLogger(MOD_ID);
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
public static final String CONFIG_DIR = FabricLoader.getInstance().getConfigDir().toFile()+"/sit!/";

View file

@ -23,6 +23,7 @@ import net.minecraft.util.ActionResult;
import one.oth3r.sit.SitClient;
import one.oth3r.sit.command.SitCommand;
import one.oth3r.sit.file.FileData;
import one.oth3r.sit.file.LangReader;
import one.oth3r.sit.file.SittingConfig;
import one.oth3r.sit.packet.SitPayloads;
import org.lwjgl.glfw.GLFW;
@ -77,7 +78,7 @@ public class Events {
player.networkHandler.sendCommand("sit");
} else {
// unsupported server message if not in a Sit! server
player.sendMessage(Chat.lang("sit!.chat.unsupported")
player.sendMessage(Utl.lang("sit!.chat.unsupported")
.color(Color.RED).b(), true);
}
}
@ -103,7 +104,7 @@ public class Events {
ServerPlayNetworking.send(context.player(),new SitPayloads.ResponsePayload(SitPayloads.ResponsePayload.VERSION));
// log the receiving of the packet from the player
Data.LOGGER.info(Chat.lang("sit!.console.player_settings",context.player().getName().getString()).toString());
Data.LOGGER.info(Utl.lang("sit!.console.player_settings",context.player().getName().getString()).toString());
})));
}
@ -113,7 +114,7 @@ public class Events {
// only update when needed
if (!Data.isSupportedServer()) {
Data.setSupportedServer(true);
Data.LOGGER.info(Chat.lang("sit!.console.connected",payload.value()).toString());
Data.LOGGER.info(Utl.lang("sit!.console.connected",payload.value()).toString());
}
}));
}
@ -171,6 +172,7 @@ public class Events {
private static void serverLifecycle() {
ServerLifecycleEvents.SERVER_STARTED.register(s -> {
Data.setServer(s);
LangReader.loadLanguageFile();
// right click on block event
UseBlockCallback.EVENT.register((pl, world, hand, hitResult) -> {
@ -190,7 +192,7 @@ public class Events {
ParseResults<ServerCommandSource> parse = dispatcher.parse("sit", player.getCommandSource());
dispatcher.execute(parse);
} catch (CommandSyntaxException e) {
Data.LOGGER.error("Error executing sit command for player %s", player.getName().getString());
Data.LOGGER.error("Error executing sit command for player {}", player.getName().getString());
}
}

View file

@ -77,8 +77,7 @@ public class Logic {
* @return true if sitting was successful
*/
public static boolean sitLooking(ServerPlayerEntity player) {
return sit(player, Utl.getBlockPosPlayerIsLookingAt(player.getServerWorld(),player,
Utl.getPlayerReach(player)),null);
return sit(player, Utl.getBlockPosPlayerIsLookingAt(player.getServerWorld(),player,5),null);
}
/**
@ -201,6 +200,7 @@ public class Logic {
public static void reload() {
FileData.loadFiles();
FileData.saveFiles();
LangReader.loadLanguageFile();
}
/**
@ -227,11 +227,11 @@ public class Logic {
Formatting messageColor = config.getEnabled()?Formatting.GREEN:Formatting.RED;
// send the player the actionbar message
return Chat.lang("sit!.chat.toggle_sit",
Chat.lang(messageKey).color(config.getEnabled()? Color.GREEN : Color.RED)).b();
return Utl.lang("sit!.chat.toggle_sit",
Utl.lang(messageKey).color(config.getEnabled()? Color.GREEN : Color.RED)).b();
} else {
// unsupported server message if not in a Sit! server
return Chat.lang("sit!.chat.unsupported")
return Utl.lang("sit!.chat.unsupported")
.color(Color.RED).b();
}
}

View file

@ -10,7 +10,6 @@ import net.minecraft.block.*;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.block.enums.SlabType;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
@ -60,6 +59,46 @@ public class Utl {
return Data.getSitEntities().values().stream().noneMatch(entity -> entity.getBlockPos().equals(pos));
}
public static class Num {
public static boolean isInt(String string) {
try {
Integer.parseInt(string);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
public static Integer toInt(String s) {
// return an int no matter what
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
try {
return (int) Double.parseDouble(s);
} catch (NumberFormatException e2) {
return 0;
}
}
}
public static boolean isNum(String s) {
// checks if int or a double
try {
Integer.parseInt(s);
return true;
} catch (NumberFormatException e1) {
try {
Double.parseDouble(s);
return true;
} catch (NumberFormatException e2) {
return false;
}
}
}
}
public static final double HALF_BLOCK = 0.5;
public static final double CARPET = 0.062;
@ -281,14 +320,58 @@ public class Utl {
// send a message if needed
if (message) {
player.sendMessage(Chat.tag()
.append(Chat.lang("sit!.chat.purged",
Chat.lang("sit!.chat.purged.total",count).color(Color.gray).b()
).color(Color.GREEN)).b());
player.sendMessage(messageTag()
.append(lang("sit!.chat.purged",lang("sit!.chat.purged.total",count).color(Color.gray).b()).color(Color.GREEN)).b());
}
}
}
public static CTxT messageTag() {
return new CTxT("Sit!").btn(true).color(Color.decode("#c400ff")).append(" ");
}
/**
* gets a MutableText using the language key, if on server, using the custom lang reader
*/
public static CTxT lang(String key, Object... args) {
if (Data.isClient()) {
// we have to first convert all the CTxT's to the built version because minecraft lang reader doesn't know how to process it
// make a array with the same size of the args
Object[] fixedArgs = new Object[args.length];
// for every arg, build & add if CTxT or just add if not
for (var i = 0; i < args.length; i++) {
if (args[i] instanceof CTxT) fixedArgs[i] = ((CTxT) args[i]).b();
else fixedArgs[i] = args[i];
}
// return the translated text
return new CTxT(Text.translatable(key,fixedArgs));
}
else return LangReader.of(key, args).getTxT();
}
public static class Enum {
public static <T extends java.lang.Enum<T>> T get(Object enumString, Class<T> enumType) {
return get(enumString,enumType,enumType.getEnumConstants()[0]);
}
/**
* gets an enum from a string without returning null
* @param enumString the string of the enum
* @param enumType the class of enums
* @param defaultEnum the enum to return if a match isn't found
* @return an enum, if there isn't a match, it returns the first enum
*/
public static <T extends java.lang.Enum<T>> T get(Object enumString, Class<T> enumType, T defaultEnum) {
T[] values = enumType.getEnumConstants();
for (T all : values) {
// check if there is a match for any of the enum names
if (enumString.toString().equals(all.name())) return all;
}
// if there's no match return the first entry
return defaultEnum;
}
}
/**
* sends the settings packets to the server, if client & in game
*/
@ -399,13 +482,4 @@ public class Utl {
return new BlockPos(player.getBlockPos());
}
public static double getPlayerReach(PlayerEntity player) {
// use the BLOCK_INTERACTION_RANGE attribute if available
if (player.getAttributeInstance(EntityAttributes.BLOCK_INTERACTION_RANGE) != null) {
return player.getAttributeValue(EntityAttributes.BLOCK_INTERACTION_RANGE);
}
// fallback to 5
return 5;
}
}

View file

@ -68,8 +68,13 @@
"key.sit!.sit": "Sitzen",
"key.sit!.config": "Konfiguration öffnen",
"sit!.screen.config": "Sit! Konfiguration",
"sit!.gui.button.file": "Datei öffnen",
"sit!.gui.button.folder": "Ordner öffnen",
"sit!.gui.button.reset": "Zurücksetzen",
"sit!.gui.button.issues": "Probleme",
"sit!.gui.button.donate": "Spenden",
"sit!.gui.button.revert": "Änderungen rückgängig machen",
"sit!.gui.button.save": "Speichern und schließen",
"sit!.gui.button.website": "Website",
"sit!.console.connected": "Verbunden mit Sit! Server: %s",
"sit!.console.player_settings": "Benutzerdefinierte Sitzungseinstellungen von %s erhalten!",

View file

@ -68,8 +68,13 @@
"key.sit!.sit": "Sentarse",
"key.sit!.config": "Abrir configuración",
"sit!.screen.config": "Configuracion de Sit!",
"sit!.gui.button.file": "Abrir Archivo",
"sit!.gui.button.folder": "Abrir Carpeta",
"sit!.gui.button.reset": "Reiniciar",
"sit!.gui.button.issues": "Problemas",
"sit!.gui.button.donate": "Donar",
"sit!.gui.button.revert": "Revertir cambios",
"sit!.gui.button.save": "Guardar y salir",
"sit!.gui.button.website": "Sitio web ",
"sit!.console.player_settings": "¡Se recibió configuraciones personalizadas dé %s!",
"modmenu.descriptionTranslation.sit-oth3r": "¡Añade la capacidad de sentarse a Minecraft! Configuración extensa para restricciones de mano y bloques sentables.\n ¡Los jugadores pueden tener su propia configuración cuando usan Sit! del lado del cliente en un servidor!"

View file

@ -68,8 +68,13 @@
"key.sit!.sit": "S'asseoir",
"key.sit!.config": "Ouvrir la configuration",
"sit!.screen.config": "Sit! Config",
"sit!.gui.button.file": "Ouvrir le fichier",
"sit!.gui.button.folder": "Ouvrir le dossier",
"sit!.gui.button.reset": "Restaurer",
"sit!.gui.button.issues": "Problèmes",
"sit!.gui.button.donate": "Faire un don",
"sit!.gui.button.revert": "Annuler les modifications",
"sit!.gui.button.save": "Enregistrer et fermer",
"sit!.gui.button.website": "Site web",
"sit!.console.connected": "Connecté au serveur Sit! : %s",
"sit!.console.player_settings": "Reçu les paramètres de séance personnalisés de %s!",

View file

@ -68,8 +68,13 @@
"key.sit!.sit": "Siediti",
"key.sit!.config": "Apri Impostazioni",
"sit!.screen.config": "Impostazioni Sit!",
"sit!.gui.button.file": "Apri File",
"sit!.gui.button.folder": "Apri Cartella",
"sit!.gui.button.reset": "Resetta",
"sit!.gui.button.issues": "Problemi",
"sit!.gui.button.donate": "Dona",
"sit!.gui.button.revert": "Annulla i Cambiamenti",
"sit!.gui.button.save": "Salva ed Esci",
"sit!.gui.button.website": "Sito Web",
"sit!.console.connected": "Connesso al server Sit!: %s",
"sit!.console.player_settings": "Ricevute impostazioni custom da %s!",

View file

@ -44,7 +44,12 @@
"key.sit!.toggle": "Przełącz możliwość siadania",
"key.sit!.config": "Otwórz ustawienia",
"sit!.screen.config": "Konfiguracja Sit!",
"sit!.gui.button.file": "Otwórz plik",
"sit!.gui.button.folder": "Otwórz folder",
"sit!.gui.button.reset": "Reset",
"sit!.gui.button.donate": "Wesprzyj",
"sit!.gui.button.revert": "Cofnij zmiany",
"sit!.gui.button.save": "Zapisz i zamknij",
"sit!.gui.button.website": "Strona",
"sit!.console.connected": "Połączono z serwerem wspierającym Sit!: %s",
"sit!.console.player_settings": "Otrzymano niestandardowe ustawienia z: %s!",

View file

@ -68,8 +68,13 @@
"key.sit!.sit": "Sentar",
"key.sit!.config": "Abrir Configuração",
"sit!.screen.config": "Configuração do Sit!",
"sit!.gui.button.file": "Abrir Arquivo",
"sit!.gui.button.folder": "Abrir Pasta",
"sit!.gui.button.reset": "Reiniciar",
"sit!.gui.button.issues": "Problemas",
"sit!.gui.button.donate": "Doar",
"sit!.gui.button.revert": "Reverter Alterações",
"sit!.gui.button.save": "Salvar e Fechar",
"sit!.gui.button.website": "Website",
"sit!.console.connected": "Conectado ao servidor Sit!: %s",
"sit!.console.player_settings": "Recebidas configurações de sentar personalizadas de %s!",

View file

@ -68,8 +68,13 @@
"key.sit!.sit": "Sentar",
"key.sit!.config": "Abrir definições",
"sit!.screen.config": "Definições do Sit!",
"sit!.gui.button.file": "Abrir ficheiro",
"sit!.gui.button.folder": "Abrir pasta",
"sit!.gui.button.reset": "Repor",
"sit!.gui.button.issues": "Problemas",
"sit!.gui.button.donate": "Doar",
"sit!.gui.button.revert": "Reverter alterações",
"sit!.gui.button.save": "Guardar e fechar",
"sit!.gui.button.website": "Website",
"sit!.console.connected": "Conectado ao servidor Sit!: %s",
"sit!.console.player_settings": "Recebidas definições de sentar personalizadas de %s!",

View file

@ -68,8 +68,13 @@
"key.sit!.sit": "Сесть",
"key.sit!.config": "Открыть Конфигурацию",
"sit!.screen.config": "Конфигурация Sit!",
"sit!.gui.button.file": "Открыть Файл",
"sit!.gui.button.folder": "Открыть Папку",
"sit!.gui.button.reset": "Сбросить",
"sit!.gui.button.issues": "Баг‑трекер",
"sit!.gui.button.donate": "Пожертвовать",
"sit!.gui.button.revert": "Отменить Изменения",
"sit!.gui.button.save": "Сохранить и Закрыть",
"sit!.gui.button.website": "Веб-сайт",
"sit!.console.connected": "Подключено к серверу Sit!: %s",
"sit!.console.player_settings": "Получены пользовательские настройки сидения от %s!",

View file

@ -68,8 +68,13 @@
"key.sit!.sit": "Otur",
"key.sit!.config": "Ayarlandırmaları aç",
"sit!.screen.config": "Sit! Ayarlandırmaları",
"sit!.gui.button.file": "Dosya Aç",
"sit!.gui.button.folder": "Klasörü Aç",
"sit!.gui.button.reset": "Sıfırla",
"sit!.gui.button.issues": "Sorunlar",
"sit!.gui.button.donate": "Bağış yap",
"sit!.gui.button.revert": "Değişiklikleri Geri Al",
"sit!.gui.button.save": "Kaydet ve Kapat",
"sit!.gui.button.website": "İnternet Sitesi",
"sit!.console.connected": "Sit! sunucusuna bağlanıldı: %s",
"sit!.console.player_settings": "Özel oturma ayarları %s alındı!",

View file

@ -68,8 +68,13 @@
"key.sit!.sit": "坐下",
"key.sit!.config": "打开配置",
"sit!.screen.config": "Sit! 配置",
"sit!.gui.button.file": "打开文件",
"sit!.gui.button.folder": "打开文件夹",
"sit!.gui.button.reset": "重置",
"sit!.gui.button.issues": "问题反馈",
"sit!.gui.button.donate": "赞助",
"sit!.gui.button.revert": "还原更改",
"sit!.gui.button.save": "保存并关闭",
"sit!.gui.button.website": "网站",
"sit!.console.connected": "已连接到 Sit! 服务器: %s",
"sit!.console.player_settings": "已从 %s 获得自定义坐下设置。",

View file

@ -68,8 +68,13 @@
"key.sit!.sit": "坐下",
"key.sit!.config": "開啟設定",
"sit!.screen.config": "坐下! 設定",
"sit!.gui.button.file": "開啟檔案",
"sit!.gui.button.folder": "開啟資料夾",
"sit!.gui.button.reset": "重置",
"sit!.gui.button.issues": "問題",
"sit!.gui.button.donate": "贊助",
"sit!.gui.button.revert": "還原變更",
"sit!.gui.button.save": "儲存並關閉",
"sit!.gui.button.website": "網站",
"sit!.console.connected": "已連線至 Sit! 伺服器: %s",
"sit!.console.player_settings": "已從 %s 收到自訂坐下設定!",

View file

@ -29,7 +29,7 @@
"fabricloader": ">=0.14.21",
"minecraft": ">=${min_minecraft_version} <=${max_minecraft_version}",
"fabric": "*",
"otterlib": ">=${otterlib_version} <${otterlib_max_version}"
"otterlib": ">=${otterlib_version}"
},
"suggests": {
"modmenu": "*"