Compare commits

...
Sign in to create a new pull request.

81 commits

Author SHA1 Message Date
35e6435417 allow sitting on the dried ghast because why not 2025-06-17 20:00:36 +02:00
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
f77e3db29a merge y offset fix from upstream 2025-04-10 10:17:41 +02:00
Oth3r
884a3f639b v1.2.3.1 2025-04-08 14:07:05 -05:00
Oth3r
1fc549c51e fix sitting level being off 2025-04-08 14:03:46 -05:00
Oth3r
85732506a2 bump dependencies 2025-04-08 14:02:09 -05:00
042b089712 allow disabling of y limit (default disabled lol) 2025-04-04 11:55:54 +02:00
2f18f285ca merge bed changes into 1.21.5 2025-04-04 11:33:08 +02:00
Oth3r
0d90b1b85d use the minecraft versions var 2025-03-25 12:17:57 -05:00
Oth3r
12573bbd88 1.21.5 port 2025-03-25 12:16:03 -05:00
Oth3r
36602a444b add missing max mc version 2025-03-25 12:13:17 -05:00
Oth3r
7b8cefb1c5 remove unused imports 2025-03-25 12:13:02 -05:00
Oth3r
78c6894135 1.20.5 port 2025-03-25 12:06:10 -05:00
Oth3r
83fda90948 add minecraft_versions 2025-03-25 12:00:44 -05:00
Oth3r
3d89222840 add max minecraft version 2025-03-25 12:00:04 -05:00
Oth3r
284930b1b6 update checkPlayerSitAbility() with the entity Y-adjustment in mind 2025-03-14 14:27:05 -05:00
Oth3r
242f107ffb real fix for #17 2025-03-14 14:10:12 -05:00
Oth3r
7459d832c7 update loom and gradle statements 2025-03-13 17:49:12 -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
Oth3r
1fa208013f v1.2.3 changelog 2025-03-09 15:01:33 -05:00
Oth3r
44183128a5 v1.2.3 2025-03-09 14:57:43 -05:00
Oth3r
248add0bc4 fixes #17 2025-03-09 14:55:48 -05:00
Oth3r
39fc860cce changelog 2025-02-14 11:59:13 -06:00
Oth3r
f983763a70 v1.2.2 2025-02-14 11:48:53 -06:00
Oth3r
6fd3a8bd29 update dependencies 2025-02-14 11:45:38 -06:00
Oth3r
b1702c9beb fix sit toggle messages not showing correctly 2025-02-14 11:41:31 -06:00
Oth3r
dbee32a5e9 update localization 2025-02-14 11:41:15 -06:00
Oth3r
e76629af32 use player y instead of player eye y 2025-02-13 16:01:33 -06:00
Oth3r
e8ac5722ea sitting-eye-y-bounds -> height-difference-limit 2025-02-13 09:50:23 -06:00
Oth3r
04d246a5bf new y sitting limiter - #16 2025-02-11 14:51:32 -06:00
Oth3r
b46e10e835 copy constructors 2025-02-11 14:51:17 -06:00
69 changed files with 1454 additions and 695 deletions

View file

@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Please fill out the sections below to help identify and fix the bug
Please fill out the sections below to help identify and fix the bug.
- type: textarea
id: description
attributes:

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!
[![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)
<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/https://discord.gg/AVSTHCAUvn?style=flat)](https://www.oth3r.one/discord)
[![modrinth](https://img.shields.io/modrinth/dt/sit!?label=Modrinth&logo=modrinth)](https://modrinth.com/mod/sit!) [![curseforge](https://cf.way2muchnoise.eu/892424.svg)](https://www.curseforge.com/minecraft/mc-mods/Sit1)
**Sit!** is a minecraft mod that adds sitting in vanilla minecraft.
Sit on **stairs**, **slabs**, **carpets** by default, and sit on everything else using the config!
You can also customize hand restrictions to stop accidentally sitting down!
The mod also has full Geyser support! Enjoy sitting with everyone, weather they are on Bedrock or Java!
### **Sit!** is a vanilla+ mod that adds sitting in minecraft.
* Sit on **stairs**, **slabs**, **carpets** by default, and sit on everything else by tweaking the config!
* You can also customize **hand restrictions** to stop accidentally sitting down!
* The mod also has full **Geyser** support! Enjoy sitting with everyone, whether they are on Bedrock or Java!
* If Sit! clients join a Sit! server they can use **their own hand settings** to sit.
### Where to install?
**Sit!** works on the server (singleplayer included), also with support for clients that join in to use their own settings to sit.
**Sit!** works on the server, without the players needing to install the mod *(singleplayer included!)*.
\
[Fabric API](https://modrinth.com/mod/fabric-api) and [OtterLib](https://modrinth.com/mod/otterlib) is required to for the mod to load.
## Help localize Sit! on [Crowdin](https://crowdin.com/project/oth3r-sit)!
![overview](https://github.com/Oth3r/Sit/blob/master/media/overview.gif?raw=true)
### Help localize Sit! on [Crowdin](https://crowdin.com/project/oth3r-sit)!
Sit! is currently in English, Traditional Chinese, Italian, Brazilian Portuguese, and Turkish! Help expand this list via Crowdin so reach more people!
## Check out my other Projects!
[![Caligo badge](https://github.com/Oth3r/Caligo/blob/master/media/promo_badge.png?raw=true)](https://modrinth.com/mod/caligo)
[![DirectionHUD badge](https://github.com/Oth3r/DirectionHUD/blob/master/media/mod-badge.png?raw=true)](https://modrinth.com/mod/directionhud)
[![DirectionHUD Spigot badge](https://github.com/Oth3r/DirectionHUD/blob/master/media/plugin-badge.png?raw=true)](https://modrinth.com/plugin/directionhud-plugin)
<a href="https://modrinth.com/mod/caligo">
<img src="https://github.com/Oth3r/Caligo/blob/master/media/promo_badge.png?raw=true" alt="Caligo badge"
style="margin-right: 5px;">
</a>
<a href="https://modrinth.com/mod/directionhud">
<img src="https://github.com/Oth3r/DirectionHUD/blob/master/media/mod-badge.png?raw=true" alt="Directionhud badge"
style="margin-right: 5px;">
</a>
<a href="https://modrinth.com/mod/more-heart-types">
<img src="https://github.com/Oth3r/MoreHeartTypes/blob/master/media/Badge.png?raw=true" alt="More Heart Types badge"
style="">
</a>
# Features
### Hand Restrictions
### 🤚 Hand Restrictions
Don't want to accidentally sit down? Set custom restrictions for each hand in the config!
\
Use **player unique** hand restrictions when connecting to a `Sit!` server on a `Sit!` Client!
* Per player hand restrictions when connecting to a `Sit!` server on a `Sit!` Client!
<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
Want to sit on _**EVERY**_ block? With the config you can add more options to sit on! Custom block states are also supported.
<img src="https://github.com/Oth3r/oth3r.github.io/blob/main/mod_data/Sit!/media/desc/custom_blocks.gif?raw=true" width="100%" style="margin-bottom: 10px; max-width:600px;"
alt="players sitting on a vast range of blocks">
![custom blocks](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
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!
<img src="https://github.com/Oth3r/oth3r.github.io/blob/main/mod_data/Sit!/media/desc/keybinds.gif?raw=true" width="100%" style="margin-bottom: 10px; max-width:600px;"
alt="setting keybinds for the sit mod, and sitting by using them">
![config](https://github.com/Oth3r/Sit/blob/master/media/config.gif?raw=true)
![custom blocks config](https://github.com/Oth3r/Sit/blob/master/media/custom-blocks-config.png?raw=true)
### 📃 Customizable Config
Don't like the default settings? Go wild in the config for yourself or your players!
<img src="https://github.com/Oth3r/oth3r.github.io/blob/main/mod_data/Sit!/media/desc/config.gif?raw=true" width="100%" style="margin-bottom: 10px; max-width:600px;"
alt="the Sit! config wiki page">
## Future Goals
* Forge Port (probably NeoForge 1.21)
* Custom dismounting logic
* better config (coming soon!)
* keybindings (next update)
* NeoForge Port
* Full config via [OtterLib](https://modrinth.com/mod/otterlib)

View file

@ -1,8 +1,7 @@
plugins {
id 'fabric-loom' version '1.8-SNAPSHOT'
id 'fabric-loom' version "1.10-SNAPSHOT"
id 'maven-publish'
id 'com.modrinth.minotaur' version '2.+'
id 'net.darkhax.curseforgegradle' version '1.1.+'
id "me.modmuss50.mod-publish-plugin" version "0.8.4"
id 'co.uzzu.dotenv.gradle' version '4.0.0'
}
@ -14,8 +13,9 @@ base {
}
repositories {
maven { url "https://maven.terraformersmc.com/releases/" }
maven { url "https://maven.isxander.dev/releases" }
mavenLocal()
maven { url = "https://maven.terraformersmc.com/releases/" }
maven { url = "https://maven.isxander.dev/releases" }
}
loom {
@ -30,15 +30,20 @@ dependencies {
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
modImplementation "one.oth3r:otterlib:${project.otterlib_version}"
}
processResources {
filteringCharset "UTF-8"
filteringCharset = "UTF-8"
var replaceProperties = [
version : project.version,
minecraft_version : minecraft_version,
min_minecraft_version : min_minecraft_version,
max_minecraft_version : max_minecraft_version,
otterlib_version : otterlib_version,
otterlib_max_version : otterlib_max_version,
loader_version : loader_version
]
@ -85,33 +90,35 @@ publishing {
}
}
import com.modrinth.minotaur.dependencies.ModDependency
modrinth {
token = env.fetchOrNull('MODRINTH')
projectId = 'EsYqsGV4'
versionNumber = project.mod_version
versionName = "v${project.mod_version} [Fabric]"
versionType = "release"
uploadFile = remapJar
gameVersions = [project.minecraft_version]
loaders = ['fabric', 'quilt']
dependencies = [
new ModDependency('P7dR8mSH', 'required'),
new ModDependency('mOgUt4GM', 'optional')
]
publishMods {
changelog = file('changelog.md').text
}
type = STABLE
import net.darkhax.curseforgegradle.TaskPublishCurseForge
file = remapJar.archiveFile
modLoaders.add("fabric")
modLoaders.add("quilt")
tasks.register('publishCurseForge', TaskPublishCurseForge) {
apiToken = env.fetchOrNull('CURSEFORGE')
version = mod_version
displayName = "v${mod_version} [Fabric]"
def mainFile = upload(892424, remapJar)
mainFile.changelog = file('changelog.md')
mainFile.displayName = "v${project.mod_version} [Fabric]"
mainFile.addModLoader("fabric", 'quilt')
mainFile.releaseType = "release"
mainFile.addEnvironment("client", "server")
curseforge {
accessToken = env.fetchOrNull('CURSEFORGE')
projectId = "892424"
projectSlug = "sit1"
minecraftVersions.addAll(minecraft_versions.split(",").toList())
requires("fabric-api", "otterlib")
announcementTitle = "Download from CurseForge"
}
modrinth {
accessToken = env.fetchOrNull('MODRINTH')
projectId = "EsYqsGV4"
minecraftVersions.addAll(minecraft_versions.split(",").toList())
requires("fabric-api", "otterlib")
announcementTitle = "Download from Modrinth"
}
}

View file

@ -1,9 +1,18 @@
# v1.2.1
Quick bugfix update. :)
### block interaction checker
now it actually works (based on config sadly)
* added `interaction-blocks` to the server config, any block added to this list will block sitting with the hand
### other changes
* added refreshes to the config files on startup and reload to write missing parts to disk
* bumped the `server-config.json` version
* fixed `usable` hand filter not working
# v1.2.4.3
* added a max OtterLib version as the beta will have breaking changes between major versions
# v1.2.4.2
* fixed language file not loading (reverted uppercase locales)
* fixed block checking having a hardcoded player reach - now uses player reach (1.20.6+)
* fixed block and item tag check logic for cases with only not(!) tags
# v1.2.4.1
* removed unused assets
* enabled file logging for easier debugging
# v1.2.4.0
Small changelog but big update!
\
Switching to OtterLib will allow for a simplified main mod and lead to more unified mod development across my projects! Download OtterLib today: [Link](https://modrinth.com/mod/otterlib)
* make sitting via hand execute the `/sit` command, to allow for universal sitting permission control
* switch to using OtterLib for file management, config screen management, and more to come

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,16 +4,21 @@ org.gradle.parallel=true
# Fabric Properties
# check these on https://fabricmc.net/develop
min_minecraft_version=1.21.4
minecraft_version=1.21.4
yarn_mappings=1.21.4+build.1
loader_version=0.16.9
min_minecraft_version=1.21.6
max_minecraft_version=1.21.6
minecraft_versions=1.21.6
minecraft_version=1.21.6
yarn_mappings=1.21.6+build.1
loader_version=0.16.14
# Mod Properties
mod_version=1.2.1+1.21.4
mod_version=1.2.4.3+1.21.6
maven_group=one.oth3r
file_name=sit!
# Dependencies
fabric_version=0.110.5+1.21.4
modmenu_version=12.0.0-beta.1
fabric_version=0.127.0+1.21.6
modmenu_version=15.0.0-beta.1
otterlib_version=0.1.2.1+1.21.6-fabric
otterlib_max_version=0.2.0.0+1.21.6-fabric

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;
import net.fabricmc.api.ClientModInitializer;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.Identifier;
import one.oth3r.otterlib.client.screen.ConfigScreen;
import one.oth3r.otterlib.client.screen.utl.CustomImage;
import one.oth3r.otterlib.client.screen.utl.SimpleButton;
import one.oth3r.sit.file.FileData;
import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Events;
import one.oth3r.sit.utl.Utl;
import java.net.URI;
import java.util.List;
public class SitClient implements ClientModInitializer {
@ -12,5 +22,18 @@ public class SitClient implements ClientModInitializer {
Events.registerClient();
}
public static Screen getConfigScreen(Screen parent) {
return new ConfigScreen(parent, Utl.lang("sit!.screen.config"),
new CustomImage(Identifier.of(Data.MOD_ID, "textures/gui/banner.png"),128, 72),
List.of(
SimpleButton.Templates.fileEditor(Utl.lang("config.server"), FileData.getServerConfig(), new CustomImage(Identifier.of(Data.MOD_ID, "server_button"),246,26)).build(),
SimpleButton.Templates.fileEditor(Utl.lang("config.sitting"), FileData.getSittingConfig(), new CustomImage(Identifier.of(Data.MOD_ID, "sitting_button"), 246, 26)).build()
),
List.of(
SimpleButton.Templates.warning(Utl.lang("sit!.gui.button.issues")).openLink("https://github.com/Oth3r/Sit/issues").build(),
new SimpleButton.Builder(Utl.lang("sit!.gui.button.website")).openLink("https://modrinth.com/mod/sit!").build(),
SimpleButton.Templates.done(Utl.lang("gui.done")).build(),
SimpleButton.Templates.donate(Utl.lang("sit!.gui.button.donate")).openLink(URI.create("https://ko-fi.com/oth3r")).build()
));
}
}

View file

@ -14,6 +14,7 @@ import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Logic;
import one.oth3r.sit.utl.Utl;
import java.awt.*;
import java.util.concurrent.CompletableFuture;
public class SitCommand {
@ -49,7 +50,7 @@ public class SitCommand {
if (player == null) {
if (args[0].equalsIgnoreCase("reload")) {
Logic.reload();
Data.LOGGER.info(Utl.lang("sit!.chat.reloaded").getString());
Data.LOGGER.info(Utl.lang("sit!.chat.reloaded").toString());
}
return 1;
}
@ -75,7 +76,7 @@ public class SitCommand {
if (args[0].equalsIgnoreCase("reload")) {
Logic.reload();
player.sendMessage(Utl.messageTag().append(Utl.lang("sit!.chat.reloaded").formatted(Formatting.GREEN)));
player.sendMessage(Utl.messageTag().append(Utl.lang("sit!.chat.reloaded").color(Color.GREEN)).b());
}
if (args[0].equalsIgnoreCase("purgeChairEntities")) Utl.Entity.purge(player,true);

View file

@ -9,6 +9,7 @@ import net.minecraft.util.Identifier;
import one.oth3r.sit.utl.Utl;
import java.util.ArrayList;
import java.util.Objects;
public class CustomBlock {
@ -28,6 +29,12 @@ public class CustomBlock {
this.blockStates = blockStates;
}
public CustomBlock(CustomBlock customBlock) {
this.blockIds = new ArrayList<>(customBlock.blockIds);
this.blockTags = new ArrayList<>(customBlock.blockTags);
this.blockStates = new ArrayList<>(customBlock.blockStates);
}
public ArrayList<String> getBlockIds() {
return blockIds;
}
@ -84,18 +91,38 @@ public class CustomBlock {
}
// a boolean to check if one of the blocks are in a filtered tag
boolean tagCheck = false;
// & a switch for if there is only not(!) tags
boolean tagCheck = false, hasPositiveTags = false;
// for all the entered tags
for (String tag : blockTags) {
// substring to remove # and if needed, !
// if there is a math for the NOT(!) tag, return false
if (tag.startsWith("!") && blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.of(tag.substring(2))))) return false;
// if there is a match, return true
if (blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse(tag.substring(1))))) tagCheck = true;
if (tag.startsWith("!")) {
// if there is a match for the NOT(!) tag, return false
Identifier id = Identifier.tryParse(tag.substring(2));
if (id != null && blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), id))) return false;
} else {
// flip the hasPositiveTags boolean
hasPositiveTags = true;
// if there is a match, return true
Identifier id = Identifier.tryParse(tag.substring(1));
if (id != null && blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), id))) tagCheck = true;
}
}
// not returning true in the loop because there might be a (!) not tag that the block might fall into, after the block was already in another tag
return tagCheck;
// if there were any required tags, return whether we matched one
// if there were only not(!) tags, and we didn't violate any, return true
return hasPositiveTags? tagCheck : true;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
CustomBlock that = (CustomBlock) o;
return Objects.equals(blockIds, that.blockIds) && Objects.equals(blockTags, that.blockTags) && Objects.equals(blockStates, that.blockStates);
}
@Override
public int hashCode() {
return Objects.hash(blockIds, blockTags, blockStates);
}
}

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 java.util.ArrayList;
import java.util.Objects;
public class CustomItem {
@SerializedName("item-ids")
@ -21,6 +22,11 @@ public class CustomItem {
this.itemTags = itemTags;
}
public CustomItem(CustomItem customItem) {
this.itemIDs = new ArrayList<>(customItem.itemIDs);
this.itemTags = new ArrayList<>(customItem.itemTags);
}
public ArrayList<String> getItemIDs() {
return itemIDs;
}
@ -45,21 +51,38 @@ public class CustomItem {
}
// a boolean to check if one of the items are in a filtered tag
boolean tagCheck = false;
// & a switch for if there is only not(!) tags
boolean tagCheck = false, hasPositiveTags = false;
// check the custom item tags
for (String tag : itemTags) {
// substring to remove # and if needed, "!"
// if a NOT tag
if (tag.startsWith("!")) {
// if there is a math for the NOT(!) tag, return false
if (itemStack.isIn(TagKey.of(Registries.ITEM.getKey(), 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
return tagCheck;
// if there were any required tags, return whether we matched one
// if there were only not(!) tags, and we didn't violate any, return true
return hasPositiveTags? tagCheck : true;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
CustomItem that = (CustomItem) o;
return Objects.equals(itemIDs, that.itemIDs) && Objects.equals(itemTags, that.itemTags);
}
@Override
public int hashCode() {
return Objects.hash(itemIDs, itemTags);
}
}

View file

@ -3,6 +3,7 @@ package one.oth3r.sit.file;
import com.google.gson.annotations.SerializedName;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;
public class HandSetting {
@ -21,6 +22,11 @@ public class HandSetting {
this.filter = filter;
}
public HandSetting(HandSetting handSetting) {
this.sittingRequirement = handSetting.sittingRequirement;
this.filter = new Filter(handSetting.filter);
}
public SittingRequirement getSittingRequirement() {
return sittingRequirement;
}
@ -52,6 +58,12 @@ public class HandSetting {
this.customItems = customItems;
}
public Filter(Filter filter) {
this.invert = filter.invert;
this.presets = new Presets(filter.presets);
this.customItems = new CustomItem(filter.customItems);
}
public Boolean isInverted() {
return invert;
}
@ -80,6 +92,12 @@ public class HandSetting {
this.usable = usable;
}
public Presets(Presets presets) {
this.block = presets.block;
this.food = presets.food;
this.usable = presets.usable;
}
public boolean isBlock() {
return block;
}
@ -91,6 +109,42 @@ public class HandSetting {
public boolean isUsable() {
return usable;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
Presets presets = (Presets) o;
return block == presets.block && food == presets.food && usable == presets.usable;
}
@Override
public int hashCode() {
return Objects.hash(block, food, usable);
}
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
Filter filter = (Filter) o;
return Objects.equals(invert, filter.invert) && Objects.equals(presets, filter.presets) && Objects.equals(customItems, filter.customItems);
}
@Override
public int hashCode() {
return Objects.hash(invert, presets, customItems);
}
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
HandSetting that = (HandSetting) o;
return sittingRequirement == that.sittingRequirement && Objects.equals(sittingRequirementOptions, that.sittingRequirementOptions) && Objects.equals(filter, that.filter);
}
@Override
public int hashCode() {
return Objects.hash(sittingRequirement, sittingRequirementOptions, filter);
}
}

View file

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

View file

@ -1,10 +1,13 @@
package one.oth3r.sit.file;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import net.minecraft.util.Hand;
import one.oth3r.otterlib.file.CustomFile;
import one.oth3r.otterlib.file.FileSettings;
import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Utl;
import org.jetbrains.annotations.NotNull;
@ -13,28 +16,39 @@ import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
import java.util.Properties;
import java.util.stream.Collectors;
public class ServerConfig implements CustomFile<ServerConfig> {
@SerializedName("version")
private Double version = 2.1;
private Double version = 2.3;
@SerializedName("lang")
private String lang = "en_us";
@SerializedName("lang-options")
private final String langOptions = "en_us, it_it, pt_br, tr_tr, zh_tw";
private final String langOptions = "en_us, it_it, pt_br, tr_tr, zh_tw, zh_ch, de_de";
@SerializedName("keep-active")
private Boolean keepActive = true;
@SerializedName("sit-while-seated")
private Boolean sitWhileSeated = false;
@SerializedName("preset-blocks")
private PresetBlocks presetBlocks = new PresetBlocks();
@SerializedName("height-difference-limit")
private YDifferenceLimit yDifferenceLimit = new YDifferenceLimit();
@SerializedName("custom-enabled")
private Boolean customEnabled = false;
@SerializedName("custom-blocks")
private ArrayList<SittingBlock> sittingBlocks = FileData.Defaults.SITTING_BLOCKS;
@SerializedName("blacklisted-blocks")
private ArrayList<CustomBlock> blacklistedBlocks = FileData.Defaults.BLACKLISTED_BLOCKS;
@SerializedName("interaction-blocks")
@ -43,15 +57,7 @@ public class ServerConfig implements CustomFile<ServerConfig> {
public ServerConfig() {}
public ServerConfig(ServerConfig serverConfig) {
this.version = serverConfig.version;
this.lang = serverConfig.lang;
this.keepActive = serverConfig.keepActive;
this.sitWhileSeated = serverConfig.sitWhileSeated;
this.presetBlocks = serverConfig.presetBlocks;
this.customEnabled = serverConfig.customEnabled;
this.sittingBlocks = serverConfig.sittingBlocks;
this.blacklistedBlocks = serverConfig.blacklistedBlocks;
this.interactionBlocks = serverConfig.interactionBlocks;
copyFileData(serverConfig);
}
public ServerConfig(Double version, String lang, boolean keepActive, boolean sitWhileSeated,
@ -89,6 +95,10 @@ public class ServerConfig implements CustomFile<ServerConfig> {
return presetBlocks;
}
public YDifferenceLimit getYDifferenceLimit() {
return yDifferenceLimit;
}
public Boolean isCustomEnabled() {
return customEnabled;
}
@ -125,6 +135,13 @@ public class ServerConfig implements CustomFile<ServerConfig> {
this.fullBlocks = fullBlocks;
}
public PresetBlocks(PresetBlocks presetBlocks) {
this.stairs = presetBlocks.stairs;
this.slabs = presetBlocks.slabs;
this.carpets = presetBlocks.carpets;
this.fullBlocks = presetBlocks.fullBlocks;
}
public boolean isStairs() {
return stairs;
}
@ -140,11 +157,96 @@ public class ServerConfig implements CustomFile<ServerConfig> {
public boolean isFullBlocks() {
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 {
@SerializedName("enabled")
private boolean enabled = false;
@SerializedName("above")
private Double above = 1.0;
@SerializedName("below")
private Double below = 1.0;
public YDifferenceLimit() {
}
public YDifferenceLimit(Double above, Double below, boolean enabled) {
this.above = above;
this.below = below;
this.enabled = enabled;
}
public YDifferenceLimit(YDifferenceLimit yDifferenceLimit) {
this.above = yDifferenceLimit.above;
this.below = yDifferenceLimit.below;
this.enabled = yDifferenceLimit.enabled;
}
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Double getAbove() {
return above;
}
public void setAbove(Double above) {
this.above = above;
}
public Double getBelow() {
return below;
}
public void setBelow(Double 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
public void reset() {
loadFileData(new ServerConfig());
copyFileData(new ServerConfig());
}
@Override
@ -152,39 +254,50 @@ public class ServerConfig implements CustomFile<ServerConfig> {
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
public void loadFileData(ServerConfig newFile) {
public void copyFileData(ServerConfig newFile) {
this.version = newFile.version;
this.lang = newFile.lang;
this.keepActive = newFile.keepActive;
this.sitWhileSeated = newFile.sitWhileSeated;
this.presetBlocks = newFile.presetBlocks;
this.presetBlocks = new PresetBlocks(newFile.presetBlocks);
this.yDifferenceLimit = new YDifferenceLimit(newFile.yDifferenceLimit);
this.customEnabled = newFile.customEnabled;
this.sittingBlocks = newFile.sittingBlocks;
this.blacklistedBlocks = newFile.blacklistedBlocks;
this.sittingBlocks = newFile.sittingBlocks.stream().map(SittingBlock::new).collect(Collectors.toCollection(ArrayList::new));
this.blacklistedBlocks = newFile.blacklistedBlocks.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
public void update() {
public void update(JsonElement json) {
/// update to 2.1, just a new list, nothing to change
if (version == 2.0) {
version = 2.1;
/// update to 2.2, new settings, no changes
if (version >= 2.0 && version <= 2.1) {
version = 2.2;
}
if (version == 2.2) {
// make sure that the lang is all lowercase
version = 2.3;
this.lang = this.lang.substring(0,3)+this.lang.substring(3).toLowerCase();
}
}
@Override
public String getFileName() {
return "server-config.json";
}
@Override
public String getDirectory() {
return Data.CONFIG_DIR;
}
@Override
public void fileNotExist() {
CustomFile.super.fileNotExist();
public void createDirectory() {
CustomFile.super.createDirectory();
// try checking the old/legacy config directory for the file
if (Legacy.getLegacyFile().exists()) {
Data.LOGGER.info("Updating Sit!.properties to sit!/config.json");
@ -192,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 {
/**
* 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 java.util.ArrayList;
import java.util.Objects;
public class SittingBlock extends CustomBlock {
@SerializedName("sitting-height")
@ -22,4 +23,22 @@ public class SittingBlock extends CustomBlock {
super(blockIds, blockTags, blockStates);
this.sittingHeight = sittingHeight;
}
public SittingBlock(SittingBlock sittingBlock) {
super(sittingBlock);
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;
import com.google.common.base.Objects;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;
import net.minecraft.util.Hand;
import one.oth3r.otterlib.file.CustomFile;
import one.oth3r.otterlib.file.FileSettings;
import one.oth3r.sit.utl.Data;
import org.jetbrains.annotations.NotNull;
import java.nio.file.Path;
import java.nio.file.Paths;
public class SittingConfig implements CustomFile<SittingConfig> {
@SerializedName("version")
@ -29,7 +36,7 @@ public class SittingConfig implements CustomFile<SittingConfig> {
}
public SittingConfig(SittingConfig sittingConfig) {
loadFileData(sittingConfig);
copyFileData(sittingConfig);
}
public Double getVersion() {
@ -64,9 +71,19 @@ public class SittingConfig implements CustomFile<SittingConfig> {
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
public void reset() {
loadFileData(new SittingConfig());
copyFileData(new SittingConfig());
}
@Override
@ -75,24 +92,35 @@ public class SittingConfig implements CustomFile<SittingConfig> {
}
@Override
public void loadFileData(SittingConfig newFile) {
this.version = newFile.version;
this.enabled = newFile.enabled;
this.handSitting = newFile.handSitting;
this.mainHand = newFile.mainHand;
this.offHand = newFile.offHand;
public void copyFileData(SittingConfig sittingConfig) {
this.version = sittingConfig.version;
this.enabled = sittingConfig.enabled;
this.handSitting = sittingConfig.handSitting;
this.mainHand = new HandSetting(sittingConfig.mainHand);
this.offHand = new HandSetting(sittingConfig.offHand);
}
@Override
public void update() {}
public void update(JsonElement jsonElement) {
@Override
public String getFileName() {
return "sitting-config.json";
}
@Override
public String getDirectory() {
return Data.CONFIG_DIR;
public SittingConfig clone() {
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.network.ServerPlayerEntity;
import net.minecraft.util.Formatting;
import one.oth3r.sit.file.FileData;
import one.oth3r.sit.utl.Data;
import one.oth3r.sit.utl.Logic;
import one.oth3r.sit.utl.Utl;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.awt.*;
@Mixin(ReloadCommand.class)
public class ReloadCommandMixin {
@Inject(at = @At("TAIL"), method = "register")
private static void register(CommandDispatcher<ServerCommandSource> dispatcher, CallbackInfo ci) {
FileData.loadFiles();
Logic.reload();
// make sure the server isn't null
MinecraftServer server = Data.getServer();
@ -27,7 +29,7 @@ public class ReloadCommandMixin {
// send a reloaded message to all players with permissions
for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) {
if (player.isCreativeLevelTwoOp()) {
player.sendMessage(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,30 +0,0 @@
package one.oth3r.sit.screen;
import com.mojang.blaze3d.systems.RenderSystem;
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) {
RenderSystem.enableBlend();
RenderSystem.enableDepthTest();
context.drawTexture(RenderLayer::getGuiTextured, image,
this.getX(), this.getY(), 0.0f, 0.0f, this.getWidth(), this.getHeight(), this.getWidth(), this.getHeight());
}
}

View file

@ -1,81 +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) {
RenderSystem.enableBlend();
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));
RenderSystem.disableBlend();
}
}

View file

@ -2,10 +2,11 @@ package one.oth3r.sit.screen;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import one.oth3r.sit.SitClient;
public class ModMenu implements ModMenuApi {
@Override
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;
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.keybinding.v1.KeyBindingHelper;
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.network.ClientPlayerEntity;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
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.file.FileData;
import one.oth3r.sit.file.LangReader;
import one.oth3r.sit.file.SittingConfig;
import one.oth3r.sit.packet.SitPayloads;
import one.oth3r.sit.screen.ConfigScreen;
import org.lwjgl.glfw.GLFW;
import java.awt.*;
public class Events {
private static class Keybindings {
@ -54,7 +59,7 @@ public class Events {
ClientPlayerEntity player = client.player;
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
@ -70,11 +75,11 @@ public class Events {
// just send the sit command
if (Data.isInGame()) {
if (Data.isSupportedServer()) {
player.networkHandler.sendCommand("sit");
player.networkHandler.sendChatCommand("sit");
} else {
// unsupported server message if not in a Sit! server
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));
// 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
if (!Data.isSupportedServer()) {
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;
// 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;
import net.minecraft.block.*;
import net.minecraft.block.BlockState;
import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.registry.Registries;
import net.minecraft.registry.tag.TagKey;
@ -12,64 +12,90 @@ import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import one.oth3r.sit.file.FileData;
import one.oth3r.sit.file.SittingConfig;
import one.oth3r.sit.file.HandSetting;
import one.oth3r.sit.file.*;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
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
if (player.isSneaking()) return false;
// if sitting on a sit entity and sit while seated off, false
if (!FileData.getServerConfig().canSitWhileSeated() && Data.getSitEntity(player) != null) return false;
ServerWorld serverWorld = player.getServerWorld();
ServerWorld serverWorld = player.getWorld();
BlockState blockState = serverWorld.getBlockState(blockPos);
Double sitHeight = null;
// is a bed?
if (blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse("minecraft:beds")))) {
if (hitResult != null) {
// is a cookie?
if (Registries.ITEM.getId(player.getStackInHand(Hand.MAIN_HAND).getItem()).toString().equals("minecraft:cookie"))
sitHeight = BED_HEIGHT;
else return false;
} else {
sitHeight = BED_HEIGHT;
}
// hit result == null means mod right?
if (hitResult != null && !Registries.ITEM.getId(player.getStackInHand(Hand.MAIN_HAND).getItem()).toString().equals("minecraft:cookie"))
return false;
// behave normally otherwise
} 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 (hitResult != null) {
if (!checkHands(player)) return false;
}
sitHeight = Utl.getSittingHeight(blockState, player, blockPos, hitResult);
}
// if the sit height is null, its not a sittable block
if (sitHeight == null) return false;
// check if the block is in the right y level limits from the config
if (!checkYLimits(player, blockPos)) return false;
Double sitHeight = Utl.getSittingHeight(player, blockPos, hitResult);
// 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);
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;
}
/**
* 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) {
return sit(player, Utl.getBlockPosPlayerIsLookingAt(player.getServerWorld(),player,5),null);
return sit(player, Utl.getBlockPosPlayerIsLookingAt(player.getWorld(),player,
Utl.getPlayerReach(player)),null);
}
/**
@ -98,6 +124,28 @@ public class Logic {
return canSit;
}
/**
* check if the Y-level of the block is within the limits of the player, bounds are set in the {@link ServerConfig}
*/
public static boolean checkYLimits(ServerPlayerEntity player, BlockPos blockPos) {
ServerConfig.YDifferenceLimit yDifferenceLimit = FileData.getServerConfig().getYDifferenceLimit();
// check if enabled
if (!yDifferenceLimit.isEnabled()) return true;
double playerY = player.getBlockY();
double blockY = blockPos.getY();
// if the block is above the eye height
boolean isAbove = playerY < blockY;
// return true if equal
if (playerY == blockY) return true;
// get the height difference (positive)
double heightDifference = Math.abs(playerY - blockY);
return (isAbove? yDifferenceLimit.getAbove() : yDifferenceLimit.getBelow()) >= heightDifference;
}
/**
* removes the entity bound to the player from the game, using the player
*/
@ -122,7 +170,7 @@ public class Logic {
// get the new entity
DisplayEntity.TextDisplayEntity sitEntity = Data.getSpawnList().get(player);
// spawn and ride the entity
player.getServerWorld().spawnEntity(sitEntity);
player.getWorld().spawnEntity(sitEntity);
player.startRiding(sitEntity);
// add the entity to the list
Data.addSitEntity(player, sitEntity);
@ -155,7 +203,7 @@ public class Logic {
// get the poses to check above the block
BlockPos pos1 = new BlockPos(pos).add(0,1,0), pos2 = new BlockPos(pos).add(0,2,0), posBelow = new BlockPos(pos);
// doesn't check 2 blocks above if not sitting above .80 of the block
if (pos.getY() > entity.getY() - .80) {
if (pos.getY() > (entity.getY()-Utl.Entity.Y_ADJUSTMENT) - .80) {
pos2 = pos2.add(0,-1,0);
posBelow = posBelow.add(0,-1,0);
}
@ -172,6 +220,7 @@ public class Logic {
public static void reload() {
FileData.loadFiles();
FileData.saveFiles();
LangReader.loadLanguageFile();
}
/**
@ -194,16 +243,16 @@ public class Logic {
// get the message settings
String messageKey = "sit!.chat.sit_toggle."+(config.getEnabled()?"on":"off");
String messageKey = "sit!.chat.toggle_sit."+(config.getEnabled()?"on":"off");
Formatting messageColor = config.getEnabled()?Formatting.GREEN:Formatting.RED;
// send the player the actionbar message
return Utl.lang("sit!.chat.sit_toggle",
Utl.lang(messageKey).formatted(messageColor));
return Utl.lang("sit!.chat.toggle_sit",
Utl.lang(messageKey).color(config.getEnabled()? Color.GREEN : Color.RED)).b();
} else {
// unsupported server message if not in a Sit! server
return 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.SlabType;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
@ -19,9 +20,7 @@ import net.minecraft.registry.Registries;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.text.TextColor;
import net.minecraft.util.*;
import net.minecraft.util.hit.BlockHitResult;
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.world.RaycastContext;
import net.minecraft.world.World;
import one.oth3r.otterlib.chat.CTxT;
import one.oth3r.sit.file.*;
import one.oth3r.sit.packet.SitPayloads;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@ -42,6 +43,9 @@ import java.util.List;
public class Utl {
private static double BED_HEIGHT = 0.5625;
private static double DRIED_GHAST_HEIGHT = 0.625;
/**
* check if a block is obstructed (no collision)
* @return true if not obstructed
@ -154,16 +158,26 @@ public class Utl {
/**
* 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 blockPos the pos of the block
* @param hit nullable, for the player interaction check
* @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();
BlockState blockState = serverWorld.getBlockState(blockPos);
Block block = blockState.getBlock();
// check bed first
if (blockState.isIn(TagKey.of(Registries.BLOCK.getKey(), Identifier.tryParse("minecraft:beds")))) {
return BED_HEIGHT;
}
// why not sit on the dried ghast?
if (Registries.BLOCK.getEntry(block).getIdAsString().equals("minecraft:dried_ghast"))
return DRIED_GHAST_HEIGHT;
// make sure that the block that is being sit on has no interaction when hand sitting
if (hit != null && blockIsInList(config.getInteractionBlocks(), blockState)) {
return null;
@ -209,7 +223,7 @@ public class Utl {
/**
* the customizable y height of the entity, as some versions have different sitting heights on the entity
*/
private static final double Y_ADJUSTMENT = 0;
public static final double Y_ADJUSTMENT = 0;
/**
* checks if the entity's block is still there, & is valid
@ -219,7 +233,7 @@ public class Utl {
// get the blockstate
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)
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;
}
/**
@ -228,10 +242,9 @@ public class Utl {
public static BlockPos getBlockPos(DisplayEntity.TextDisplayEntity entity) {
// the entity Y level, adjusted
// the adjustment - is the opposite of the offset applied in Entity.create()
double entityY = entity.getY() + (Y_ADJUSTMENT*-1);
int entityBlockY = (int) (Math.floor(entity.getY() + (Y_ADJUSTMENT*-1)));
// get the block pos
BlockPos pos = new BlockPos(entity.getBlockX(),(int)entityY,entity.getBlockZ());
BlockPos pos = new BlockPos(entity.getBlockX(),entityBlockY,entity.getBlockZ());
// if above the block, subtract 1
if (isAboveBlockHeight(entity)) {
pos = pos.add(0,-1,0);
@ -306,7 +319,7 @@ public class Utl {
/// FYI it cant purge an entity from a disconnected player or unloaded chunks
// 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),
entity -> entity.getName().getString().equals(Data.ENTITY_NAME));
@ -321,26 +334,32 @@ public class Utl {
// send a message if needed
if (message) {
player.sendMessage(messageTag().append(Utl.lang("sit!.chat.purged",Utl.lang("sit!.chat.purged.total",count).styled(
style -> style.withColor(Colors.LIGHT_GRAY).withItalic(true)
)).styled(
style -> style.withColor(Colors.GREEN)
)));
player.sendMessage(messageTag()
.append(lang("sit!.chat.purged",lang("sit!.chat.purged.total",count).color(Color.gray).b()).color(Color.GREEN)).b());
}
}
}
public static MutableText messageTag() {
return Text.literal("[").append(Text.literal("Sit!").styled(
style -> style.withColor(TextColor.parse("#c400ff").result().orElse(TextColor.fromFormatting(Formatting.DARK_PURPLE))))
).append("] ");
public static CTxT messageTag() {
return new CTxT("Sit!").btn(true).color(Color.decode("#c400ff")).append(" ");
}
/**
* gets a MutableText using the language key, if on server, using the custom lang reader
*/
public static MutableText lang(String key, Object... args) {
if (Data.isClient()) return Text.translatable(key, args);
public static CTxT lang(String key, Object... args) {
if (Data.isClient()) {
// we have to first convert all the CTxT's to the built version because minecraft lang reader doesn't know how to process it
// make a array with the same size of the args
Object[] fixedArgs = new Object[args.length];
// for every arg, build & add if CTxT or just add if not
for (var i = 0; i < args.length; i++) {
if (args[i] instanceof CTxT) fixedArgs[i] = ((CTxT) args[i]).b();
else fixedArgs[i] = args[i];
}
// return the translated text
return new CTxT(Text.translatable(key,fixedArgs));
}
else return LangReader.of(key, args).getTxT();
}
@ -371,7 +390,8 @@ public class Utl {
* sends the settings packets to the server, if client & in game
*/
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())));
}
}
@ -476,4 +496,13 @@ public class Utl {
return new BlockPos(player.getBlockPos());
}
public static double getPlayerReach(PlayerEntity player) {
// use the BLOCK_INTERACTION_RANGE attribute if available
if (player.getAttributeInstance(EntityAttributes.BLOCK_INTERACTION_RANGE) != null) {
return player.getAttributeValue(EntityAttributes.BLOCK_INTERACTION_RANGE);
}
// fallback to 5
return 5;
}
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,77 @@
{
"config.entry.exclusion": "Setze ein `!` vor einen Eintrag um ihn auszuschließen!",
"config.entry.example": "Beispiel eingeben: %s",
"config.server": "Server Konfiguration",
"config.server.description": "Konfiguriert die Einstellung des Servers.",
"config.server.lang": "Sprache",
"config.server.lang.description": "Die Sprache, die für die Sit! Mod benutzt wird.",
"config.server.keep-active": "Aktiv lassen",
"config.server.keep-active.description": "Stellt ein ob die Sit! Entität bleiben soll, selbst wenn der Spieler/Server offline ist.\nWenn nein, wird der Spieler nicht mehr sitzen, wenn er sich wieder einloggt.",
"config.server.sit-while-seated": "Setzten während reiten",
"config.server.sit-while-seated.description": "Stellt die Fähigkeit ein auf einem anderem Sit! Block zu sitzen, wenn man bereits auf einem sitzt.",
"config.server.preset-blocks": "Vorhandene Blöcke",
"config.server.preset-blocks.description": "Stellt die Standard Sit! Blöcke ein.",
"config.server.preset-blocks.stairs": "Treppen",
"config.server.preset-blocks.slabs": "Stufen",
"config.server.preset-blocks.carpets": "Teppiche",
"config.server.preset-blocks.full-blocks": "Volle Blöcke",
"config.server.custom-enabled": "Benutzerdefiniert",
"config.server.custom-enabled.description": "Stellt das Benutzen von Benutzerdefinierten Blöcken zum Sitzen ein.",
"config.server.custom-blocks": "Benutzerdefinierte Blöcke",
"config.server.custom-blocks.description": "Die Liste Benutzerdefinierter Sitz-Blöcke",
"config.server.custom-block.block-ids": "Block IDs",
"config.server.custom-block.block-ids.description": "Die Block-ID(s) für Benutzerdefinierte Sitzt-Blöcke.",
"config.server.custom-block.block-tags": "Block Tags",
"config.server.custom-block.block-tags.description": "Die Block-Tag(s) für Benutzerdefinierte Sitzt-Blöcke.",
"config.server.custom-block.blockstates": "Blockstates",
"config.server.custom-block.blockstates.description": "Die Blockstates, die ein Block haben muss, um ein eigener Sitz-Block zu sein.",
"config.server.custom-block.sitting-height": "Sitzt Höhe",
"config.server.custom-block.sitting-height.description": "Die Spieler Sitzhöhe von den eigenen Blöcken.",
"config.server.blacklisted-blocks": "Gesperrte Blöcke",
"config.server.blacklisted-blocks.description": "Die Liste der Blöcke auf denen man nicht sitzen kann.",
"config.sitting": "Sitzt Konfiguration",
"config.sitting.description": "Konfiguriert die Sitzfähigkeit. Auf dem Server kann jeder Spieler seine eigene Sitzkonfiguration haben, wenn er den Mod benutzt.",
"config.sitting.enabled": "Aktiviert",
"config.sitting.enabled.description": "Stellt die Fähigkeit zum Sitzen ein.",
"config.sitting.hand-sitting": "Hand Sitzen",
"config.sitting.hand-sitting.description": "Stellt die Fähigkeit ein, mit der Hilfe von Hand-Interaktionen zu sitzen.",
"config.sitting.hand.main": "Haupthand",
"config.sitting.hand.main.description": "Haupthand",
"config.sitting.hand.off": "Zweithand",
"config.sitting.hand.off.description": "Zweithand",
"config.sitting.hand.description": "Konfiguriert die %s sitzt Einstellungen.",
"config.sitting.hand.requirement": "Sitzungsanforderung",
"config.sitting.hand.requirement.description": "Die Handanforderung zum Sitten. Z.B. wenn EMPTY, muss die Hand leer sein",
"config.sitting.hand.requirement.description.none": "Keine Anforderung zum Sitzen.",
"config.sitting.hand.requirement.description.empty": "Die Hand muss leer sein, um zu sitzen.",
"config.sitting.hand.requirement.description.filter": "Man kann nur sitzen, wenn der Gegenstand in der Hand einem der Filter entspricht.",
"config.sitting.hand.filter": "Filter",
"config.sitting.hand.filter.description": "Die Liste der Gegenstände für die Filter-Handvoraussetzung.",
"config.sitting.hand.filter.block": "Blöcke",
"config.sitting.hand.filter.block.description": "Der Block-Standard-Filter.",
"config.sitting.hand.filter.food": "Essen",
"config.sitting.hand.filter.food.description": "Der Essen-Standard-Filter.",
"config.sitting.hand.filter.usable": "Benutzbare Gegenstände",
"config.sitting.hand.filter.usable.description": "Die benutzbaren Gegenstände Standardfilter. (Dreizacken, Schilde, Bogen)",
"config.sitting.hand.filter.custom-items": "Benutzerdefinierte Items",
"config.sitting.hand.filter.custom-items.description": "Eine Liste von Benutzerdefinierten Elementen, die dem Filter hinzugefügt werden sollen.",
"config.sitting.hand.filter.custom-tags": "Benutzerdefinierte Tags",
"config.sitting.hand.filter.custom-tags.description": "Eine Liste von Benutzerdefinierte Item-Tags für den Filter.",
"sit!.chat.toggle_sit": "%s sitzt!",
"sit!.chat.toggle_sit.on": "Aktiviert",
"sit!.chat.toggle_sit.off": "Deaktiviert",
"sit!.chat.unsupported": "Sit! Ist auf dem Server nicht verfügbar.",
"sit!.chat.reloaded": "Konfiguration wurde neu geladen!",
"sit!.chat.purged": "Alle geladenen Sit! Entitäten gelöscht! %s",
"sit!.chat.purged.total": "(%s entfernt)",
"key.sit!.toggle": "Sitzen umschalten",
"key.sit!.sit": "Sitzen",
"key.sit!.config": "Konfiguration öffnen",
"sit!.screen.config": "Sit! Konfiguration",
"sit!.gui.button.issues": "Probleme",
"sit!.gui.button.donate": "Spenden",
"sit!.gui.button.website": "Website",
"sit!.console.connected": "Verbunden mit Sit! Server: %s",
"sit!.console.player_settings": "Benutzerdefinierte Sitzungseinstellungen von %s erhalten!",
"modmenu.descriptionTranslation.sit-oth3r": "Fügt die Möglichkeit hinzu, in Minecraft zu sitzen! Endlose Anpassungsmöglichkeiten für Handbeschränkungen und sitzbare Blöcke.\nSpieler können ihre eigenen Sitzeinstellungen verwenden, wenn sie den Sit!-Client auf dem Server nutzen!"
}

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",
"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.donate": "Donate",
"sit!.gui.button.revert": "Revert Changes",
"sit!.gui.button.save": "Save and Close",
"sit!.gui.button.website": "Website",
"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.example": "Esempio campo: %s",
"config.server": "Configura Server",
@ -69,13 +68,8 @@
"key.sit!.sit": "Siediti",
"key.sit!.config": "Apri Impostazioni",
"sit!.screen.config": "Impostazioni Sit!",
"sit!.gui.button.file": "Apri File",
"sit!.gui.button.folder": "Apri Cartella",
"sit!.gui.button.reset": "Resetta",
"sit!.gui.button.issues": "Problemi",
"sit!.gui.button.donate": "Dona",
"sit!.gui.button.revert": "Annulla i Cambiamenti",
"sit!.gui.button.save": "Salva ed Esci",
"sit!.gui.button.website": "Sito Web",
"sit!.console.connected": "Connesso al server Sit!: %s",
"sit!.console.player_settings": "Ricevute impostazioni custom da %s!",

View file

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

View file

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

View file

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

@ -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! 模组以后,玩家加入装有 Sit! 的服务器可以拥有自己的坐下配置。"
}

View file

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

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

@ -1,51 +0,0 @@
{
"config.sit.empty": "空",
"config.sit.restrictive": "限制",
"config.sit.none": "無",
"config.sit.category.general": "一般",
"config.sit.category.general.tooltip": "一般設定",
"config.sit.category.main_hand": "慣用手",
"config.sit.category.main_hand.tooltip": "慣用手設定",
"config.sit.category.off_hand": "非慣用手",
"config.sit.category.off_hand.tooltip": "非慣用手設定",
"config.sit.general.keep_active": "保持活躍",
"config.sit.general.keep_active.description": "即使在登出/關閉時,也保持實體處於活躍狀態",
"config.sit.general.sittable": "可坐的方塊",
"config.sit.general.sittable.description": "切換坐在不同方塊類型上的能力。",
"config.sit.general.sit_while_seated": "坐下時坐下",
"config.sit.general.sit_while_seated.description": "切換已經坐在一個方塊上時,坐在其他方塊上的能力。",
"config.sit.general.sittable.stairs": "階梯",
"config.sit.general.sittable.slabs": "半磚",
"config.sit.general.sittable.carpets": "地毯",
"config.sit.general.sittable.full_blocks": "完整方塊",
"config.sit.general.sittable.custom": "自訂",
"config.sit.general.sittable.custom.description": "啟用新增自訂方塊以供坐下。",
"config.sit.general.sittable_blocks": "自訂可坐方塊",
"config.sit.general.sittable_blocks.description": "新增自訂可坐方塊!",
"config.sit.general.sittable_blocks.description_2": "範例:%s",
"config.sit.general.sittable_blocks.description_4": "第一個條目:自訂方塊",
"config.sit.general.sittable_blocks.description_5": "第二個條目坐姿高度0-1 之間的數字,例如 0.52",
"config.sit.general.sittable_blocks.description_6": "第三個條目:碰撞箱大小(玩家下馬時在實體上方生成的位置)",
"config.sit.general.sittable_blocks.description_7": "第四個條目(可選):坐下的必要方塊狀態(輸入「!」排除方塊狀態)",
"config.sit.general.sittable_blocks.description_8": "使用「|」分隔不同的條目!",
"config.sit.hand": "手部設定",
"config.sit.hand.requirements": "需求",
"config.sit.hand.requirements.description": "坐下的手部需求。",
"config.sit.hand.requirements.description_2": "空 = 手必須是空的",
"config.sit.hand.requirements.description_3": "限制 = 為手部狀態設定限制",
"config.sit.hand.requirements.description_4": "無 = 隨時可以坐下",
"config.sit.hand.restrictions": "限制",
"config.sit.hand.restrictions.description": "切換預設的手部限制以供坐下。",
"config.sit.hand.restrictions.blocks": "方塊",
"config.sit.hand.restrictions.food": "食物",
"config.sit.hand.restrictions.usable": "可使用的",
"config.sit.hand.restrictions.usable.description": "例如:弓、三叉戟、盾牌",
"config.sit.hand.whitelist": "白名單",
"config.sit.hand.whitelist.description": "為玩家可以用來坐下的物品建立自訂白名單。",
"config.sit.hand.blacklist": "黑名單",
"config.sit.hand.blacklist.description": "為玩家無法用來坐下的物品建立自訂黑名單。",
"config.sit.hand.list.description": "範例:",
"config.sit.hand.list.description_2": "「minecraft:torch」",
"key.sit.command.reloaded": "已重新載入設定!",
"key.sit.command.purged": "已清除所有活躍的椅子實體!"
}

View file

@ -9,8 +9,8 @@
"Virt"
],
"contact": {
"homepage": "https://modrinth.com/mod/sit!",
"sources": "https://github.com/Oth3r/Sit"
"homepage": "https://copeberg.org/virt/Sit",
"sources": "https://copeberg.org/virt/Sit"
},
"license": "LGPL-3.0-only",
"icon": "assets/sit-oth3r/icon.png",
@ -28,8 +28,9 @@
},
"depends": {
"fabricloader": ">=0.14.21",
"minecraft": ">=${min_minecraft_version} <=${minecraft_version}",
"fabric": "*"
"minecraft": ">=${min_minecraft_version} <=${max_minecraft_version}",
"fabric": "*",
"otterlib": ">=${otterlib_version} <${otterlib_max_version}"
},
"suggests": {
"modmenu": "*"
@ -38,4 +39,4 @@
"mixins": [
"sit!.mixins.json"
]
}
}