Compare commits

..

52 commits

Author SHA1 Message Date
26df4015fe fix bed sitting for new version 2025-06-17 19:42:29 +02:00
70a662d768 merge 1.21.6 support 2025-06-17 19:09:47 +02:00
Oth3r
3f9517a1f0 1.21.6 update 2025-06-17 10:34:33 -05:00
Oth3r
7a1f058f6c 1.21.6 port 2025-06-17 10:34:23 -05:00
Oth3r
ea7e42f8a5 changelog clarification 2025-06-14 19:13:19 -05:00
Oth3r
82c4b375d5 v1.2.4.3 2025-06-14 18:57:37 -05:00
Oth3r
02a7157a93 add otterlib max version as the beta changes a lot of stuff 2025-06-14 18:56:21 -05:00
Oth3r
c675a24e94 v1.2.4.2+1.21.5 2025-06-14 18:52:00 -05:00
Oth3r
2eb6952144 fix not(!) tag check logic 2025-06-14 18:50:55 -05:00
Haru
d82b4b49f9
Merge pull request #24 from Oth3r/crowdin/translations
Update translations from Crowdin
2025-06-14 18:07:09 -05:00
github-actions[bot]
cfcf68f463 Rename JSON translation files to lowercase for consistency 2025-06-14 22:49:33 +00:00
github-actions[bot]
235a0a61db New Crowdin translations by GitHub Action 2025-06-14 22:49:21 +00:00
Oth3r
dea8b5af3e fix target directory 2025-06-14 17:48:17 -05:00
Oth3r
86066ebfb1 Merge remote-tracking branch 'origin/master' 2025-06-14 17:45:58 -05:00
Oth3r
e6eb46d7fa lowercase locale 2025-06-14 17:43:38 -05:00
Oth3r
6c02b090ac get the player's actual reach when checking sitting 2025-06-14 17:13:19 -05:00
Oth3r
bc23a3d2c2
README refresh 2025-06-06 20:09:48 -05:00
Oth3r
61ff50a81d
add OtterLib dependency message, fixes #23 2025-06-06 20:01:52 -05:00
Oth3r
62fd879d0d v1.2.4.1 2025-05-13 14:01:40 -05:00
Oth3r
50c84def58 remove loom version property 2025-05-12 23:18:33 -05:00
Oth3r
d32913a728 remove unnecessary assets 2025-05-12 23:15:36 -05:00
Oth3r
2402c7d7f0 bump versions 2025-05-12 23:12:10 -05:00
Oth3r
2f5dc87a43 update method name to avoid deprecation 2025-05-12 23:10:41 -05:00
Oth3r
4a5df4f253 enabled logging for config files 2025-05-12 23:10:20 -05:00
Oth3r
a39d4cf12f v1.2.4.0 2025-05-08 13:03:25 -05:00
Oth3r
63bf555cdc switch to mod-publish-plugin 2025-05-08 13:03:15 -05:00
Oth3r
2cf57f78c2 add otterlib dependency in fabric.mod.json 2025-05-08 12:54:45 -05:00
Oth3r
a30c9b1cbd update to be compatible with new otterlib version 2025-05-08 12:54:19 -05:00
Oth3r
6f66526f52 remove unneeded language entries 2025-05-08 11:49:55 -05:00
Oth3r
1783c04c87 switch to otterlib config UI 2025-05-04 17:43:37 -05:00
Oth3r
3944881f22 use the otterlib customfile interface 2025-05-04 13:39:34 -05:00
Oth3r
c3b7bb02fd switch to CTxT 2025-05-03 15:41:16 -05:00
Oth3r
e8947f2a24 add otterlib 2025-05-03 15:36:42 -05:00
Oth3r
e0080e313e
Merge pull request #20 from Oth3r/crowdin_translations
Updated Crowdin translations
2025-05-03 13:43:47 -05:00
Crowdin Bot
b733960e4b New Crowdin translations by GitHub Action 2025-05-03 18:41:23 +00:00
Oth3r
03a1283dd2 fix trigger path 2025-05-03 13:37:50 -05:00
Oth3r
07b3077438 Merge branch 'master' into dev 2025-05-03 13:23:41 -05:00
Oth3r
31fff71539 update all languages for the new naming system 2025-05-03 13:20:35 -05:00
Oth3r
aa3b25442d fix the reload method not loading the langreader 2025-05-03 13:18:21 -05:00
Oth3r
6d2c052100 use the reload method instead of loading the files directly 2025-05-03 13:17:40 -05:00
Oth3r
63a8db389c add crowdin actions 2025-05-03 13:08:50 -05:00
Oth3r
fbfde6c8ff grammer 2025-05-03 12:58:42 -05:00
Oth3r
5d8c7cf560 add feature request template 2025-05-03 12:58:39 -05:00
Oth3r
5e3e18db09 update discord link 2025-04-19 19:43:53 -05:00
Oth3r
699280f005 v1.2.3.2 2025-04-19 19:42:04 -05:00
Oth3r
b13f78d45c make extra sure that packets can be sent to the server 2025-04-19 19:39:49 -05:00
Oth3r
e05162f62a Merge branch 'master' into dev 2025-03-13 17:38:07 -05:00
Oth3r
2ca49209b2 documentation 2025-03-12 18:20:53 -05:00
Oth3r
da5fc6b3de fix command parsing 2025-03-12 17:38:58 -05:00
Oth3r
82fd2b1fbf make sitting via hand use the command, for permission support 2025-03-10 10:12:10 -05:00
Oth3r
12bc551356 add canSit() method 2025-03-10 10:11:51 -05:00
Oth3r
9b7794dbb5 remove BlockState parameter of getSittingHeight() method and retrieve inside 2025-03-10 10:04:24 -05:00
68 changed files with 1165 additions and 620 deletions

View file

@ -5,7 +5,7 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | 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 - type: textarea
id: description id: description
attributes: attributes:

View file

@ -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)

View file

@ -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"

View file

@ -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 }}

View file

@ -1,46 +1,68 @@
# Sit! <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;">
[![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/Mec6yNQ9B7?style=flat)](https://discord.gg/Mec6yNQ9B7)
[![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) [![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 minecraft mod that adds sitting in vanilla minecraft.
Sit on **stairs**, **slabs**, **carpets** by default, and sit on everything else using the config! ### **Sit!** is a vanilla+ mod that adds sitting in minecraft.
You can also customize hand restrictions to stop accidentally sitting down! * Sit on **stairs**, **slabs**, **carpets** by default, and sit on everything else by tweaking the config!
The mod also has full Geyser support! Enjoy sitting with everyone, weather they are on Bedrock or Java! * 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? ### 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)!
![overview](https://github.com/Oth3r/Sit/blob/master/media/overview.gif?raw=true) 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! ## Check out my other Projects!
[![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) <a href="https://modrinth.com/mod/caligo">
[![DirectionHUD Spigot badge](https://github.com/Oth3r/DirectionHUD/blob/master/media/plugin-badge.png?raw=true)](https://modrinth.com/plugin/directionhud-plugin) <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>
# Features # Features
### Hand Restrictions ### 🤚 Hand Restrictions
Don't want to accidentally sit down? Set custom restrictions for each hand in the config! 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! <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">
![hand restrictions](https://github.com/Oth3r/Sit/blob/master/media/hand-restrictions.gif?raw=true) ### 🟩 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 <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;"
Want to sit on _**EVERY**_ block? With the config you can add more options to sit on! Custom block states are also supported. alt="players sitting on a vast range of blocks">
![custom blocks](https://github.com/Oth3r/Sit/blob/master/media/custom-blocks.gif?raw=true) ### ⌨️ Keybinds
Don't want to sit with the **just** the hand? Use a keybind or type a command to sit instead!
### Customizable Config <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;"
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! alt="setting keybinds for the sit mod, and sitting by using them">
![config](https://github.com/Oth3r/Sit/blob/master/media/config.gif?raw=true) ### 📃 Customizable Config
![custom blocks config](https://github.com/Oth3r/Sit/blob/master/media/custom-blocks-config.png?raw=true) 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">
## Future Goals ## Future Goals
* Forge Port (probably NeoForge 1.21) * NeoForge Port
* Custom dismounting logic * Full config via [OtterLib](https://modrinth.com/mod/otterlib)
* better config (coming soon!)
* keybindings (next update)

View file

@ -1,8 +1,7 @@
plugins { plugins {
id 'fabric-loom' version '1.10-SNAPSHOT' id 'fabric-loom' version "1.10-SNAPSHOT"
id 'maven-publish' id 'maven-publish'
id 'com.modrinth.minotaur' version '2.+' id "me.modmuss50.mod-publish-plugin" version "0.8.4"
id 'net.darkhax.curseforgegradle' version '1.1.+'
id 'co.uzzu.dotenv.gradle' version '4.0.0' id 'co.uzzu.dotenv.gradle' version '4.0.0'
} }
@ -14,6 +13,7 @@ base {
} }
repositories { repositories {
mavenLocal()
maven { url = "https://maven.terraformersmc.com/releases/" } maven { url = "https://maven.terraformersmc.com/releases/" }
maven { url = "https://maven.isxander.dev/releases" } maven { url = "https://maven.isxander.dev/releases" }
} }
@ -30,6 +30,8 @@ dependencies {
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}" modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
modImplementation "one.oth3r:otterlib:${project.otterlib_version}"
} }
processResources { processResources {
@ -40,6 +42,8 @@ processResources {
minecraft_version : minecraft_version, minecraft_version : minecraft_version,
min_minecraft_version : min_minecraft_version, min_minecraft_version : min_minecraft_version,
max_minecraft_version : max_minecraft_version, max_minecraft_version : max_minecraft_version,
otterlib_version : otterlib_version,
otterlib_max_version : otterlib_max_version,
loader_version : loader_version loader_version : loader_version
] ]
@ -86,33 +90,35 @@ publishing {
} }
} }
import com.modrinth.minotaur.dependencies.ModDependency publishMods {
modrinth {
token = env.fetchOrNull('MODRINTH')
projectId = 'EsYqsGV4'
versionNumber = project.mod_version
versionName = "v${project.mod_version} [Fabric]"
versionType = "release"
uploadFile = remapJar
gameVersions = project.minecraft_versions.split(",").toList()
loaders = ['fabric', 'quilt']
dependencies = [
new ModDependency('P7dR8mSH', 'required'),
new ModDependency('mOgUt4GM', 'optional')
]
changelog = file('changelog.md').text 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) { version = mod_version
apiToken = env.fetchOrNull('CURSEFORGE') displayName = "v${mod_version} [Fabric]"
def mainFile = upload(892424, remapJar) curseforge {
mainFile.changelog = file('changelog.md') accessToken = env.fetchOrNull('CURSEFORGE')
mainFile.displayName = "v${project.mod_version} [Fabric]" projectId = "892424"
mainFile.addModLoader("fabric", 'quilt') projectSlug = "sit1"
mainFile.releaseType = "release" minecraftVersions.addAll(minecraft_versions.split(",").toList())
mainFile.addEnvironment("client", "server")
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"
}
} }

View file

@ -1,5 +1,18 @@
# v1.2.3.1 # v1.2.4.3
* added a version position for quick patches * added a max OtterLib version as the beta will have breaking changes between major versions
* fixed sitting height being off by .2
# v1.2.3 # v1.2.4.2
* fixed not being able to sit when the Y level was below 0 * 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

12
crowdin.yml Normal file
View file

@ -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",
}
]

View file

@ -4,19 +4,21 @@ org.gradle.parallel=true
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
min_minecraft_version=1.21.5 min_minecraft_version=1.21.6
max_minecraft_version=1.21.5 max_minecraft_version=1.21.6
minecraft_versions=1.21.5 minecraft_versions=1.21.6
minecraft_version=1.21.5 minecraft_version=1.21.6
yarn_mappings=1.21.5+build.1 yarn_mappings=1.21.6+build.1
loader_version=0.16.10 loader_version=0.16.14
# Mod Properties # Mod Properties
mod_version=1.2.3.1+1.21.5 mod_version=1.2.4.3+1.21.6
maven_group=one.oth3r maven_group=one.oth3r
file_name=sit! file_name=sit!
# Dependencies # Dependencies
fabric_version=0.119.5+1.21.5 fabric_version=0.127.0+1.21.6
modmenu_version=14.0.0-rc.2 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

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View file

@ -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

View file

@ -1,8 +1,18 @@
package one.oth3r.sit; package one.oth3r.sit;
import net.fabricmc.api.ClientModInitializer; 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.Data;
import one.oth3r.sit.utl.Events; 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 { public class SitClient implements ClientModInitializer {
@ -12,5 +22,18 @@ public class SitClient implements ClientModInitializer {
Events.registerClient(); 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()
));
}
} }

View file

@ -14,6 +14,7 @@ import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Logic; import one.oth3r.sit.utl.Logic;
import one.oth3r.sit.utl.Utl; import one.oth3r.sit.utl.Utl;
import java.awt.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class SitCommand { public class SitCommand {
@ -49,7 +50,7 @@ public class SitCommand {
if (player == null) { if (player == null) {
if (args[0].equalsIgnoreCase("reload")) { if (args[0].equalsIgnoreCase("reload")) {
Logic.reload(); Logic.reload();
Data.LOGGER.info(Utl.lang("sit!.chat.reloaded").getString()); Data.LOGGER.info(Utl.lang("sit!.chat.reloaded").toString());
} }
return 1; return 1;
} }
@ -75,7 +76,7 @@ public class SitCommand {
if (args[0].equalsIgnoreCase("reload")) { if (args[0].equalsIgnoreCase("reload")) {
Logic.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); if (args[0].equalsIgnoreCase("purgeChairEntities")) Utl.Entity.purge(player,true);

View file

@ -9,6 +9,7 @@ import net.minecraft.util.Identifier;
import one.oth3r.sit.utl.Utl; import one.oth3r.sit.utl.Utl;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
public class CustomBlock { public class CustomBlock {
@ -90,18 +91,38 @@ public class CustomBlock {
} }
// a boolean to check if one of the blocks are in a filtered tag // 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) { for (String tag : blockTags) {
// substring to remove # and if needed, ! // substring to remove # and if needed, !
// if there is a math for the NOT(!) tag, return false if (tag.startsWith("!")) {
if (tag.startsWith("!") && blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.of(tag.substring(2))))) return false; // if there is a match for the NOT(!) tag, return false
// if there is a match, return true Identifier id = Identifier.tryParse(tag.substring(2));
if (blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse(tag.substring(1))))) tagCheck = true; 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 // if there were any required tags, return whether we matched one
return tagCheck; // 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);
} }
} }

View file

@ -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 <T extends CustomFile<T>> {
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<T> 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());
}
}

View file

@ -7,6 +7,7 @@ import net.minecraft.registry.tag.TagKey;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
public class CustomItem { public class CustomItem {
@SerializedName("item-ids") @SerializedName("item-ids")
@ -21,6 +22,11 @@ public class CustomItem {
this.itemTags = itemTags; this.itemTags = itemTags;
} }
public CustomItem(CustomItem customItem) {
this.itemIDs = new ArrayList<>(customItem.itemIDs);
this.itemTags = new ArrayList<>(customItem.itemTags);
}
public ArrayList<String> getItemIDs() { public ArrayList<String> getItemIDs() {
return itemIDs; return itemIDs;
} }
@ -45,21 +51,38 @@ public class CustomItem {
} }
// a boolean to check if one of the items are in a filtered tag // 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) { for (String tag : itemTags) {
// substring to remove # and if needed, "!" // substring to remove # and if needed, "!"
// if a NOT tag
if (tag.startsWith("!")) { if (tag.startsWith("!")) {
// if there is a math for the NOT(!) tag, return false // if there is a math for the NOT(!) tag, return false
if (itemStack.isIn(TagKey.of(Registries.ITEM.getKey(), Identifier.of(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(), Identifier.of(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 // if there were any required tags, return whether we matched one
return tagCheck; // 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);
} }
} }

View file

@ -3,6 +3,7 @@ package one.oth3r.sit.file;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class HandSetting { public class HandSetting {
@ -21,6 +22,11 @@ public class HandSetting {
this.filter = filter; this.filter = filter;
} }
public HandSetting(HandSetting handSetting) {
this.sittingRequirement = handSetting.sittingRequirement;
this.filter = new Filter(handSetting.filter);
}
public SittingRequirement getSittingRequirement() { public SittingRequirement getSittingRequirement() {
return sittingRequirement; return sittingRequirement;
} }
@ -52,6 +58,12 @@ public class HandSetting {
this.customItems = customItems; 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() { public Boolean isInverted() {
return invert; return invert;
} }
@ -80,6 +92,12 @@ public class HandSetting {
this.usable = usable; this.usable = usable;
} }
public Presets(Presets presets) {
this.block = presets.block;
this.food = presets.food;
this.usable = presets.usable;
}
public boolean isBlock() { public boolean isBlock() {
return block; return block;
} }
@ -91,6 +109,42 @@ public class HandSetting {
public boolean isUsable() { public boolean isUsable() {
return usable; 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);
}
} }

View file

@ -4,6 +4,7 @@ import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import net.minecraft.text.MutableText; import net.minecraft.text.MutableText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import one.oth3r.otterlib.chat.CTxT;
import one.oth3r.sit.Sit; import one.oth3r.sit.Sit;
import one.oth3r.sit.utl.Data; import one.oth3r.sit.utl.Data;
@ -20,14 +21,19 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class LangReader { public class LangReader {
private static final Map<String, String> defaultLangMap = new HashMap<>();
private static final Map<String, String> languageMap = new HashMap<>(); private static final Map<String, String> languageMap = new HashMap<>();
private final String translationKey; private final String translationKey;
private final Object[] placeholders; private final Object[] placeholders;
public LangReader(String translationKey, Object... placeholders) { public LangReader(String translationKey, Object... placeholders) {
this.translationKey = translationKey; this.translationKey = translationKey;
this.placeholders = placeholders; this.placeholders = placeholders;
} }
public MutableText getTxT() {
public CTxT getTxT() {
String translated = getLanguageValue(translationKey); String translated = getLanguageValue(translationKey);
if (placeholders != null && placeholders.length > 0) { if (placeholders != null && placeholders.length > 0) {
//removed all double \\ and replaces with \ //removed all double \\ and replaces with \
@ -35,7 +41,8 @@ public class LangReader {
String regex = "%\\d*\\$?[dfs]"; String regex = "%\\d*\\$?[dfs]";
Matcher anyMatch = Pattern.compile(regex).matcher(translated); Matcher anyMatch = Pattern.compile(regex).matcher(translated);
Matcher endMatch = Pattern.compile(regex+"$").matcher(translated); Matcher endMatch = Pattern.compile(regex+"$").matcher(translated);
//Arraylist with all the %(#$)[dfs]
// Arraylist with all the %(#$)[dfs]
ArrayList<String> matches = new ArrayList<>(); ArrayList<String> matches = new ArrayList<>();
while (anyMatch.find()) { while (anyMatch.find()) {
String match = anyMatch.group(); 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 there are placeholders specified, and the split is more than 1, it will replace %(dfs) with the placeholder objects
if (parts.length > 1) { if (parts.length > 1) {
MutableText txt = Text.empty(); CTxT txt = new CTxT("");
int i = 0; int i = 0;
for (String match : matches) { for (String match : matches) {
int get = i; int get = i;
@ -62,47 +69,56 @@ public class LangReader {
} }
if (parts.length != i) txt.append(parts[i]); if (parts.length != i) txt.append(parts[i]);
//convert the obj into txt //convert the obj into txt
Object obj = placeholders[get]; txt.append(getTxTFromObj(placeholders[get]));
if (obj instanceof Text) txt.append((Text) obj);
else txt.append(String.valueOf(obj));
i++; i++;
} }
if (parts.length != i) txt.append(parts[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) { public static LangReader of(String translationKey, Object... placeholders) {
return new LangReader(translationKey, placeholders); return new LangReader(translationKey, placeholders);
} }
public static void loadLanguageFile() { public static void loadLanguageFile() {
ClassLoader classLoader = Sit.class.getClassLoader(); Type tToken = new TypeToken<Map<String, String>>(){}.getType();
try { try {
InputStream inputStream = classLoader.getResourceAsStream("assets/sit-oth3r/lang/" + FileData.getServerConfig().getLang() +".json"); // load the config language
Reader selectionReader = new InputStreamReader(getInputStream(false), StandardCharsets.UTF_8);
// if the input stream is null, the language file wasn't found languageMap.putAll(new Gson().fromJson(selectionReader, tToken));
if (inputStream == null) { // load the default language as well (fallback)
// try loading the default language file Reader defaultReader = new InputStreamReader(getInputStream(true), StandardCharsets.UTF_8);
inputStream = classLoader.getResourceAsStream("assets/sit-oth3r/lang/" + new ServerConfig().getLang() +".json"); defaultLangMap.putAll(new Gson().fromJson(defaultReader, tToken));
Data.LOGGER.error("COULDN'T LOAD THE LANGUAGE FILE. RESETTING TO en_us.");
}
// if the input stream is still null, throw an exception
if (inputStream == null) throw new IllegalArgumentException("UNABLE TO LOAD THE ENGLISH LANGUAGE FILE.");
Type type = new TypeToken<Map<String, String>>(){}.getType();
Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
languageMap.putAll(new Gson().fromJson(reader, type));
// close the input stream
inputStream.close();
} catch (Exception e) { } catch (Exception e) {
Data.LOGGER.error(e.getMessage()); 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) { public static String getLanguageValue(String key) {
return languageMap.getOrDefault(key, key); return languageMap.getOrDefault(key, defaultLangMap.getOrDefault(key, key));
} }
} }

View file

@ -1,10 +1,13 @@
package one.oth3r.sit.file; package one.oth3r.sit.file;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import one.oth3r.otterlib.file.CustomFile;
import one.oth3r.otterlib.file.FileSettings;
import one.oth3r.sit.utl.Data; import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Utl; import one.oth3r.sit.utl.Utl;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -13,15 +16,18 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects;
import java.util.Properties; import java.util.Properties;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ServerConfig implements CustomFile<ServerConfig> { public class ServerConfig implements CustomFile<ServerConfig> {
@SerializedName("version") @SerializedName("version")
private Double version = 2.2; private Double version = 2.3;
@SerializedName("lang") @SerializedName("lang")
private String lang = "en_us"; private String lang = "en_us";
@ -51,7 +57,7 @@ public class ServerConfig implements CustomFile<ServerConfig> {
public ServerConfig() {} public ServerConfig() {}
public ServerConfig(ServerConfig serverConfig) { public ServerConfig(ServerConfig serverConfig) {
loadFileData(serverConfig); copyFileData(serverConfig);
} }
public ServerConfig(Double version, String lang, boolean keepActive, boolean sitWhileSeated, public ServerConfig(Double version, String lang, boolean keepActive, boolean sitWhileSeated,
@ -151,6 +157,18 @@ public class ServerConfig implements CustomFile<ServerConfig> {
public boolean isFullBlocks() { public boolean isFullBlocks() {
return fullBlocks; return fullBlocks;
} }
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
PresetBlocks that = (PresetBlocks) o;
return stairs == that.stairs && slabs == that.slabs && carpets == that.carpets && fullBlocks == that.fullBlocks;
}
@Override
public int hashCode() {
return Objects.hash(stairs, slabs, carpets, fullBlocks);
}
} }
public static class YDifferenceLimit { public static class YDifferenceLimit {
@ -199,11 +217,36 @@ public class ServerConfig implements CustomFile<ServerConfig> {
public void setBelow(Double below) { public void setBelow(Double below) {
this.below = below; this.below = below;
} }
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
YDifferenceLimit that = (YDifferenceLimit) o;
return Objects.equals(above, that.above) && Objects.equals(below, that.below);
}
@Override
public int hashCode() {
return Objects.hash(above, below);
}
}
@Override
public FileSettings getFileSettings() {
return new FileSettings(Data.LOGGER);
}
/**
* the path to the file - including the extension ex. usr/config/custom-file.json
*/
@Override
public Path getFilePath() {
return Paths.get(Data.CONFIG_DIR, "server-config.json");
} }
@Override @Override
public void reset() { public void reset() {
loadFileData(new ServerConfig()); copyFileData(new ServerConfig());
} }
@Override @Override
@ -211,8 +254,13 @@ public class ServerConfig implements CustomFile<ServerConfig> {
return ServerConfig.class; return ServerConfig.class;
} }
/**
* loads the data from the file object into the current object - DEEP COPY
*
* @param newFile the file to take the properties from
*/
@Override @Override
public void loadFileData(ServerConfig newFile) { public void copyFileData(ServerConfig newFile) {
this.version = newFile.version; this.version = newFile.version;
this.lang = newFile.lang; this.lang = newFile.lang;
this.keepActive = newFile.keepActive; this.keepActive = newFile.keepActive;
@ -228,28 +276,28 @@ public class ServerConfig implements CustomFile<ServerConfig> {
this.interactionBlocks = newFile.interactionBlocks.stream().map(CustomBlock::new).collect(Collectors.toCollection(ArrayList::new)); 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 @Override
public void update() { public void update(JsonElement json) {
/// update to 2.1, just a new list, nothing to change /// update to 2.1, just a new list, nothing to change
/// update to 2.2, new settings, no changes /// update to 2.2, new settings, no changes
if (version >= 2.0 && version <= 2.1) { if (version >= 2.0 && version <= 2.1) {
version = 2.2; 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 @Override
public String getFileName() { public void createDirectory() {
return "server-config.json"; CustomFile.super.createDirectory();
}
@Override
public String getDirectory() {
return Data.CONFIG_DIR;
}
@Override
public void fileNotExist() {
CustomFile.super.fileNotExist();
// try checking the old/legacy config directory for the file // try checking the old/legacy config directory for the file
if (Legacy.getLegacyFile().exists()) { if (Legacy.getLegacyFile().exists()) {
Data.LOGGER.info("Updating Sit!.properties to sit!/config.json"); Data.LOGGER.info("Updating Sit!.properties to sit!/config.json");
@ -257,6 +305,25 @@ public class ServerConfig implements CustomFile<ServerConfig> {
} }
} }
@Override
public ServerConfig clone() {
ServerConfig clone = new ServerConfig();
clone.copyFileData(this);
return clone;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
ServerConfig that = (ServerConfig) o;
return Objects.equals(version, that.version) && Objects.equals(lang, that.lang) && Objects.equals(keepActive, that.keepActive) && Objects.equals(sitWhileSeated, that.sitWhileSeated) && Objects.equals(presetBlocks, that.presetBlocks) && Objects.equals(yDifferenceLimit, that.yDifferenceLimit) && Objects.equals(customEnabled, that.customEnabled) && Objects.equals(sittingBlocks, that.sittingBlocks) && Objects.equals(blacklistedBlocks, that.blacklistedBlocks) && Objects.equals(interactionBlocks, that.interactionBlocks);
}
@Override
public int hashCode() {
return Objects.hash(version, lang, langOptions, keepActive, sitWhileSeated, presetBlocks, yDifferenceLimit, customEnabled, sittingBlocks, blacklistedBlocks, interactionBlocks);
}
protected static class Legacy { protected static class Legacy {
/** /**
* gets the legacy file, from the old directory for fabric, and the same one for spigot * gets the legacy file, from the old directory for fabric, and the same one for spigot

View file

@ -3,6 +3,7 @@ package one.oth3r.sit.file;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
public class SittingBlock extends CustomBlock { public class SittingBlock extends CustomBlock {
@SerializedName("sitting-height") @SerializedName("sitting-height")
@ -27,4 +28,17 @@ public class SittingBlock extends CustomBlock {
super(sittingBlock); super(sittingBlock);
this.sittingHeight = sittingBlock.sittingHeight; this.sittingHeight = sittingBlock.sittingHeight;
} }
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
SittingBlock that = (SittingBlock) o;
return Objects.equals(sittingHeight, that.sittingHeight);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), sittingHeight);
}
} }

View file

@ -1,10 +1,17 @@
package one.oth3r.sit.file; package one.oth3r.sit.file;
import com.google.common.base.Objects;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import one.oth3r.otterlib.file.CustomFile;
import one.oth3r.otterlib.file.FileSettings;
import one.oth3r.sit.utl.Data; import one.oth3r.sit.utl.Data;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.nio.file.Path;
import java.nio.file.Paths;
public class SittingConfig implements CustomFile<SittingConfig> { public class SittingConfig implements CustomFile<SittingConfig> {
@SerializedName("version") @SerializedName("version")
@ -29,7 +36,7 @@ public class SittingConfig implements CustomFile<SittingConfig> {
} }
public SittingConfig(SittingConfig sittingConfig) { public SittingConfig(SittingConfig sittingConfig) {
loadFileData(sittingConfig); copyFileData(sittingConfig);
} }
public Double getVersion() { public Double getVersion() {
@ -64,9 +71,19 @@ public class SittingConfig implements CustomFile<SittingConfig> {
return offHand; return offHand;
} }
@Override
public FileSettings getFileSettings() {
return new FileSettings(Data.LOGGER);
}
@Override
public Path getFilePath() {
return Paths.get(Data.CONFIG_DIR, "sitting-config.json");
}
@Override @Override
public void reset() { public void reset() {
loadFileData(new SittingConfig()); copyFileData(new SittingConfig());
} }
@Override @Override
@ -75,24 +92,35 @@ public class SittingConfig implements CustomFile<SittingConfig> {
} }
@Override @Override
public void loadFileData(SittingConfig newFile) { public void copyFileData(SittingConfig sittingConfig) {
this.version = newFile.version; this.version = sittingConfig.version;
this.enabled = newFile.enabled; this.enabled = sittingConfig.enabled;
this.handSitting = newFile.handSitting; this.handSitting = sittingConfig.handSitting;
this.mainHand = newFile.mainHand; this.mainHand = new HandSetting(sittingConfig.mainHand);
this.offHand = newFile.offHand; this.offHand = new HandSetting(sittingConfig.offHand);
} }
@Override @Override
public void update() {} public void update(JsonElement jsonElement) {
@Override
public String getFileName() {
return "sitting-config.json";
} }
@Override @Override
public String getDirectory() { public SittingConfig clone() {
return Data.CONFIG_DIR; SittingConfig clone = new SittingConfig();
clone.copyFileData(this);
return clone;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
SittingConfig that = (SittingConfig) o;
return Objects.equal(version, that.version) && Objects.equal(enabled, that.enabled) && Objects.equal(handSitting, that.handSitting) && Objects.equal(mainHand, that.mainHand) && Objects.equal(offHand, that.offHand);
}
@Override
public int hashCode() {
return Objects.hashCode(version, enabled, handSitting, mainHand, offHand);
} }
} }

View file

@ -6,19 +6,21 @@ import net.minecraft.server.command.ReloadCommand;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
import one.oth3r.sit.file.FileData;
import one.oth3r.sit.utl.Data; import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Logic;
import one.oth3r.sit.utl.Utl; import one.oth3r.sit.utl.Utl;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.awt.*;
@Mixin(ReloadCommand.class) @Mixin(ReloadCommand.class)
public class ReloadCommandMixin { public class ReloadCommandMixin {
@Inject(at = @At("TAIL"), method = "register") @Inject(at = @At("TAIL"), method = "register")
private static void register(CommandDispatcher<ServerCommandSource> dispatcher, CallbackInfo ci) { private static void register(CommandDispatcher<ServerCommandSource> dispatcher, CallbackInfo ci) {
FileData.loadFiles(); Logic.reload();
// make sure the server isn't null // make sure the server isn't null
MinecraftServer server = Data.getServer(); MinecraftServer server = Data.getServer();
@ -27,7 +29,7 @@ public class ReloadCommandMixin {
// send a reloaded message to all players with permissions // send a reloaded message to all players with permissions
for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) { for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) {
if (player.isCreativeLevelTwoOp()) { if (player.isCreativeLevelTwoOp()) {
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());
} }
} }
} }

View file

@ -1,27 +0,0 @@
package one.oth3r.sit.screen;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import java.util.function.Supplier;
public class ClickableImageWidget extends ButtonWidget {
private final Identifier image;
public ClickableImageWidget(int x, int y, int width, int height, Tooltip tooltip, Identifier image, ButtonWidget.PressAction onPress) {
super(x, y, width, height, Text.empty(), onPress, Supplier::get);
this.image = image;
this.setTooltip(tooltip);
}
@Override
protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
context.drawTexture(RenderLayer::getGuiTextured, image,
this.getX(), this.getY(), 0.0f, 0.0f, this.getWidth(), this.getHeight(), this.getWidth(), this.getHeight());
}
}

View file

@ -1,77 +0,0 @@
package one.oth3r.sit.screen;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.ConfirmLinkScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.ColorHelper;
import one.oth3r.sit.file.FileData;
import one.oth3r.sit.utl.Data;
import java.net.URI;
public class ConfigScreen extends Screen {
protected final Screen parent;
public ConfigScreen(Screen parent) {
super(Text.translatable("sit!.screen.config"));
this.parent = parent;
}
@Override
protected void init() {
int startY = this.height / 4 + 48;
int spacing = 36;
TextureButtonWidget serverConfigButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("config.server"),
(button) -> client.setScreen(new UnderConstructionScreen(this, FileData.getServerConfig())), false)
.dimensions(250,30).texture(Identifier.of(Data.MOD_ID, "server_button"), 246, 26).build());
serverConfigButton.setPosition(this.width / 2 - (serverConfigButton.getWidth()/2), startY);
TextureButtonWidget sittingConfigButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("config.sitting"),
(button) -> client.setScreen(new UnderConstructionScreen(this, FileData.getSittingConfig())), false)
.dimensions(250,30).texture(Identifier.of(Data.MOD_ID, "sitting_button"), 246, 26).build());
sittingConfigButton.setPosition(this.width / 2 - (sittingConfigButton.getWidth()/2), startY+36);
TextureButtonWidget issuesButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("sit!.gui.button.issues"),
ConfirmLinkScreen.opening(this, URI.create("https://github.com/Oth3r/Sit/issues")), true)
.dimensions(20,20).texture(Identifier.of(Data.MOD_ID, "issues"), 15, 15).build());
issuesButton.setPosition(this.width / 2 - 125, startY + 72 + 12);
this.addDrawableChild(ButtonWidget.builder(Text.translatable("sit!.gui.button.website"),
ConfirmLinkScreen.opening(this, URI.create("https://modrinth.com/mod/sit!"))
).dimensions(this.width / 2 - 100, startY + 72 + 12, 98, 20).build());
this.addDrawableChild(ButtonWidget.builder(Text.translatable("gui.done"), (button) -> {
close();
}).dimensions(this.width / 2 + 2, startY + 72 + 12, 98, 20).build());
TextureButtonWidget donateButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("sit!.gui.button.donate"),
ConfirmLinkScreen.opening(this, URI.create("https://Ko-fi.com/oth3r")), true)
.dimensions(20,20).texture(Identifier.of(Data.MOD_ID, "donate"), 15, 15).build());
donateButton.setPosition(this.width / 2 + 105, startY + 72 + 12);
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
super.render(context, mouseX, mouseY, delta);
// todo fade in like the title screen on first load?
renderBanner(context,width/2 - 64,this.height / 4 -38,1);
}
@Override
public void close() {
this.client.setScreen(parent);
}
private void renderBanner(DrawContext context, int x, int y, float alpha) {
context.drawTexture(RenderLayer::getGuiTextured,Identifier.of(Data.MOD_ID, "textures/gui/banner.png"),
x, y, 0.0f, 0.0f, 128, 72, 128, 72, ColorHelper.getWhite(alpha));
}
}

View file

@ -2,10 +2,11 @@ package one.oth3r.sit.screen;
import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi; import com.terraformersmc.modmenu.api.ModMenuApi;
import one.oth3r.sit.SitClient;
public class ModMenu implements ModMenuApi { public class ModMenu implements ModMenuApi {
@Override @Override
public ConfigScreenFactory<?> getModConfigScreenFactory() { public ConfigScreenFactory<?> getModConfigScreenFactory() {
return ConfigScreen::new; return SitClient::getConfigScreen;
} }
} }

View file

@ -1,86 +0,0 @@
package one.oth3r.sit.screen;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
public class TextureButtonWidget extends ButtonWidget {
//todo gray support
protected final Identifier texture;
protected final int textureWidth;
protected final int textureHeight;
protected final boolean tooltip;
TextureButtonWidget(int width, int height, Text message, int textureWidth, int textureHeight, Identifier texture, ButtonWidget.PressAction onPress, @Nullable ButtonWidget.NarrationSupplier narrationSupplier, boolean tooltip) {
super(0, 0, width, height, message, onPress, narrationSupplier == null ? DEFAULT_NARRATION_SUPPLIER : narrationSupplier);
this.textureWidth = textureWidth;
this.textureHeight = textureHeight;
this.texture = texture;
this.tooltip = tooltip;
if (tooltip) setTooltip(Tooltip.of(message));
}
@Override
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
super.renderWidget(context, mouseX, mouseY, delta);
int x = this.getX() + this.getWidth() / 2 - this.textureWidth / 2;
int y = this.getY() + this.getHeight() / 2 - this.textureHeight / 2;
context.drawGuiTexture(RenderLayer::getGuiTextured, this.texture, x, y, this.textureWidth, this.textureHeight);
}
@Override
public void drawMessage(DrawContext context, TextRenderer textRenderer, int color) {
if (!this.tooltip) super.drawMessage(context, textRenderer, color);
}
public static class Builder {
private final Text text;
private final ButtonWidget.PressAction onPress;
private final boolean hideText;
private int width = 150;
private int height = 20;
@Nullable
private Identifier texture;
private int textureWidth;
private int textureHeight;
@Nullable
ButtonWidget.NarrationSupplier narrationSupplier;
public Builder(Text text, ButtonWidget.PressAction onPress, boolean hideText) {
this.text = text;
this.onPress = onPress;
this.hideText = hideText;
}
public Builder dimensions(int width, int height) {
this.width = width;
this.height = height;
return this;
}
public Builder texture(Identifier texture, int width, int height) {
this.texture = texture;
this.textureWidth = width;
this.textureHeight = height;
return this;
}
public Builder narration(ButtonWidget.NarrationSupplier narrationSupplier) {
this.narrationSupplier = narrationSupplier;
return this;
}
public TextureButtonWidget build() {
if (this.texture == null) {
throw new IllegalStateException("Sprite not set");
}
return new TextureButtonWidget(width,height,text,textureWidth,textureHeight,texture,onPress,narrationSupplier,hideText);
}
}
}

View file

@ -1,79 +0,0 @@
package one.oth3r.sit.screen;
import net.minecraft.client.gui.screen.ConfirmLinkScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import one.oth3r.sit.file.CustomFile;
import one.oth3r.sit.file.SittingConfig;
import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Utl;
import java.net.URI;
import java.nio.file.Paths;
public class UnderConstructionScreen<T extends CustomFile<T>> extends Screen {
protected final Screen parent;
protected T file;
public UnderConstructionScreen(Screen parent, T file) {
super(Text.translatable("sit!.screen.config"));
this.parent = parent;
this.file = file;
}
@Override
protected void init() {
int startY = this.height / 5-4;
ButtonWidget foxPNG = this.addDrawableChild(new ClickableImageWidget(70,70,140,140, Tooltip.of(Text.of("Art by @bunnestbun")),
Identifier.of(Data.MOD_ID, "textures/gui/fox.png"), ConfirmLinkScreen.opening(this, URI.create("https://www.instagram.com/bunnestbun/"))));
foxPNG.setPosition(this.width / 2 - (foxPNG.getWidth()/2), startY-35);
ButtonWidget openFileButton = this.addDrawableChild(new ButtonWidget.Builder(Text.translatable("sit!.gui.button.file"),
(button) -> Util.getOperatingSystem().open(this.file.getFile()))
.dimensions(0, 0, 118 ,20).build());
openFileButton.setPosition(this.width / 2 - 70, startY+110);
TextureButtonWidget folderButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("sit!.gui.button.folder"),
(button) -> Util.getOperatingSystem().open(Paths.get(this.file.getFile().getParent())), true)
.dimensions(20,20).texture(Identifier.of(Data.MOD_ID, "folder"), 15, 15).build());
folderButton.setPosition(this.width / 2 + 50, startY + 110);
TextureButtonWidget resetButton = this.addDrawableChild(new TextureButtonWidget.Builder(Text.translatable("sit!.gui.button.reset"),
(button) -> {
this.file.reset();
this.file.save();
}, true)
.dimensions(20,20).texture(Identifier.of(Data.MOD_ID, "reset_file"), 15, 15).build());
resetButton.setPosition(this.width / 2 -70, startY + 135);
ButtonWidget revertButton = this.addDrawableChild(new ButtonWidget.Builder(Text.translatable("sit!.gui.button.revert"),
(button) -> this.file.save())
.dimensions(0, 0, 118,20).build());
revertButton.setPosition(this.width / 2 - 48, startY+135);
ButtonWidget saveExitButton = this.addDrawableChild(new ButtonWidget.Builder(Text.translatable("sit!.gui.button.save"),
(button) -> {
this.file.load();
this.file.save();
// send the settings to the server if editing the sitting file and on a supported server
if (this.file instanceof SittingConfig && Data.isSupportedServer()) {
Utl.sendSettingsPackets();
}
this.client.setScreen(parent);
})
.dimensions(0, 0, 140,20).build());
saveExitButton.setPosition(this.width / 2 - 70, startY+168);
}
@Override
public void close() {
this.client.setScreen(parent);
}
}

View file

@ -1,5 +1,8 @@
package one.oth3r.sit.utl; package one.oth3r.sit.utl;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.ParseResults;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
@ -14,17 +17,19 @@ import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.option.KeyBinding; import net.minecraft.client.option.KeyBinding;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.Formatting; import one.oth3r.sit.SitClient;
import one.oth3r.sit.command.SitCommand; import one.oth3r.sit.command.SitCommand;
import one.oth3r.sit.file.FileData; import one.oth3r.sit.file.FileData;
import one.oth3r.sit.file.LangReader; import one.oth3r.sit.file.LangReader;
import one.oth3r.sit.file.SittingConfig; import one.oth3r.sit.file.SittingConfig;
import one.oth3r.sit.packet.SitPayloads; import one.oth3r.sit.packet.SitPayloads;
import one.oth3r.sit.screen.ConfigScreen;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.awt.*;
public class Events { public class Events {
private static class Keybindings { private static class Keybindings {
@ -54,7 +59,7 @@ public class Events {
ClientPlayerEntity player = client.player; ClientPlayerEntity player = client.player;
while (config__key.wasPressed()) { while (config__key.wasPressed()) {
client.setScreen(new ConfigScreen(client.currentScreen)); client.setScreen(SitClient.getConfigScreen(client.currentScreen));
} }
/// anything below uses the player object, make sure it's not null /// anything below uses the player object, make sure it's not null
@ -70,11 +75,11 @@ public class Events {
// just send the sit command // just send the sit command
if (Data.isInGame()) { if (Data.isInGame()) {
if (Data.isSupportedServer()) { if (Data.isSupportedServer()) {
player.networkHandler.sendCommand("sit"); player.networkHandler.sendChatCommand("sit");
} else { } else {
// unsupported server message if not in a Sit! server // unsupported server message if not in a Sit! server
player.sendMessage(Utl.lang("sit!.chat.unsupported") player.sendMessage(Utl.lang("sit!.chat.unsupported")
.formatted(Formatting.RED), true); .color(Color.RED).b(), true);
} }
} }
} }
@ -99,7 +104,7 @@ public class Events {
ServerPlayNetworking.send(context.player(),new SitPayloads.ResponsePayload(SitPayloads.ResponsePayload.VERSION)); ServerPlayNetworking.send(context.player(),new SitPayloads.ResponsePayload(SitPayloads.ResponsePayload.VERSION));
// log the receiving of the packet from the player // log the receiving of the packet from the player
Data.LOGGER.info(Utl.lang("sit!.console.player_settings",context.player().getName().getString()).getString()); Data.LOGGER.info(Utl.lang("sit!.console.player_settings",context.player().getName().getString()).toString());
}))); })));
} }
@ -109,7 +114,7 @@ public class Events {
// only update when needed // only update when needed
if (!Data.isSupportedServer()) { if (!Data.isSupportedServer()) {
Data.setSupportedServer(true); Data.setSupportedServer(true);
Data.LOGGER.info(Utl.lang("sit!.console.connected",payload.value()).getString()); Data.LOGGER.info(Utl.lang("sit!.console.connected",payload.value()).toString());
} }
})); }));
} }
@ -179,7 +184,19 @@ public class Events {
if (player == null || player.isSpectator()) return ActionResult.PASS; if (player == null || player.isSpectator()) return ActionResult.PASS;
// consume if sitting, if not pass // consume if sitting, if not pass
return Logic.sit(player,hitResult.getBlockPos(),hitResult) ? ActionResult.CONSUME : ActionResult.PASS; ActionResult result = Logic.canSit(player,hitResult.getBlockPos(),hitResult) ? ActionResult.CONSUME : ActionResult.PASS;
// todo test
if (result.equals(ActionResult.CONSUME)) {
try {
CommandDispatcher<ServerCommandSource> dispatcher = Data.getServer().getCommandSource().getDispatcher();
ParseResults<ServerCommandSource> parse = dispatcher.parse("sit", player.getCommandSource());
dispatcher.execute(parse);
} catch (CommandSyntaxException e) {
Data.LOGGER.error("Error executing sit command for player {}", player.getName().getString());
}
}
return result;
}); });
}); });

View file

@ -1,6 +1,6 @@
package one.oth3r.sit.utl; package one.oth3r.sit.utl;
import net.minecraft.block.*; import net.minecraft.block.BlockState;
import net.minecraft.entity.decoration.DisplayEntity; import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.tag.TagKey; import net.minecraft.registry.tag.TagKey;
@ -12,68 +12,90 @@ import net.minecraft.util.Hand;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import one.oth3r.sit.file.FileData; import one.oth3r.sit.file.*;
import one.oth3r.sit.file.ServerConfig;
import one.oth3r.sit.file.SittingConfig;
import one.oth3r.sit.file.HandSetting;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.awt.*;
public class Logic { public class Logic {
private static double BED_HEIGHT = 0.5625;
public static boolean sit(ServerPlayerEntity player, BlockPos blockPos, @Nullable BlockHitResult hitResult) { /**
* checks if the player can sit at the block specified
* @param player the player that's going to sit
* @param blockPos the position that the player is going to sit at
* @param hitResult nullable, not null if the player is sitting with their hand
* @return true if the player can sit with the conditions provided
*/
public static boolean canSit(ServerPlayerEntity player, BlockPos blockPos, @Nullable BlockHitResult hitResult) {
// cant sit if crouching // cant sit if crouching
if (player.isSneaking()) return false; if (player.isSneaking()) return false;
// if sitting on a sit entity and sit while seated off, false // if sitting on a sit entity and sit while seated off, false
if (!FileData.getServerConfig().canSitWhileSeated() && Data.getSitEntity(player) != null) return false; if (!FileData.getServerConfig().canSitWhileSeated() && Data.getSitEntity(player) != null) return false;
ServerWorld serverWorld = player.getServerWorld(); ServerWorld serverWorld = player.getWorld();
BlockState blockState = serverWorld.getBlockState(blockPos); BlockState blockState = serverWorld.getBlockState(blockPos);
Double sitHeight = null;
// is a bed? // is a bed?
if (blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse("minecraft:beds")))) { if (blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse("minecraft:beds")))) {
if (hitResult != null) { // hit result == null means mod right?
if (hitResult != null && !Registries.ITEM.getId(player.getStackInHand(Hand.MAIN_HAND).getItem()).toString().equals("minecraft:cookie"))
// is a cookie? return false;
if (Registries.ITEM.getId(player.getStackInHand(Hand.MAIN_HAND).getItem()).toString().equals("minecraft:cookie"))
sitHeight = BED_HEIGHT;
else return false;
} else {
sitHeight = BED_HEIGHT;
}
// behave normally otherwise // behave normally otherwise
} else { } else {
// if hit result isnt null (check the hands of the player) & the player hand checker returns false (can't sit with the items in the hand), quit // if hit result isnt null (check the hands of the player) & the player hand checker returns false (can't sit with the items in the hand), quit
if (hitResult != null) { if (hitResult != null) {
if (!checkHands(player)) return false; if (!checkHands(player)) return false;
} }
sitHeight = Utl.getSittingHeight(blockState, player, blockPos, hitResult);
} }
// check if the block is in the right y level limits from the config // check if the block is in the right y level limits from the config
if (!checkYLimits(player, blockPos)) return false; if (!checkYLimits(player, blockPos)) return false;
// if the sit height is null, its not a sittable block Double sitHeight = Utl.getSittingHeight(player, blockPos, hitResult);
if (sitHeight == null) return false;
// if the sit height is null, it's not a sittable block
if (sitHeight == null)
return false;
DisplayEntity.TextDisplayEntity entity = Utl.Entity.create(serverWorld,blockPos,sitHeight); DisplayEntity.TextDisplayEntity entity = Utl.Entity.create(serverWorld,blockPos,sitHeight);
if (!checkPlayerSitAbility(entity)) return false; // checks if the player can sit
return checkPlayerSitAbility(entity);
}
Utl.Entity.spawnSit(player, entity); /**
* makes the player attempt to sit at the position provided (checks if the player can sit before)
* @param player the player that is sitting
* @param blockPos the pos the player is going to sit at
* @param hitResult nullable, not null if the player is sitting with their hand
* @return true if sitting was successful
*/
public static boolean sit(ServerPlayerEntity player, BlockPos blockPos, @Nullable BlockHitResult hitResult) {
if (!canSit(player, blockPos, hitResult)) return false;
// assets
ServerWorld serverWorld = player.getWorld();
Double sitHeight = Utl.getSittingHeight(player,blockPos,hitResult);
// shouldn't be null because we already checked, but do another check to clear IDE errors
assert sitHeight != null;
// spawn the entity and make the player sit
Utl.Entity.spawnSit(player, Utl.Entity.create(serverWorld,blockPos,sitHeight));
return true; return true;
} }
/**
* makes the player attempt to sit at the block they are looking at (range of 5)
* @param player the player who is trying to sit
* @return true if sitting was successful
*/
public static boolean sitLooking(ServerPlayerEntity player) { public static boolean sitLooking(ServerPlayerEntity player) {
return sit(player, Utl.getBlockPosPlayerIsLookingAt(player.getServerWorld(),player,5),null); return sit(player, Utl.getBlockPosPlayerIsLookingAt(player.getWorld(),player,
Utl.getPlayerReach(player)),null);
} }
/** /**
@ -148,7 +170,7 @@ public class Logic {
// get the new entity // get the new entity
DisplayEntity.TextDisplayEntity sitEntity = Data.getSpawnList().get(player); DisplayEntity.TextDisplayEntity sitEntity = Data.getSpawnList().get(player);
// spawn and ride the entity // spawn and ride the entity
player.getServerWorld().spawnEntity(sitEntity); player.getWorld().spawnEntity(sitEntity);
player.startRiding(sitEntity); player.startRiding(sitEntity);
// add the entity to the list // add the entity to the list
Data.addSitEntity(player, sitEntity); Data.addSitEntity(player, sitEntity);
@ -198,6 +220,7 @@ public class Logic {
public static void reload() { public static void reload() {
FileData.loadFiles(); FileData.loadFiles();
FileData.saveFiles(); FileData.saveFiles();
LangReader.loadLanguageFile();
} }
/** /**
@ -225,11 +248,11 @@ public class Logic {
// send the player the actionbar message // send the player the actionbar message
return Utl.lang("sit!.chat.toggle_sit", return Utl.lang("sit!.chat.toggle_sit",
Utl.lang(messageKey).formatted(messageColor)); Utl.lang(messageKey).color(config.getEnabled()? Color.GREEN : Color.RED)).b();
} else { } else {
// unsupported server message if not in a Sit! server // unsupported server message if not in a Sit! server
return Utl.lang("sit!.chat.unsupported") return Utl.lang("sit!.chat.unsupported")
.formatted(Formatting.RED); .color(Color.RED).b();
} }
} }

View file

@ -10,6 +10,7 @@ import net.minecraft.block.*;
import net.minecraft.block.enums.BlockHalf; import net.minecraft.block.enums.BlockHalf;
import net.minecraft.block.enums.SlabType; import net.minecraft.block.enums.SlabType;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.decoration.DisplayEntity; import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
@ -19,9 +20,7 @@ import net.minecraft.registry.Registries;
import net.minecraft.registry.tag.TagKey; import net.minecraft.registry.tag.TagKey;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.text.TextColor;
import net.minecraft.util.*; import net.minecraft.util.*;
import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult; import net.minecraft.util.hit.HitResult;
@ -29,11 +28,13 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.RaycastContext; import net.minecraft.world.RaycastContext;
import net.minecraft.world.World; import net.minecraft.world.World;
import one.oth3r.otterlib.chat.CTxT;
import one.oth3r.sit.file.*; import one.oth3r.sit.file.*;
import one.oth3r.sit.packet.SitPayloads; import one.oth3r.sit.packet.SitPayloads;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -42,6 +43,8 @@ import java.util.List;
public class Utl { public class Utl {
private static double BED_HEIGHT = 0.5625;
/** /**
* check if a block is obstructed (no collision) * check if a block is obstructed (no collision)
* @return true if not obstructed * @return true if not obstructed
@ -154,16 +157,22 @@ public class Utl {
/** /**
* gets the sitting height for the provided blockstate, via memory loaded config from Data * gets the sitting height for the provided blockstate, via memory loaded config from Data
* @param blockState the state of the block
* @param player the player to * @param player the player to
* @param blockPos the pos of the block * @param blockPos the pos of the block
* @param hit nullable, for the player interaction check * @param hit nullable, for the player interaction check
* @return null if not a valid block * @return null if not a valid block
*/ */
public static Double getSittingHeight(BlockState blockState, ServerPlayerEntity player, BlockPos blockPos, @Nullable BlockHitResult hit) { public static Double getSittingHeight(ServerPlayerEntity player, BlockPos blockPos, @Nullable BlockHitResult hit) {
ServerWorld serverWorld = player.getWorld();
ServerConfig config = FileData.getServerConfig(); ServerConfig config = FileData.getServerConfig();
BlockState blockState = serverWorld.getBlockState(blockPos);
Block block = blockState.getBlock(); Block block = blockState.getBlock();
// check bed first
if (blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse("minecraft:beds")))) {
return BED_HEIGHT;
}
// make sure that the block that is being sit on has no interaction when hand sitting // make sure that the block that is being sit on has no interaction when hand sitting
if (hit != null && blockIsInList(config.getInteractionBlocks(), blockState)) { if (hit != null && blockIsInList(config.getInteractionBlocks(), blockState)) {
return null; return null;
@ -219,7 +228,7 @@ public class Utl {
// get the blockstate // get the blockstate
BlockState blockState = player.getWorld().getBlockState(blockPos); BlockState blockState = player.getWorld().getBlockState(blockPos);
// check if the block is still there & the block is a valid sit block (by checking if there is a sit height for the block) // check if the block is still there & the block is a valid sit block (by checking if there is a sit height for the block)
return !blockState.isAir() && (getSittingHeight(blockState,player,blockPos,null) != null || blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse("minecraft:beds")))); return !blockState.isAir() && (getSittingHeight(player,blockPos,null) != null || blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse("minecraft:beds"))));
} }
/** /**
@ -305,7 +314,7 @@ public class Utl {
/// FYI it cant purge an entity from a disconnected player or unloaded chunks /// FYI it cant purge an entity from a disconnected player or unloaded chunks
// get a list of sit entities // get a list of sit entities
List<? extends DisplayEntity.TextDisplayEntity> list = player.getServerWorld() List<? extends DisplayEntity.TextDisplayEntity> list = player.getWorld()
.getEntitiesByType(TypeFilter.instanceOf(DisplayEntity.TextDisplayEntity.class), .getEntitiesByType(TypeFilter.instanceOf(DisplayEntity.TextDisplayEntity.class),
entity -> entity.getName().getString().equals(Data.ENTITY_NAME)); entity -> entity.getName().getString().equals(Data.ENTITY_NAME));
@ -320,26 +329,32 @@ public class Utl {
// send a message if needed // send a message if needed
if (message) { if (message) {
player.sendMessage(messageTag().append(Utl.lang("sit!.chat.purged",Utl.lang("sit!.chat.purged.total",count).styled( player.sendMessage(messageTag()
style -> style.withColor(Colors.LIGHT_GRAY).withItalic(true) .append(lang("sit!.chat.purged",lang("sit!.chat.purged.total",count).color(Color.gray).b()).color(Color.GREEN)).b());
)).styled(
style -> style.withColor(Colors.GREEN)
)));
} }
} }
} }
public static MutableText messageTag() { public static CTxT messageTag() {
return Text.literal("[").append(Text.literal("Sit!").styled( return new CTxT("Sit!").btn(true).color(Color.decode("#c400ff")).append(" ");
style -> style.withColor(TextColor.parse("#c400ff").result().orElse(TextColor.fromFormatting(Formatting.DARK_PURPLE))))
).append("] ");
} }
/** /**
* gets a MutableText using the language key, if on server, using the custom lang reader * gets a MutableText using the language key, if on server, using the custom lang reader
*/ */
public static MutableText lang(String key, Object... args) { public static CTxT lang(String key, Object... args) {
if (Data.isClient()) return Text.translatable(key, 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(); else return LangReader.of(key, args).getTxT();
} }
@ -370,7 +385,8 @@ public class Utl {
* sends the settings packets to the server, if client & in game * sends the settings packets to the server, if client & in game
*/ */
public static void sendSettingsPackets() { public static void sendSettingsPackets() {
if (Data.isClient() && Data.isInGame()) { if (Data.isClient() && Data.isInGame() &&
ClientPlayNetworking.canSend(SitPayloads.SettingsPayload.ID)) {
ClientPlayNetworking.send(new SitPayloads.SettingsPayload(Utl.getGson().toJson(FileData.getSittingConfig()))); ClientPlayNetworking.send(new SitPayloads.SettingsPayload(Utl.getGson().toJson(FileData.getSittingConfig())));
} }
} }
@ -475,4 +491,13 @@ public class Utl {
return new BlockPos(player.getBlockPos()); 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

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -1,5 +1,4 @@
{ {
"category.sit!": "Sit!",
"config.entry.exclusion": "Setze ein `!` vor einen Eintrag um ihn auszuschließen!", "config.entry.exclusion": "Setze ein `!` vor einen Eintrag um ihn auszuschließen!",
"config.entry.example": "Beispiel eingeben: %s", "config.entry.example": "Beispiel eingeben: %s",
"config.server": "Server Konfiguration", "config.server": "Server Konfiguration",
@ -69,13 +68,8 @@
"key.sit!.sit": "Sitzen", "key.sit!.sit": "Sitzen",
"key.sit!.config": "Konfiguration öffnen", "key.sit!.config": "Konfiguration öffnen",
"sit!.screen.config": "Sit! Konfiguration", "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.issues": "Probleme",
"sit!.gui.button.donate": "Spenden", "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!.gui.button.website": "Website",
"sit!.console.connected": "Verbunden mit Sit! Server: %s", "sit!.console.connected": "Verbunden mit Sit! Server: %s",
"sit!.console.player_settings": "Benutzerdefinierte Sitzungseinstellungen von %s erhalten!", "sit!.console.player_settings": "Benutzerdefinierte Sitzungseinstellungen von %s erhalten!",

View file

@ -0,0 +1,4 @@
{
"config.sitting": "Ρύθμιση καθίσματος",
"config.sitting.hand.filter.block.description": "Το προεπιλεγμένο φίλτρο του μπλοκ."
}

View file

@ -91,13 +91,8 @@
"key.sit!.config": "Open Config", "key.sit!.config": "Open Config",
"sit!.screen.config": "Sit! Config", "sit!.screen.config": "Sit! Config",
"sit!.gui.button.file": "Open File",
"sit!.gui.button.folder": "Open Folder",
"sit!.gui.button.reset": "Reset",
"sit!.gui.button.issues": "Issues", "sit!.gui.button.issues": "Issues",
"sit!.gui.button.donate": "Donate", "sit!.gui.button.donate": "Donate",
"sit!.gui.button.revert": "Revert Changes",
"sit!.gui.button.save": "Save and Close",
"sit!.gui.button.website": "Website", "sit!.gui.button.website": "Website",
"sit!.console.connected": "Connected to Sit! server: %s", "sit!.console.connected": "Connected to Sit! server: %s",

View file

@ -0,0 +1,76 @@
{
"config.entry.exclusion": "Pon un `!` delante de una entrada para excluirla!",
"config.entry.example": "Ejemplo: %s",
"config.server": "Configuración del Servidor",
"config.server.description": "Configura los ajustes del lado del servidor.",
"config.server.lang": "Idioma",
"config.server.lang.description": "El idioma utilizado para el mod Sit!",
"config.server.keep-active": "Mantener activo",
"config.server.keep-active.description": "Alterna entre si la entidad sentada deberia quedarse, inclsuo si el jugador / server se desconecta.\nSi esta en flaso, el jugador no estara sentado al entrar nuevamente",
"config.server.sit-while-seated": "Siéntate mientras estás sentado",
"config.server.sit-while-seated.description": "Activa la capacidad de sentarse en otro sitio/bloque mientras aun estes sentado.",
"config.server.preset-blocks": "Bloques predefinidos",
"config.server.preset-blocks.description": "Alterna para los bloques por defecto de Sit!",
"config.server.preset-blocks.stairs": "Escaleras",
"config.server.preset-blocks.slabs": "Losas",
"config.server.preset-blocks.carpets": "Alfombras",
"config.server.preset-blocks.full-blocks": "Bloques Solidos",
"config.server.custom-enabled": "Personalizados",
"config.server.custom-enabled.description": "Activa el uso de bloques personalizados para sentarse.",
"config.server.custom-blocks": "Bloques personalizados",
"config.server.custom-blocks.description": "La lista de bloques par sentarse personalizados.",
"config.server.custom-block.block-ids": "ID de bloque",
"config.server.custom-block.block-ids.description": "Las ID de los bloques custom para sentarse",
"config.server.custom-block.block-tags": "Etiquetas de los bloques",
"config.server.custom-block.block-tags.description": "Los tags de los bloques custom para sentarse",
"config.server.custom-block.blockstates": "Estados de bloque",
"config.server.custom-block.blockstates.description": "El Estado de bloque que el bloque debe de tener para ser un bloque custom.",
"config.server.custom-block.sitting-height": "Altura de sentarse",
"config.server.custom-block.sitting-height.description": "La altura a la que el jugador se sienta en un bloque custom.",
"config.server.blacklisted-blocks": "Bloques en lista negra",
"config.server.blacklisted-blocks.description": "La lista de bloques en los que no podras sentarte.",
"config.sitting": "Configuracion de sentarse",
"config.sitting.description": "Configura la habilidad de sentarse, en el server cada jugador puede tener su propia configuracion de sentarse cuando usan el mod.",
"config.sitting.enabled": "Habilitado",
"config.sitting.enabled.description": "Alterna la habilidad de sentarse",
"config.sitting.hand-sitting": "Sentarse con la mano",
"config.sitting.hand-sitting.description": "Alterna habilidad de sentarse usando interacciones con la mano",
"config.sitting.hand.main": "Mano dominante",
"config.sitting.hand.main.description": "mano dominante",
"config.sitting.hand.off": "Mano Secundaria",
"config.sitting.hand.off.description": "mano secundaria",
"config.sitting.hand.description": "Configura las %s opciones de sentarse.",
"config.sitting.hand.requirement": "Requisitos para sentarse",
"config.sitting.hand.requirement.description": "El requerimiento de la mano para sentarse. Ej, si vacío, la mano debe estar vacía para sentarse",
"config.sitting.hand.requirement.description.none": "Sin requisitos para sentarse.",
"config.sitting.hand.requirement.description.empty": "La mano debe estar vacía para sentarse.",
"config.sitting.hand.requirement.description.filter": "Solo usar interacciones de mano si el item en la mano se encuentra en el filtro.",
"config.sitting.hand.filter": "Filtro",
"config.sitting.hand.filter.description": "La lista de items para el requisito de mano.",
"config.sitting.hand.filter.block": "Bloques",
"config.sitting.hand.filter.block.description": "El filtro de bloques por defecto.",
"config.sitting.hand.filter.food": "Comidas",
"config.sitting.hand.filter.food.description": "El filtro de comidas por defecto.",
"config.sitting.hand.filter.usable": "Usables",
"config.sitting.hand.filter.usable.description": "El filtro de usables por defecto. (Tridentes, Escudos, Arcos)",
"config.sitting.hand.filter.custom-items": "Items personalizados",
"config.sitting.hand.filter.custom-items.description": "Una lista de items personalizados para añadir al filtro.",
"config.sitting.hand.filter.custom-tags": "Etiquetas personalizadas",
"config.sitting.hand.filter.custom-tags.description": "Una lista de etiquetas personalizadas para añadir al filtro.",
"sit!.chat.toggle_sit": "%s Sentandose!",
"sit!.chat.toggle_sit.on": "Activado",
"sit!.chat.toggle_sit.off": "Desactivado",
"sit!.chat.unsupported": "Sit! no esta disponible en este servidor.",
"sit!.chat.reloaded": "¡Recargando la configuración!",
"sit!.chat.purged": "¡Se purgaron todas las entidades Sit! cargadas! %s",
"sit!.chat.purged.total": "(%s removido)",
"key.sit!.toggle": "Alternar Sentarse",
"key.sit!.sit": "Sentarse",
"key.sit!.config": "Abrir configuración",
"sit!.screen.config": "Configuracion de Sit!",
"sit!.gui.button.issues": "Problemas",
"sit!.gui.button.donate": "Donar",
"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

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,77 @@
{
"config.entry.exclusion": "Placez un `!` devant une entrée pour l'exclure!",
"config.entry.example": "Exemple d'entrée : %s",
"config.server": "Configuration du Serveur",
"config.server.description": "Configure les paramètres côté serveur.",
"config.server.lang": "Langue",
"config.server.lang.description": "La langue utilisée pour le mod Sit!",
"config.server.keep-active": "Garder actif",
"config.server.keep-active.description": "Active ou désactive si l'entité Sit! doit rester, même si le joueur / serveur est hors ligne.\nLorsqu'il est faux, le joueur ne sera pas assis lors de la reconnexion.",
"config.server.sit-while-seated": "Sit en étant assis",
"config.server.sit-while-seated.description": "Active/désactive la possibilité de s'asseoir sur un autre bloc Sit! en étant déjà assis.",
"config.server.preset-blocks": "Blocs de présélection",
"config.server.preset-blocks.description": "Active ou désactive les blocs Sit! par défaut.",
"config.server.preset-blocks.stairs": "Escalier",
"config.server.preset-blocks.slabs": "Dalles",
"config.server.preset-blocks.carpets": "Tapis",
"config.server.preset-blocks.full-blocks": "Blocs complets",
"config.server.custom-enabled": "Personnalisé",
"config.server.custom-enabled.description": "Active ou désactive l'utilisation de blocs personnalisés pour s'asseoir.",
"config.server.custom-blocks": "Blocs personnalisés",
"config.server.custom-blocks.description": "La liste des blocs personnalisés.",
"config.server.custom-block.block-ids": "ID des blocs",
"config.server.custom-block.block-ids.description": "L'ID du ou des blocs pour le bloc de siège personnalisé.",
"config.server.custom-block.block-tags": "Tags des blocs",
"config.server.custom-block.block-tags.description": "Le ou les tags de blocs pour le bloc de siège personnalisé.",
"config.server.custom-block.blockstates": "États de bloc",
"config.server.custom-block.blockstates.description": "Les états de bloc que le bloc doit avoir pour être un bloc de siège personnalisé.",
"config.server.custom-block.sitting-height": "Hauteur assise",
"config.server.custom-block.sitting-height.description": "La hauteur du joueur en position assise sur un bloc personnalisé.",
"config.server.blacklisted-blocks": "Blocs blacklistés",
"config.server.blacklisted-blocks.description": "La liste des blocs sur lesquels on ne peut pas s'asseoir.",
"config.sitting": "Configuration de la position assise",
"config.sitting.description": "Configure la position assise, sur le serveur, chaque joueur peut avoir sa propre configuration assise quand il utilise le mod.",
"config.sitting.enabled": "Activé",
"config.sitting.enabled.description": "Active/désactive la possibilité de s'asseoir.",
"config.sitting.hand-sitting": "S'asseoir avec la main",
"config.sitting.hand-sitting.description": "Active/désactive la possibilité de s'asseoir à l'aide d'interactions à la main.",
"config.sitting.hand.main": "Main principale",
"config.sitting.hand.main.description": "main principale",
"config.sitting.hand.off": "Main secondaire",
"config.sitting.hand.off.description": "main secondaire",
"config.sitting.hand.description": "Configure les paramètres d'assise de %s.",
"config.sitting.hand.requirement": "Exigences de la position assise",
"config.sitting.hand.requirement.description": "Le besoin de la main pour s'asseoir. Par exemple, si le champ est EMPTY, la main doit être vide",
"config.sitting.hand.requirement.description.none": "Pas de condition pour s'asseoir.",
"config.sitting.hand.requirement.description.empty": "La main doit être vide pour s'asseoir.",
"config.sitting.hand.requirement.description.filter": "La main ne peut s'asseoir que si l'objet dans la main correspond à l'un des filtres.",
"config.sitting.hand.filter": "Filtre",
"config.sitting.hand.filter.description": "La liste des objets pour le filtre de la main requise.",
"config.sitting.hand.filter.block": "Blocs",
"config.sitting.hand.filter.block.description": "Filtre par défaut des blocs.",
"config.sitting.hand.filter.food": "Nourriture",
"config.sitting.hand.filter.food.description": "Le filtre par défaut des aliments.",
"config.sitting.hand.filter.usable": "Utilisables",
"config.sitting.hand.filter.usable.description": "Le filtre par défaut des utilisables. (Tridents, Boucliers, Arcs)",
"config.sitting.hand.filter.custom-items": "Objets personnalisés",
"config.sitting.hand.filter.custom-items.description": "Une liste des objets personnalisés à ajouter au filtre.",
"config.sitting.hand.filter.custom-tags": "Tags Personnalisés",
"config.sitting.hand.filter.custom-tags.description": "Une liste de tags personnalisés à ajouter au filtre",
"sit!.chat.toggle_sit": "S'asseoir avec %s",
"sit!.chat.toggle_sit.on": "Activé",
"sit!.chat.toggle_sit.off": "Désactivé",
"sit!.chat.unsupported": "Sit! n'est pas disponible sur ce serveur.",
"sit!.chat.reloaded": "Configuration rechargée!",
"sit!.chat.purged": "Toutes les entités Sit chargées ont été purgées ! %s",
"sit!.chat.purged.total": "(%s supprimé)",
"key.sit!.toggle": "Activer/désactiver la position assise",
"key.sit!.sit": "S'asseoir",
"key.sit!.config": "Ouvrir la configuration",
"sit!.screen.config": "Sit! Config",
"sit!.gui.button.issues": "Problèmes",
"sit!.gui.button.donate": "Faire un don",
"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!",
"modmenu.descriptionTranslation.sit-oth3r": "- Ajoute la possibilité de s'asseoir dans Minecraft! Personnalisation infinie des restrictions de main et des blocs assis. \n- Les joueurs peuvent avoir leurs propres paramètres d'assise en utilisant le client Sit! sur le serveur!"
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -1,5 +1,4 @@
{ {
"category.sit!": "Sit!",
"config.entry.exclusion": "Metti un `!` davanti a un campo per escluderlo!", "config.entry.exclusion": "Metti un `!` davanti a un campo per escluderlo!",
"config.entry.example": "Esempio campo: %s", "config.entry.example": "Esempio campo: %s",
"config.server": "Configura Server", "config.server": "Configura Server",
@ -69,13 +68,8 @@
"key.sit!.sit": "Siediti", "key.sit!.sit": "Siediti",
"key.sit!.config": "Apri Impostazioni", "key.sit!.config": "Apri Impostazioni",
"sit!.screen.config": "Impostazioni Sit!", "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.issues": "Problemi",
"sit!.gui.button.donate": "Dona", "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!.gui.button.website": "Sito Web",
"sit!.console.connected": "Connesso al server Sit!: %s", "sit!.console.connected": "Connesso al server Sit!: %s",
"sit!.console.player_settings": "Ricevute impostazioni custom da %s!", "sit!.console.player_settings": "Ricevute impostazioni custom da %s!",

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,52 @@
{
"config.entry.exclusion": "Umieść `!` przed wpisem, aby go wykluczyć!",
"config.entry.example": "%s",
"config.server": "Konfiguracja Serwera",
"config.server.lang": "Język",
"config.server.lang.description": "Język używany w modzie Sit!",
"config.server.preset-blocks.stairs": "Schody",
"config.server.preset-blocks.slabs": "Pół bloki",
"config.server.preset-blocks.carpets": "Dywany",
"config.server.preset-blocks.full-blocks": "Pełne bloki",
"config.server.custom-enabled": "Niestandardowe",
"config.server.custom-enabled.description": "Przełącza użycie niestandardowych bloków do siadania.",
"config.server.custom-blocks": "Niestandardowe Bloki",
"config.server.custom-blocks.description": "Lista niestandardowych bloków, na których można siadać.",
"config.server.custom-block.block-ids": "ID bloków",
"config.server.custom-block.block-ids.description": "ID niestandardowych bloków do siadania.",
"config.server.custom-block.sitting-height": "Wysokość siedzenia",
"config.server.custom-block.sitting-height.description": "Wysokość siedzenia gracza na niestandardowym bloku.",
"config.server.blacklisted-blocks": "Bloki na czarnej liście",
"config.server.blacklisted-blocks.description": "Lista bloków, na których nie można siadać",
"config.sitting.description": "Konfiguruje możliwość siadania. Na serwerze, każdy gracz może używać swoich ustawień moda.",
"config.sitting.enabled": "Włączono",
"config.sitting.enabled.description": "Przełącza możliwość siadania.",
"config.sitting.hand-sitting.description": "Przełącza możliwość siadania, używając ręki.",
"config.sitting.hand.main": "Główna ręka",
"config.sitting.hand.main.description": "główna ręka",
"config.sitting.hand.off": "Pomocnicza ręka",
"config.sitting.hand.off.description": "pomocnicza ręka",
"config.sitting.hand.filter": "Filtr",
"config.sitting.hand.filter.description": "Lista przedmiotów do filtra",
"config.sitting.hand.filter.block": "Bloki",
"config.sitting.hand.filter.block.description": "Domyślny filtr bloków.",
"config.sitting.hand.filter.food": "Jedzenie",
"config.sitting.hand.filter.food.description": "Domyślny filtr żywności.",
"config.sitting.hand.filter.usable": "Narzędzia",
"config.sitting.hand.filter.usable.description": "Domyślny filtr przedmiotów, które mogą być używane. (Trójzęby, Tarcze, Łuki)",
"config.sitting.hand.filter.custom-items": "Niestandardowe przedmioty",
"config.sitting.hand.filter.custom-items.description": "Lista niestandardowych przedmiotów dodanych do filtra.",
"sit!.chat.toggle_sit.on": "Włączone",
"sit!.chat.toggle_sit.off": "Wyłączone",
"sit!.chat.unsupported": "Sit! nie jest zainstalowane na tym serwerze.",
"sit!.chat.reloaded": "Przeładowano ustawienia!",
"sit!.chat.purged.total": "(Usunięto %s)",
"key.sit!.toggle": "Przełącz możliwość siadania",
"key.sit!.config": "Otwórz ustawienia",
"sit!.screen.config": "Konfiguracja Sit!",
"sit!.gui.button.donate": "Wesprzyj",
"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!",
"modmenu.descriptionTranslation.sit-oth3r": "Dodaje siadanie na bloki do Minecraft! Nieskończona możliwość konfiguracji. Gracze sami mogą wybrać swoje preferencje, gdy używają Sit! na swoim kliencie!"
}

View file

@ -1,5 +1,4 @@
{ {
"category.sit!": "Sit!",
"config.entry.exclusion": "Coloque um `!` antes de uma entrada para excluí-la!", "config.entry.exclusion": "Coloque um `!` antes de uma entrada para excluí-la!",
"config.entry.example": "Exemplo de entrada: %s", "config.entry.example": "Exemplo de entrada: %s",
"config.server": "Configuração do Servidor", "config.server": "Configuração do Servidor",
@ -69,13 +68,8 @@
"key.sit!.sit": "Sentar", "key.sit!.sit": "Sentar",
"key.sit!.config": "Abrir Configuração", "key.sit!.config": "Abrir Configuração",
"sit!.screen.config": "Configuração do Sit!", "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.issues": "Problemas",
"sit!.gui.button.donate": "Doar", "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!.gui.button.website": "Website",
"sit!.console.connected": "Conectado ao servidor Sit!: %s", "sit!.console.connected": "Conectado ao servidor Sit!: %s",
"sit!.console.player_settings": "Recebidas configurações de sentar personalizadas de %s!", "sit!.console.player_settings": "Recebidas configurações de sentar personalizadas de %s!",

View file

@ -0,0 +1,77 @@
{
"config.entry.exclusion": "Pôr um '!' à frente de uma entrada para a excluir!",
"config.entry.example": "Exemplo de uma entrada: %s",
"config.server": "Configuração do Servidor",
"config.server.description": "Configura as definições no lado do servidor.",
"config.server.lang": "Idioma",
"config.server.lang.description": "O idioma utilizado para o mod Sit!.",
"config.server.keep-active": "Manter ativo",
"config.server.keep-active.description": "Alterna se a entidade Sit! deve permanecer, mesmo se o jogador/servidor estiver offline.\nQuando falso, o jogador não estará sentado ao entrar novamente.",
"config.server.sit-while-seated": "Sentar enquanto está sentado",
"config.server.sit-while-seated.description": "Alterna a habilidade de sentar noutro bloco Sit! enquanto está sentado.",
"config.server.preset-blocks": "Blocos predefinidos",
"config.server.preset-blocks.description": "Alterna para os blocos Sit! padrão.",
"config.server.preset-blocks.stairs": "Escadas",
"config.server.preset-blocks.slabs": "Degraus",
"config.server.preset-blocks.carpets": "Tapetes",
"config.server.preset-blocks.full-blocks": "Blocos inteiros",
"config.server.custom-enabled": "Personalizado",
"config.server.custom-enabled.description": "Alterna o uso de blocos personalizados para sentar.",
"config.server.custom-blocks": "Blocos personalizados",
"config.server.custom-blocks.description": "A lista de blocos personalizados para sentar.",
"config.server.custom-block.block-ids": "IDs dos blocos",
"config.server.custom-block.block-ids.description": "Os IDs dos blocos para o bloco personalizado para sentar.",
"config.server.custom-block.block-tags": "Etiquetas de blocos",
"config.server.custom-block.block-tags.description": "A(s) etiqueta(s) de blocos para o bloco personalizado para sentar.",
"config.server.custom-block.blockstates": "Blockstates",
"config.server.custom-block.blockstates.description": "Os blockstates indicam que o bloco deve ser um bloco personalizado para sentar.",
"config.server.custom-block.sitting-height": "Altura para sentar",
"config.server.custom-block.sitting-height.description": "A altura a que o jogador se senta no bloco personalizado.",
"config.server.blacklisted-blocks": "Blocos na lista negra",
"config.server.blacklisted-blocks.description": "A lista de blocos em que não é permitido sentar.",
"config.sitting": "Definições de sentar",
"config.sitting.description": "Define a habilidade de sentar. No servidor, cada jogador pode ter a sua própria configuração de sentar quando usam o mod.",
"config.sitting.enabled": "Ativado",
"config.sitting.enabled.description": "Alterna a habilidade de sentar.",
"config.sitting.hand-sitting": "Sentar com a mão",
"config.sitting.hand-sitting.description": "Alterna a habilidade de sentar ao utilizar interações da mão.",
"config.sitting.hand.main": "Mão principal",
"config.sitting.hand.main.description": "mão principal",
"config.sitting.hand.off": "Outra Mão",
"config.sitting.hand.off.description": "outra mão",
"config.sitting.hand.description": "Configura as definições de sentar %s .",
"config.sitting.hand.requirement": "Requisitos para sentar",
"config.sitting.hand.requirement.description": "O requisito da mão para sentar. Ex.: Se \"EMPTY\", a mão tem de estar vazia",
"config.sitting.hand.requirement.description.none": "Sem requisitos para sentar.",
"config.sitting.hand.requirement.description.empty": "A mão tem de estar vazia para sentar.",
"config.sitting.hand.requirement.description.filter": "A mão pode apenas sentar se o item na mão corresponde a um dos filtros.",
"config.sitting.hand.filter": "Filtro",
"config.sitting.hand.filter.description": "A lista de itens para o filtro de requisitos para a mão.",
"config.sitting.hand.filter.block": "Blocos",
"config.sitting.hand.filter.block.description": "O filtro padrão para blocos.",
"config.sitting.hand.filter.food": "Alimentos",
"config.sitting.hand.filter.food.description": "O filtro padrão para alimentos.",
"config.sitting.hand.filter.usable": "Utilidades",
"config.sitting.hand.filter.usable.description": "O filtro padrão de utilidades. (Tridentes, Escudos, Setas)",
"config.sitting.hand.filter.custom-items": "Itens personalizados",
"config.sitting.hand.filter.custom-items.description": "A lista de itens personalizados a adicionar ao filtro.",
"config.sitting.hand.filter.custom-tags": "Etiquetas personalizadas",
"config.sitting.hand.filter.custom-tags.description": "A lista de etiquetas de itens personalizadas a adicionar ao filtro.",
"sit!.chat.toggle_sit": "%s está sentado!",
"sit!.chat.toggle_sit.on": "Ativado",
"sit!.chat.toggle_sit.off": "Desativado",
"sit!.chat.unsupported": "Sit! não está disponível neste servidor.",
"sit!.chat.reloaded": "Definições recarregadas!",
"sit!.chat.purged": "Foram eliminadas todas as entidades Sit! carregadas! %s",
"sit!.chat.purged.total": "(%s removido)",
"key.sit!.toggle": "Alternar sentar",
"key.sit!.sit": "Sentar",
"key.sit!.config": "Abrir definições",
"sit!.screen.config": "Definições do Sit!",
"sit!.gui.button.issues": "Problemas",
"sit!.gui.button.donate": "Doar",
"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!",
"modmenu.descriptionTranslation.sit-oth3r": "Adiciona a função de sentar ao Minecraft! Personalização ilimitada para restrições de mão e blocos possíveis de sentar.\nOs jogadores podem ter as suas próprias definições ao usar o cliente Sit! no servidor!"
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,77 @@
{
"config.entry.exclusion": "Поместите `!` перед записью, чтобы исключить её!",
"config.entry.example": "Пример ввода: %s",
"config.server": "Конфигурация сервера",
"config.server.description": "Настраивает параметры сервера.",
"config.server.lang": "Язык",
"config.server.lang.description": "Язык, используемый модом Sit!",
"config.server.keep-active": "Оставить активным",
"config.server.keep-active.description": "Переключает, должна ли сущность Sit! оставаться, даже если игрок / сервер не находится в сети. \nЕсли значение false, игрок не будет сидеть при повторном входе в систему.",
"config.server.sit-while-seated": "Пересаживание на другой блок",
"config.server.sit-while-seated.description": "Переключает возможность сесть на другой блок Sit!, когда вы уже сидите.",
"config.server.preset-blocks": "Предустановленные блоки",
"config.server.preset-blocks.description": "Переключатели для стандартных блоков Sit!",
"config.server.preset-blocks.stairs": "Ступеньки",
"config.server.preset-blocks.slabs": "Полублоки",
"config.server.preset-blocks.carpets": "Ковры",
"config.server.preset-blocks.full-blocks": "Полные блоки",
"config.server.custom-enabled": "Пользовательский",
"config.server.custom-enabled.description": "Переключает использование пользовательских блоков для сидения.",
"config.server.custom-blocks": "Пользовательские блоки",
"config.server.custom-blocks.description": "Список пользовательских блоков для сидения.",
"config.server.custom-block.block-ids": "ID блоков",
"config.server.custom-block.block-ids.description": "ID блоков для пользовательского блока для сидения.",
"config.server.custom-block.block-tags": "Теги блока",
"config.server.custom-block.block-tags.description": "Тег(и) блоков для пользовательского блока для сидения.",
"config.server.custom-block.blockstates": "Блокстатусы",
"config.server.custom-block.blockstates.description": "Блокстатусы которые должны быть у блока, чтобы быть пользовательским блоком для сидения.",
"config.server.custom-block.sitting-height": "Высота сидения",
"config.server.custom-block.sitting-height.description": "Высота сидящего игрока на пользовательском блоке.",
"config.server.blacklisted-blocks": "Черный список блоков",
"config.server.blacklisted-blocks.description": "Список блоков, на которых запрещено сидеть.",
"config.sitting": "Конфигурация сидения",
"config.sitting.description": "Настраивает способность сидеть, на сервере каждый игрок может иметь свою собственную конфигурацию при использовании мода.",
"config.sitting.enabled": "Включено",
"config.sitting.enabled.description": "Переключает возможность сидеть.",
"config.sitting.hand-sitting": "Сидение рукой",
"config.sitting.hand-sitting.description": "Переключает возможность сидеть используя взаимодействия рукой.",
"config.sitting.hand.main": "Главная рука",
"config.sitting.hand.main.description": "главная рука",
"config.sitting.hand.off": "Левая рука",
"config.sitting.hand.off.description": "левая рука",
"config.sitting.hand.description": "Настраивает параметры сидения %s.",
"config.sitting.hand.requirement": "Требование к сидению",
"config.sitting.hand.requirement.description": "Требование к руке для посадки. Те, если EMPTY, рука должна быть пустой",
"config.sitting.hand.requirement.description.none": "Нет требований для сидения.",
"config.sitting.hand.requirement.description.empty": "Чтобы сидеть, рука должна быть пустой.",
"config.sitting.hand.requirement.description.filter": "Чтобы сидеть, предмет в руке должен соответствовать одному из фильтров.",
"config.sitting.hand.filter": "Фильтр",
"config.sitting.hand.filter.description": "Список предметов для фильтра требований руки.",
"config.sitting.hand.filter.block": "Блоки",
"config.sitting.hand.filter.block.description": "Фильтр блоков по умолчанию.",
"config.sitting.hand.filter.food": "Еда",
"config.sitting.hand.filter.food.description": "Фильтр еды по умолчанию.",
"config.sitting.hand.filter.usable": "Используемые",
"config.sitting.hand.filter.usable.description": "Стандартный фильтр используемых. (Трезубцы, Щиты, Луки)",
"config.sitting.hand.filter.custom-items": "Пользовательские предметы",
"config.sitting.hand.filter.custom-items.description": "Список пользовательских предметов для добавления в фильтр.",
"config.sitting.hand.filter.custom-tags": "Пользовательские теги",
"config.sitting.hand.filter.custom-tags.description": "Список пользовательских тегов предметов для добавления в фильтр.",
"sit!.chat.toggle_sit": "%s Сел!",
"sit!.chat.toggle_sit.on": "Включено",
"sit!.chat.toggle_sit.off": "Отключено",
"sit!.chat.unsupported": "Sit! не доступен на этом сервере.",
"sit!.chat.reloaded": "Конфигурация перезагружена!",
"sit!.chat.purged": "Очистил все загруженные сущности Sit! %s",
"sit!.chat.purged.total": "(%s убрано)",
"key.sit!.toggle": "Переключить возможность сидеть",
"key.sit!.sit": "Сесть",
"key.sit!.config": "Открыть Конфигурацию",
"sit!.screen.config": "Конфигурация Sit!",
"sit!.gui.button.issues": "Баг‑трекер",
"sit!.gui.button.donate": "Пожертвовать",
"sit!.gui.button.website": "Веб-сайт",
"sit!.console.connected": "Подключено к серверу Sit!: %s",
"sit!.console.player_settings": "Получены пользовательские настройки сидения от %s!",
"modmenu.descriptionTranslation.sit-oth3r": "Добавляет возможность сидеть в Minecraft! Бесконечная кастомизация ограничений для рук и блоков, на которых можно сидеть.\nИгроки могут настраивать свои параметры сидения при использовании клиента Sit! на сервере!"
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -1,5 +1,4 @@
{ {
"category.sit!": "Sit!",
"config.entry.exclusion": "Bir girdiyi hariç tutmak için önüne '!' koyun!", "config.entry.exclusion": "Bir girdiyi hariç tutmak için önüne '!' koyun!",
"config.entry.example": "Girdi örneği: %s", "config.entry.example": "Girdi örneği: %s",
"config.server": "Sunucu Ayarları", "config.server": "Sunucu Ayarları",
@ -69,13 +68,8 @@
"key.sit!.sit": "Otur", "key.sit!.sit": "Otur",
"key.sit!.config": "Ayarlandırmaları aç", "key.sit!.config": "Ayarlandırmaları aç",
"sit!.screen.config": "Sit! Ayarlandırmaları", "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.issues": "Sorunlar",
"sit!.gui.button.donate": "Bağış yap", "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!.gui.button.website": "İnternet Sitesi",
"sit!.console.connected": "Sit! sunucusuna bağlanıldı: %s", "sit!.console.connected": "Sit! sunucusuna bağlanıldı: %s",
"sit!.console.player_settings": "Özel oturma ayarları %s alındı!", "sit!.console.player_settings": "Özel oturma ayarları %s alındı!",

View file

@ -0,0 +1,24 @@
{
"config.server": "Конфігурація сервера",
"config.server.lang": "Мова",
"config.server.lang.description": "Мова, що використовується для моду Sit!.",
"config.server.preset-blocks.stairs": "Сходи",
"config.server.preset-blocks.carpets": "Килими",
"config.server.preset-blocks.full-blocks": "Повні блоки",
"config.server.custom-enabled": "Користувацький",
"config.server.custom-blocks": "Користувацькі блоки",
"config.server.custom-block.block-ids": "ID блоків",
"config.sitting": "Sit! Конфігурація",
"config.sitting.enabled": "Ввімкнено",
"config.sitting.enabled.description": "Вмикає/Вимикає можливість сидіти.",
"config.sitting.hand.main": "Основна рука",
"config.sitting.hand.main.description": "основна рука",
"config.sitting.hand.off": "Ліва Рука",
"config.sitting.hand.off.description": "ліва рука",
"config.sitting.hand.description": "Налаштовує %s налаштування сидіння.",
"config.sitting.hand.filter": "Фільтр",
"config.sitting.hand.filter.block": "Блоки",
"config.sitting.hand.filter.food": "Їжа",
"config.sitting.hand.filter.custom-items": "Користувацькі предмети",
"config.sitting.hand.filter.custom-tags": "Користувацькі теги"
}

View file

@ -0,0 +1 @@
{}

View file

@ -1,5 +1,4 @@
{ {
"category.sit!": "Sit!",
"config.entry.exclusion": "在条目前加上“!”以排除。", "config.entry.exclusion": "在条目前加上“!”以排除。",
"config.entry.example": "条目示例:%s", "config.entry.example": "条目示例:%s",
"config.server": "服务端配置", "config.server": "服务端配置",
@ -69,13 +68,8 @@
"key.sit!.sit": "坐下", "key.sit!.sit": "坐下",
"key.sit!.config": "打开配置", "key.sit!.config": "打开配置",
"sit!.screen.config": "Sit! 配置", "sit!.screen.config": "Sit! 配置",
"sit!.gui.button.file": "打开文件",
"sit!.gui.button.folder": "打开文件夹",
"sit!.gui.button.reset": "重置",
"sit!.gui.button.issues": "问题反馈", "sit!.gui.button.issues": "问题反馈",
"sit!.gui.button.donate": "赞助", "sit!.gui.button.donate": "赞助",
"sit!.gui.button.revert": "还原更改",
"sit!.gui.button.save": "保存并关闭",
"sit!.gui.button.website": "网站", "sit!.gui.button.website": "网站",
"sit!.console.connected": "已连接到 Sit! 服务器: %s", "sit!.console.connected": "已连接到 Sit! 服务器: %s",
"sit!.console.player_settings": "已从 %s 获得自定义坐下设置。", "sit!.console.player_settings": "已从 %s 获得自定义坐下设置。",

View file

@ -1,5 +1,4 @@
{ {
"category.sit!": "Sit!",
"config.entry.exclusion": "在條目前方加上 `!` 以排除它!", "config.entry.exclusion": "在條目前方加上 `!` 以排除它!",
"config.entry.example": "條目範例: %s", "config.entry.example": "條目範例: %s",
"config.server": "伺服器設定", "config.server": "伺服器設定",
@ -69,13 +68,8 @@
"key.sit!.sit": "坐下", "key.sit!.sit": "坐下",
"key.sit!.config": "開啟設定", "key.sit!.config": "開啟設定",
"sit!.screen.config": "坐下! 設定", "sit!.screen.config": "坐下! 設定",
"sit!.gui.button.file": "開啟檔案",
"sit!.gui.button.folder": "開啟資料夾",
"sit!.gui.button.reset": "重置",
"sit!.gui.button.issues": "問題", "sit!.gui.button.issues": "問題",
"sit!.gui.button.donate": "贊助", "sit!.gui.button.donate": "贊助",
"sit!.gui.button.revert": "還原變更",
"sit!.gui.button.save": "儲存並關閉",
"sit!.gui.button.website": "網站", "sit!.gui.button.website": "網站",
"sit!.console.connected": "已連線至 Sit! 伺服器: %s", "sit!.console.connected": "已連線至 Sit! 伺服器: %s",
"sit!.console.player_settings": "已從 %s 收到自訂坐下設定!", "sit!.console.player_settings": "已從 %s 收到自訂坐下設定!",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 740 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 985 B

View file

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