Compare commits

..

No commits in common. "main" and "v3.0.5" have entirely different histories.
main ... v3.0.5

400 changed files with 8627 additions and 18930 deletions

3
.github/FUNDING.yml vendored
View File

@ -1,3 +0,0 @@
github: FlorianMichael
custom: ["https://florianmichael.de/donate"]
ko_fi: rk_01

View File

@ -13,11 +13,9 @@ body:
attributes:
label: General Information
description: |
Please provide a ViaVersion dump, if you experience a crash, also the crash report (latest.log file). You can get both by
going to `ViaFabricPlus -> Report issues` and using the buttons there.
Please provide a list of all installed mods
placeholder: |
ViaVersion dump url: **paste here**
Crash report url: **upload to mclo.gs and paste here**
Example: "ViaFabricPlus, Fabric-API, Quilted-Fabric-API, ModMenu"
validations:
required: true

View File

@ -1,44 +0,0 @@
name: Feature Request
description: Suggest a feature to be added in ViaFabricPlus
labels: [ enhancement ]
body:
- type: markdown
attributes:
value: |
**Before requesting a new feature, please see if using latest build from https://github.com/ViaVersion/ViaFabricPlus/actions already includes a solution.**
Whenever you see fit, you can upload images or videos to any of the text fields.
- type: textarea
attributes:
label: Problem Description
description: |
Describe the issue you are facing or why you need the feature to be added.
placeholder: |
I am always frustrated with...
validations:
required: true
- type: textarea
attributes:
label: Solution Description
description: |
Describe the solution you would like to see.
validations:
required: true
- type: textarea
attributes:
label: Alternatives
description: |
Describe alternatives you have considered.
validations:
required: false
- type: textarea
attributes:
label: Additional Info
description: |
Does the feature apply to any specific version or environment?
validations:
required: false

View File

@ -1,10 +0,0 @@
version: 2
updates:
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@ -1,24 +1,24 @@
name: Build
name: ViaFabricPlus CI
on: [pull_request, push, workflow_dispatch]
jobs:
build:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 21
java-version: 17
check-latest: true
- name: Build with Gradle
run: ./gradlew build
- name: Upload Artifacts to GitHub
uses: actions/upload-artifact@v4
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: Artifacts
path: build/libs/

View File

@ -1,20 +0,0 @@
name: Update Gradle Wrapper
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * 0"
jobs:
update-gradle-wrapper:
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 21
check-latest: true
- name: Update Gradle Wrapper
uses: gradle-update/update-gradle-wrapper-action@v2

View File

@ -1,45 +0,0 @@
# Contributing guidelines for the project
## Setting up a Workspace
ViaFabricPlus uses Gradle, to make sure that it is installed properly you can check [Gradle's website](https://gradle.org/install/).
1. Clone the repository using `git clone https://github.com/ViaVersion/ViaFabricPlus`.
2. CD into the local repository.
3. Run `./gradlew genSources`.
4. Open the folder as a Gradle project in your preferred IDE.
5. Run the mod.
## Update translation files
Translation files are located in `src/main/resources/assets/viafabricplus/lang/`. To update them, you need to do the following:
1. Copy the `en_us.json` file and rename it to the language code of the language you want to update (e.g. `de_de.json` for German)
2. Translate all values in the file to the language you want to update
3. Do not change the keys of the values, only the values themselves
4. Do not change the formatting of the file (e.g. the spaces between the keys and values or the order of the keys)
5. Try to be consistent with Minecraft language files.
6. Take a look at UN's guidelines for Gender-inclusive language: https://www.un.org/en/gender-inclusive-language/guidelines.shtml
7. Create a pull request and wait for it to be reviewed and merged.
8. You're done, congrats!
## Add a new feature or fix a bug
1. Create a new branch for your feature/bugfix (e.g. `feature/fix-xyz` or `fix/fix-xyz`)
2. Implement your feature/bugfix and make sure it works correctly
3. Clean your code and make sure it is readable and understandable (e.g. use proper variable names)
4. Use the Google java code style (https://google.github.io/styleguide/javaguide.html) and format your code accordingly
5. If you're changing API, make sure to update the documentation in the `docs` folder, add javadocs to your code and don't break backwards compatibility if not necessary
6. Create a pull request and wait for it to be reviewed and merged.
7. You're done, congrats!
## Adding protocol new fixes - which are important and which aren't?
Protocol fixes are the core functionality of ViaFabricPlus, they make ViaFabricPlus stand out from all other existing
protocol translation platforms, and so it's even more important to keep them working.
When adding new fixes, you should always check if the fix is relevant for the current version of the game. If you're unsure,
ask in the ViaVersion discord.
In general, you should only implement changes which could be detected by the server or are relevant for the gameplay.
From experience, most changes are related to either movement or networking. If you contribute new fixes, please proof
your changes by showing that they are relevant and also by providing a game source diff. **It's important that fixes
are changing the actual change happend in the game and not just visual changes.**
## Maintaining the mod
See [MAINTAINING.md](docs/MAINTAINING.md) for more information on how to maintain the mod.

138
README.md
View File

@ -12,47 +12,125 @@
</div>
# Why another protocol translator?
ViaFabricPlus implements the [ViaVersion projects](https://github.com/ViaVersion) into Fabric and provides tons of fixes to the existing protocol translation which can't be implemented in the original ViaVersion project.
These fixes consist of movement changes, block/entity collisions, rendering changes, and many more.
At the time of writing, ViaFabricPlus is the only mod that supports joining all Minecraft server versions down to the first multiplayer version while implementing
legacy combat mechanics, movement, and rendering changes to make the gameplay feel more like the old days.
**On the other hand, ViaFabricPlus supports only the latest Minecraft client version, and only Fabric.**
If you need ViaFabricPlus for older versions of the game, you can use [ViaFabric](https://viaversion.com/fabric)
## Supported Server versions
- Release (1.0.0 - 1.21.3)
ViaFabricPlus is a deep integration of ViaVersion on the Fabric platform, it implements many changes that can't be fixed on protocol level (old animations, old movement/swimming, collisions and general rendering changes).
At the time of writing, VFP is the only protocol translation platform for the client with which you can play on all Minecraft multiplayer versions with many QoL features and get the feel of the old versions.
### Supported Server versions
- Release (1.0.0 - 23w51b)
- Beta (b1.0 - b1.8.1)
- Alpha (a1.0.15 - a1.2.6)
- Classic (c0.0.15 - c0.30 including [CPE](https://wiki.vg/Classic_Protocol_Extension))
- April Fools (3D Shareware, 20w14infinite)
- Combat Snapshots (Combat Test 8c)
- Bedrock Edition 1.21.40 ([Some features are missing](https://github.com/RaphiMC/ViaBedrock#features))
- Snapshots (3D Shareware, 20w14infinite, Combat Test 8C)
- Bedrock (1.20.0)
## How to (Users)
- [A detailed guide on how to install and use the mod](docs/USAGE.md)
- If you encounter any issues, please report them on either:
- [the issue tracker](https://github.com/ViaVersion/ViaFabricPlus/issues)
- [the ViaVersion Discord](https://discord.gg/viaversion)
# For users
### Detailed instructions for use are available [here](docs/USAGE.md)
### If you encounter any issues, please report them on the [issue tracker](https://github.com/ViaVersion/ViaFabricPlus/issues) or on the ViaVersion [Discord](https://discord.gg/viaversion)
## How to (Developers)
- [Detailed guidelines for contributions as well as setting up a dev environment](CONTRIBUTING.md)
- [API and integration examples for developers](docs/DEVELOPER_API.md)
## Known incompatibilities
### Breaks
- ***[ViaFabric (*)](https://github.com/ViaVersion/ViaFabric)***
- ***[krypton (<= 0.2.2)](https://github.com/astei/krypton)***
- ***[MemoryLeakFix (<= 1.1.0)](https://github.com/fxmorin/MemoryLeakFix)***
## ViaFabric
[ViaFabric](https://github.com/ViaVersion/ViaFabric) can be used for server-side purposes or when using older versions of the game.
### Conflicts
- ***[DashLoader (*)](https://github.com/alphaqu/DashLoader/tree/fabric-1.20)*** - Font rendering related fixes aren't working
- ***[Armor Skin (*)](https://github.com/IzzyDotExe/ArmorSkin)*** - Beta HUD changes aren't working
### Does it work with ViaFabricPlus:
## Feature list
<details>
<summary>Click to open</summary>
- No, ViaFabricPlus cannot be used with ViaFabric.
- [x] Bounding boxes for all versions
- [x] Entity interaction and movement related packet fixes
- [x] Sync and async mouse/keyboard handling in <= 1.12.2
- [x] Mining speeds and item attributes
- [x] Filter item creative tabs for only available items
- [x] Combat system in <= 1.8
- [x] Tons of modifications to ViaVersion, ViaAprilFools, ViaLegacy and ViaBedrock to make it more legit (Metadata fixes, broken packets, edge-cases)
- [x] Visual and screen related changes (newer Command Block features, GameMode selection, ...)
- [x] Chat signatures (secure login) for all versions (1.19.0, 1.19.1, 1.19.2)
- [x] Address parsing for all Minecraft versions
- [x] PackFormats and HTTP Header for all resource pack versions
- [x] Raytrace related fixes in <= 1.8
- [x] Implementing HUD changes for <= b1.7.3
- [x] Chat lengths of all versions
- [x] Implementing non-sequenced block placement in <= 1.18.2
- [x] Animation related fixes (1.7 Sneaking, c0.30 walking animation, ...)
- [x] Fixed clientside packet handling (1.16.5 transactions, 1.19.0 tablist, ...)
</details>
### Differences with ViaFabric:
https://github.com/ViaVersion/ViaFabric?tab=readme-ov-file#differences-with-viafabricplus
# For developers and translators
### Contributions in the form of pull requests are always welcome, [here](docs/UPDATE_INSTRUCTIONS.md) are some guidelines for contributing to the project.
#### A detailed TODO list can be found at the class header of [this](https://github.com/ViaVersion/ViaFabricPlus/blob/main/src/main/java/de/florianmichael/viafabricplus/ViaFabricPlus.java) file.
## Credits
Special thanks to all our [Contributors](https://github.com/ViaVersion/ViaFabricPllus/graphs/contributors).
### Dependencies
For compiling only! **You do not need to install these!**
<details>
<summary>Click to get a list of all dependencies</summary>
| Dependency | Download |
|------------------------|------------------------------------------------------|
| Fabric API | https://github.com/FabricMC/fabric |
| Fabric Loader | https://github.com/FabricMC/fabric-loader |
| Classic4J | https://github.com/FlorianMichael/Classic4J |
| ViaVersion | https://github.com/ViaVersion/ViaVersion |
| ViaBackwards | https://github.com/ViaVersion/ViaBackwards |
| ViaLoader | https://github.com/ViaVersion/ViaLoader |
| ViaLegacy | https://github.com/ViaVersion/ViaLegacy |
| ViaAprilFools | https://github.com/ViaVersion/ViaAprilFools |
| ViaBedrock | https://github.com/RaphiMC/ViaBedrock |
| MinecraftAuth | https://github.com/RaphiMC/MinecraftAuth |
| Netty-transport-RakNet | https://github.com/CloudburstMC/Network/tree/develop |
| Reflect | https://github.com/Lenni0451/Reflect |
| MCPing | https://github.com/Lenni0451/MCPing |
| MixinExtras | https://github.com/LlamaLad7/MixinExtras |
</details>
### Setting up a Workspace
ViaFabricPlus uses Gradle, to make sure that it is installed properly you can check [Gradle's website](https://gradle.org/install/).
1. Clone the repository using `git clone https://github.com/ViaVersion/ViaFabricPlus`.
2. CD into the local repository.
3. Run `./gradlew genSources`.
4. Open the folder as a Gradle project in your preferred IDE.
5. Run the mod.
### Include via Gradle/Maven
```groovy
repositories {
maven {
name = "ViaVersion"
url = "https://repo.viaversion.com"
}
}
dependencies {
modImplementation("de.florianmichael:viafabricplus:3.0.2") // Get the latest version from releases
}
```
```xml
<repositories>
<repository>
<id>viaversion</id>
<url>https://repo.viaversion.com</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>de.florianmichael</groupId>
<artifactId>viafabricplus</artifactId>
<version>3.0.2</version> <!-- Get the latest version from releases -->
</dependency>
</dependencies>
```
### To learn more about the API and about addons, you can simply click [here](docs/DEVELOPER_API.md)
## Disclaimer
It cannot be guaranteed that this mod is allowed on specific servers as it can possibly cause problems with anti-cheat plugins.\
***(USE ONLY WITH CAUTION!)***
### If you want to talk with me, feel free to join my [Discord](https://discord.gg/BwWhCHUKDf)

View File

@ -1,14 +1,12 @@
plugins {
id "idea"
id "fabric-loom" version "1.4-SNAPSHOT"
id "maven-publish"
id "fabric-loom" version "1.8-SNAPSHOT"
}
base {
archivesName = project.archives_base_name
version = project.mod_version
group = project.maven_group
archivesName = project.maven_name
version = project.maven_version
description = project.maven_description
}
configurations {
@ -22,6 +20,10 @@ configurations {
repositories {
mavenCentral()
maven {
name = "Jitpack"
url = "https://jitpack.io"
}
maven {
name = "ViaVersion"
url = "https://repo.viaversion.com"
@ -30,21 +32,13 @@ repositories {
name = "Lenni0451"
url = "https://maven.lenni0451.net/everything"
}
maven {
name = "OpenCollab Snapshots"
url = "https://repo.opencollab.dev/maven-snapshots/"
}
maven {
name = "TerraformersMC"
url = "https://maven.terraformersmc.com/releases"
}
maven {
name = "Jitpack"
url = "https://jitpack.io"
content {
includeGroup "com.github.Oryxel"
}
name = "OpenCollab Snapshots"
url = "https://repo.opencollab.dev/maven-snapshots/"
}
}
@ -53,10 +47,14 @@ loom {
}
dependencies {
// Minecraft/Fabric and mods
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_version}:v2"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
modCompileOnly "com.terraformersmc:modmenu:${project.mod_menu_version}"
// Fabric API
modJij(fabricApi.module("fabric-api-base", project.fabric_api_version))
modJij(fabricApi.module("fabric-resource-loader-v0", project.fabric_api_version))
modJij(fabricApi.module("fabric-networking-api-v1", project.fabric_api_version))
@ -65,75 +63,61 @@ dependencies {
modJij(fabricApi.module("fabric-particles-v1", project.fabric_api_version))
modJij(fabricApi.module("fabric-registry-sync-v0", project.fabric_api_version))
modCompileOnly "com.terraformersmc:modmenu:11.0.3"
jij "com.viaversion:viaversion-common:5.1.2-SNAPSHOT"
jij "com.viaversion:viabackwards-common:5.1.2-SNAPSHOT"
jij "net.raphimc:viaaprilfools-common:3.0.5-SNAPSHOT"
jij "net.raphimc:ViaLegacy:3.0.6-SNAPSHOT"
jij ("net.raphimc:ViaBedrock:0.0.13-SNAPSHOT") {
// ViaVersion Libraries
jij "com.viaversion:viaversion-common:${project.viaversion_version}"
jij "com.viaversion:viabackwards-common:${project.viabackwards_version}"
jij "net.raphimc:ViaLegacy:${project.vialegacy_version}"
jij "net.raphimc:ViaAprilFools:${project.viaaprilfools_version}"
jij ("net.raphimc:ViaBedrock:${project.viabedrock_version}") {
exclude group: "io.netty"
exclude group: "io.jsonwebtoken"
exclude group: "com.mojang", module: "brigadier"
}
jij ("net.raphimc:ViaLoader:3.0.5-SNAPSHOT") {
jij ("net.raphimc:ViaLoader:${project.vialoader_version}") {
exclude group: "com.google.guava", module: "guava"
exclude group: "org.slf4j", module: "slf4j-api"
}
jij ("net.raphimc:MinecraftAuth:4.1.1") {
// RaphiMC Libraries
jij ("net.raphimc:MinecraftAuth:${project.minecraftauth_version}") {
exclude group: "org.apache.httpcomponents", module: "httpclient"
exclude group: "com.google.code.gson", module: "gson"
exclude group: "org.slf4j", module: "slf4j-api"
}
jij "net.lenni0451:Reflect:1.4.0"
jij("net.lenni0451:MCPing:1.4.2") {
// Lenni0451 Libraries
jij "net.lenni0451:Reflect:${project.reflect_version}"
jij("net.lenni0451:MCPing:${project.mcping_version}") {
exclude group: "com.google.code.gson", module: "gson"
}
jij("org.cloudburstmc.netty:netty-transport-raknet:1.0.0.CR3-SNAPSHOT") {
// Misc Libraries
jij("org.cloudburstmc.netty:netty-transport-raknet:${project.raknet_transport_version}") {
exclude group: "io.netty"
}
jij "de.florianmichael:Classic4J:2.1.1-SNAPSHOT"
jij "de.florianmichael:Classic4J:${project.classic4j_version}"
// Fabric's jar in jar system doesn't support transitive dependencies, so we have to manually add them
afterEvaluate {
configurations.jij.incoming.resolutionResult.allDependencies.each {
dependencies.include(dependencies.implementation(dependencies.compileOnlyApi(it.requested.toString()) {
transitive = false
}))
configurations.jij.incoming.resolutionResult.allDependencies {
dependencies.include(dependencies.implementation(dependencies.compileOnlyApi(requested.toString())))
}
}
}
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand(
"version": project.version,
"description": project.description,
"implVersion": "git-${project.name}-${project.version}:${latestCommitHash().get()}",
"mcVersion": mcVersion()
)
expand "version": project.version
}
}
String mcVersion() {
if (project.supported_versions.isEmpty()) {
return project.minecraft_version
} else {
return project.supported_versions
}
}
Provider<String> latestCommitHash() {
return providers.exec {
commandLine = ["git", "rev-parse", "--short", "HEAD"]
}.standardOutput.getAsText().map(String::trim)
}
java {
withSourcesJar()
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
jar {
@ -159,37 +143,10 @@ publishing {
publications {
maven(MavenPublication) {
groupId = project.maven_group
artifactId = project.maven_name
version = project.maven_version
artifactId = project.archives_base_name
version = project.mod_version
from components.java
pom {
name = artifactId
description = project.description
url = "https://github.com/ViaVersion/ViaFabricPlus"
licenses {
license {
name = "GPL-3.0 License"
url = "https://github.com/ViaVersion/ViaFabricPlus/blob/main/LICENSE"
}
}
developers {
developer {
id = "FlorianMichael"
name = "EnZaXD"
email = "florian.michael07@gmail.com"
}
developer {
id = "RK_01"
}
}
scm {
connection = "scm:git:git://github.com/ViaVersion/ViaFabricPlus.git"
developerConnection = "scm:git:ssh://github.com/ViaVersion/ViaFabricPlus.git"
url = "github.com/ViaVersion/ViaFabricPlus"
}
}
}
}
}

View File

@ -1,77 +1,14 @@
# Developer API
ViaFabricPlus provides events and various utility functions for other mods to interface with it. Note that including
ViaFabricPlus in your project comes with some requirements:
- The target version is Java 17
- Fabric loom setup (As ViaFabricPlus is a Minecraft mod and has no API-only dependency like other projects)
ViaFabricPlus provides various events and APIs for developers to use. This page explains how to use them.
Since the API is not exposed as standalone submodule (yet), functions that shouldn't be used are marked with
`ApiStatus.Internal`. Further information about certain functions can be found in the Javadoc in the corresponding file.
## How to include the mod as dependency
### Gradle
```groovy
repositories {
mavenCentral()
maven {
name = "ViaVersion"
url = "https://repo.viaversion.com"
}
maven {
name = "Lenni0451"
url = "https://maven.lenni0451.net/everything"
}
maven {
name = "Jitpack"
url = "https://jitpack.io"
content {
includeGroup "com.github.Oryxel"
}
}
}
dependencies {
modImplementation("de.florianmichael:ViaFabricPlus:x.x.x") // Get the latest version from releases
}
```
### Maven
```xml
<repositories>
<repository>
<id>viaversion</id>
<url>https://repo.viaversion.com</url>
</repository>
<repository>
<id>lenni0451</id>
<url>https://maven.lenni0451.net/everything</url>
</repository>
<repository>
<id>jitpack</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>de.florianmichael</groupId>
<artifactId>ViaFabricPlus</artifactId>
<version>x.x.x</version> <!-- Get the latest version from releases -->
</dependency>
</dependencies>
```
## Interacting with Events
ViaFabricPlus events are the intended way of interacting with the mod.
Events are fired in various situations and are using the [Fabric Event API](https://fabricmc.net/wiki/tutorial:events).
#### Example
## Events
ViaFabricPlus events are using the [Fabric Event API](https://fabricmc.net/wiki/tutorial:events). You can register to them like this:
```java
ChangeProtocolVersionCallback.EVENT.register((oldVersion, newVersion) -> {
System.out.println("Version changed to " + newVersion.getName());
});
```
### List of events/callbacks
### ViaFabricPlus has 8 events at the moment
| Callback class name | Description |
|--------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ChangeProtocolVersionCallback | Called when the user changes the target version in the screen, or if you connect to a server for which a specific version has been selected, you disconnect, the event for the actual version is also called. |
@ -83,21 +20,71 @@ ChangeProtocolVersionCallback.EVENT.register((oldVersion, newVersion) -> {
| RegisterSettingsCallback | Called after the default setting groups are loaded and before the setting config is loaded |
| LoadSaveFilesCallback | Called before and after the save files are loaded |
### Other API calls
ViaFabricPlus uses [ViaVersion](https://github.com/ViaVersion/ViaVersion) for protocol translation, so the ViaVersion API can be used.
The general API endpoint for ViaFabricPlus specifics is `ProtocolTranslator`
## Get and set the current protocol version
```java
// Get and change the current selected version
final ProtocolVersion version = ProtocolTranslator.getTargetVersion();
if (version == ProtocolVersion.v1_8) {
ProtocolTranslator.setTargetVersion(ProtocolVersion.v1_9);
}
// Gets the ViaVersion user connection object for raw packet sending using ViaVersion API
final UserConnection user = ProtocolTranslator.getPlayNetworkUserConnection();
if (user == null) {
// Mod not active
final VersionEnum version = ProtocolHack.getTargetVersion();
if (version == VersionEnum.r1_8) {
ProtocolHack.setTargetVersion(VersionEnum.r1_9);
}
```
## Get a Minecraft ClientConnection by channel
```java
final ClientConnection connection = channel.attr(ProtocolHack.CLIENT_CONNECTION_ATTRIBUTE_KEY).get();
```
## Interact with UserConnection objects
```java
// If ViaVersion is translating, this field will return the user connection of the client
final UserConnection userConnection = ProtocolHack.getPlayNetworkUserConnection();
// If you need a dummy user connection for testing, you can use this method
final UserConnection cursedDummy = ProtocolHack.createDummyUserConnection(ProtocolHack.NATIVE_VERSION, VersionEnum.r1_18_2);
// The cursedDummy field now contains all protocols from the native version to 1.18.2
```
## ViaVersion internals
### Add CustomPayload channels for versions below 1.13
In order to receive custom payloads with custom channels in versions below 1.13, you need to register them, that's what you do:
```java
Protocol1_13To1_12_2.MAPPINGS.getChannelMappings().put("FML|HS", "fml:hs");
```
### Check if an item exists in a specific version
```java
final VersionRange range = ItemRegistryDiff.ITEM_DIFF.get(Items.WRITABLE_BOOK); // If an item does not appear in the item map, it has always existed
// The Range class then contains all versions in which the item occurs.
// https://github.com/ViaVersion/ViaLoader
if (ItemRegistryDiff.contains(Items.STONE, VersionRange.andOlder(VersionEnum.r1_8))) {
// Do something
}
```
### Creating own settings for the settings screen
```java
public class ExampleSettingGroup extends SettingGroup {
private static final ExampleSettingGroup INSTANCE = new ExampleSettingGroup();
public final BooleanSetting test = new BooleanSetting(this, Text.of("Test"), false);
public ExampleSettingGroup() {
super("Example");
}
public static ExampleSettingGroup global() {
return INSTANCE;
}
}
```
and then you register the setting group in your onLoad method
```java
RegisterSettingsCallback.EVENT.register(state -> {
if (state == RegisterSettingsCallback.State.POST) {
ViaFabricPlus.global().getSettingsManager().addGroup(ExampleSettingGroup.INSTANCE);
}
});
```

View File

@ -1,99 +0,0 @@
# Updating instructions for the project
These steps are the usual process for updating ViaFabricPlus to a new version of the game. If you're unsure about something, ask in the ViaVersion discord.
1. Update all upstream versions in `gradle.properties`. The main versions you need to update are:
- `minecraft_version`
- `yarn_version`
- `loader_version`
- `fabric_api_version`
- `supported_versions` (if necessary)
As well as the versions in the `dependencies` block in the `build.gradle` file.
2. Increment the version number in `gradle.properties` by at least a minor version (e.g. 1.0.0 -> 1.1.0)
3. Check all data dumps and diffs in the fixes/data package and update them if necessary, here is a list of some critical ones:
- `ResourcePackHeaderDiff` (add the new version at the top of the list)
- `ItemRegistryDiff` (add all new items/blocks added in the new version)
- `EntityDimensionDiff` (add entity dimension changes)
4. Update the `NATIVE_VERSION` field in the ProtocolTranslator class to the new version
5. Update protocol constants in the `ViaFabricPlusProtocol` class
-------------
6. Check all mixins in the injection package if they still apply correctly, here is a list of some critical ones:
- `MixinClientWorld#tickEntity` and `MixinClientWorld#tickPassenger`
- `MixinPlayer#getBlockBreakingSpeed`
7. mDecompile the game source code with the tool of your choice.
8. Try to compile the mod and start porting the code until all existing fixes are working again.
9. Diff the game code with the code of the previous version (e.g. using git) and implement all changes that could be relevant for ViaFabricPlus, those are:
- General logic changes (e.g. `if (a && b)` -> `if (b || a)`)
- Changes to the movement code (e.g. `player.yaw` -> `player.headYaw`)
- Networking changes (e.g. sending a new packet / changing the packet structure)
- Changes to visuals (e.g. animation changes)
- Note: ViaVersion already implements most gameplay related changes for us, but you should always check for edge-cases. Since ViaVersion
is primarily a server side plugin, it does not take care of client-side related / deeper changes. ViaFabricPlus often has to inject into
ViaVersion code to improve funcitonality for the client.
**Read more about which fixes should be added [HERE](../CONTRIBUTING.md#adding-protocol-new-fixes---which-are-important-and-which-arent)**
- From experience, the following packages contain the usual important changes (mojang mappings):
- `net.minecraft`
- `net.minecraft.client`
- `net.minecraft.client.gui`
- `net.minecraft.client.multiplayer`
- `net.minecraft.client.player`
- `net.minecraft.util`
- `net.minecraft.world`
- `net.minecraft.world.entity`
- `net.minecraft.world.inventory`
- `net.minecraft.world.item`
- `net.minecraft.world.level`
- `net.minecraft.world.level.block`
- While the following packages (mojang mappings) can be skipped completely (most of the time):
- `com.mojang`
- `net.minecraft.advancements`
- `net.minecraft.commands`
- `net.minecraft.data`
- `net.minecraft.gametest`
- `net.minecraft.realms`
- `net.minecraft.recipebook`
- `net.minecraft.references`
- `net.minecraft.resources`
- `net.minecraft.server`
- `net.minecraft.sounds`
- `net.minecraft.stats`
- `net.minecraft.tags`
10. Check the ViaVersion/upstream protocol implementation for issues and report them if necessary or if these issues can't be fixed,
without tons of work, implement a workaround in ViaFabricPlus.
11. Run the game and check all GUIs and other visuals for issues.
12. Clean your code and make sure it is readable and understandable, clientside fixes are sorted by their protocol versions, having
newer fixes at the top of the file.
-------------
13. Create a pull request and wait for it to be reviewed and merged.
14. You're done, congrats!
## Git branches
- `main`: The main branch, this is where all changes are merged into
- `dev`: Used for changes which needs reviewing by all developers, usually merged into `main` shortly after
- `update/*`: Update branches, these are used to port ViaFabricPlus to newer versions of the game
- `<version>`: Final release branches sorted by their Minecraft version (e.g. `1.8.9`, `1.16.5`, `1.17.1`, ...)
There are also older formats which aren't used anymore:
- `recode/*`: Recode branches, these are used to port ViaFabricPlus to newer versions of the game or rewrite big parts of the code
- `backport/*`: Backport branches, these are used to backport newer ViaFabricPlus versions to older versions of the game
## Versioning
The versioning should only be updated every release and should only have one update between each release.
- The versioning scheme is `major.minor.patch`, where:
- `major` is incremented when breaking changes are made
- `minor` is incremented when new features are added
- `patch` is incremented when bug fixes are made
This scheme is used as follows:
- `Major` versions are only incremented with breaking and fundamental changes to the existing codebase, such as migrating mappings
or refactoring the entire codebase.
- `Minor` versions are incremented when the mod gets ported to a new version of the game or when huge features are added /
upstream changes are implemented.
- `Patch` versions are incremented when bug fixes are made or small features are added, they are the usual version increment.

View File

@ -0,0 +1,65 @@
# Updating instructions for the project
## Update translation files
Translation files are located in `src/main/resources/assets/viafabricplus/lang/`. To update them, you need to do the following:
1. Copy the `en_us.json` file and rename it to the language code of the language you want to update (e.g. `de_de.json` for German)
2. Translate all values in the file to the language you want to update
3. Do not change the keys of the values, only the values themselves
4. Do not change the formatting of the file (e.g. the spaces between the keys and values or the order of the keys)
5. Try to be consistent with Minecraft language files.
6. Take a look at UN's guidelines for Gender-inclusive language: https://www.un.org/en/gender-inclusive-language/guidelines.shtml
7. Create a pull request and wait for it to be reviewed and merged.
8. You're done, congrats!
## Add a new feature or fix a bug
1. Create a new branch for your feature/bugfix (e.g. `feature/fix-xyz` or `fix/fix-xyz`)
2. Implement your feature/bugfix and make sure it works correctly
3. Clean your code and make sure it is readable and understandable (e.g. use proper variable names)
4. Use the Google java code style (https://google.github.io/styleguide/javaguide.html) and format your code accordingly
5. If you're changing API, make sure to update the documentation in the `docs` folder, add javadocs to your code and don't break backwards compatibility if not necessary
6. Increment the version number in `gradle.properties` by at least a patch version (e.g. 1.0.0 -> 1.0.1)
7. Create a pull request and wait for it to be reviewed and merged.
8. You're done, congrats!
## Update to a new Minecraft version
1. Update all upstream versions in `gradle.properties`. The main versions you need to update are:
- `minecraft_version`
- `yarn_mappings`
- `loader_version`
- `fabric_api_version`
- `viaversion_version`
- `viabackwards_version`
- `mod_menu_version`
2. Update the `NATIVE_VERSION` field in the ProtocolHack class to the new version
3. Check all mixins in the injection package if they still apply correctly, here is a list of some critical ones:
- `MixinClientPlayerEntity#removeBl8Boolean`
- `MixinClientWorld#tickEntity` and `MixinClientWorld#tickPassenger`
- `MixinPlayer#getBlockBreakingSpeed`
4. Decompile the game source code with the tool of your choice.
5. Check all data dumps and diffs in the fixes/data package and update them if necessary, here is a list of some critical ones:
- `ResourcePackHeaderDiff` (add the new version at the top of the list)
- `ItemRegistryDiff` (add all new items/blocks added in the new version)
6. Diff the game code with the code of the previous version (e.g. using git) and implement all changes that could be relevant for ViaFabricPlus, those are:
- General logic changes (e.g. `if (a && b)` -> `if (b || a)`)
- Changes to the movement code (e.g. `player.yaw` -> `player.headYaw`)
- Networking changes (e.g. sending a new packet / changing the packet structure)
- Changes to visuals (e.g. animation changes)
- Note: ViaVersion already implements most gameplay related changes for us, but you should always check for edge-cases. Since ViaVersion
is primarily a server side plugin, it does not take care of client-side related / deeper changes.
=> If you are unsure if a change is relevant, ask in the ViaVersion discord, in general you should only implement changes
which could be detected by a server side anti cheat.
7. Check the ViaVersion/upstream protocol implementation for issues and report them if necessary or if these issues can't be fixed,
without tons of work, implement a workaround in ViaFabricPlus.
8. Run the game and check all GUIs and other visuals for issues.
9. Clean your code and make sure it is readable and understandable, clientside fixes are sorted by their protocol versions, having
newer fixes at the top of the file.
10. Increment the version number in `gradle.properties` by at least a minor version (e.g. 1.0.0 -> 1.1.0)
11. Create a pull request and wait for it to be reviewed and merged.
12. You're done, congrats!
## Git branches
- `main`: The main branch, this is where all changes are merged into
- `backport/*`: Backport branches, these are used to backport newer ViaFabricPlus versions to older versions of the game
- `recode/*`: Recode branches, these are used to port ViaFabricPlus to newer versions of the game or rewrite big parts of the code
- `<version>`: Final release branches sorted by their Minecraft version (e.g. `1.8.9`, `1.16.5`, `1.17.1`, ...)

View File

@ -6,12 +6,12 @@ where you can change the settings and set the protocol version, the position of
Settings -> General -> multiplayer screen button orientation.
![](preview/multiplayer.png)
![](preview/protocol_selection.png)
![](preview/protocol.png)
In the Add/Edit Server screen there is a button where you can select a specific version for this server, when you ping or connect to this server,
ViaFabricPlus will use the version set there, the versions are stored in the servers.dat too
![](preview/set_version_for_server.png)
![](preview/force.png)
If you don't want to specify a specific version anymore, you can simply press the button and select **"Cancel and reset"**.
@ -22,18 +22,15 @@ You can use the ViaVersion commands with **/viafabricplus** or **/viaversion**,
### Settings<br>
For users only the settings in the **General**, **Bedrock**, **Authentication** and **Visual** tab are relevant, the other settings are only for developers, you should not change the settings in the **Debug** tab if you don't know what you are doing.
![](preview/settings-selection.png)
The settings are stored in the `settings.json` file. Account credentials for Bedrock/ClassiCube in `accounts.json`.
![](preview/settings.png)
### Configuring the protocol translation libraries
To change the protocol translation settings/features you can look into the config folder. You can find 4 config files there depending on the platforms loaded:
To change the protocol translation settings/features you can look into the ViaLoader folder. You can find 4 config files there depending on the platforms loaded:
- `viaversion.yml` (ViaVersion)
- `viabackwards.yml` (ViaBackwards)
- `vialegacy.yml` (ViaLegacy)
- `viabedrock.yml` (ViaBedrock)
- `viaaprilfools.yml` (ViaAprilFools)
- viaversion.yml (ViaVersion)
- viabackwards.yml (ViaBackwards)
- vialegacy.yml (ViaLegacy)
- viabedrock.yml (ViaBedrock)
On it's first launch, ViaFabricPlus will generate the config files with proper default values. Don't touch the config files if you don't know what you are doing.
@ -45,21 +42,17 @@ The debug HUD can be enabled in the settings, it shows some useful information a
Keep in mind that the Java -> Bedrock support is still in beta phase, and therefore many things are not implemented
yet and there is no guarantee that everything will work as it should.
To log in to a Bedrock account you can press the button **"Click to set account for Bedrock edition"** in the settings.
#### Bedrock Realms
If you have a Bedrock account set in the settings, you can view its Bedrock Realms in the "Server lists" screen (can be found at the left bottom of the main GUI).
![](preview/bedrock_realms.png)
To log in to a Bedrock account you can press the button **"Click to set account for Bedrock edition"** in the settings,
then you can log in via device login, the account logged in there will be stored in **/minecraft./config/viafabricplus/accounts.json**.
### ClassiCube and BetaCraft integration
In the main GUI there is a "Server lists" button where you can go to ClassiCube and BetaCraft server lists.
In the main GUI there is an extra button for ClassiCube and BetaCraft, both buttons send API requests to the respective platforms to get the respective server list.
## BetaCraft
![](preview/betacraft_servers.png)
![](preview/betacraft.png)
## ClassiCube
![](preview/classicube_servers.png)
![](preview/classicube.png)
For ClassiCube you need an account, which you can make on the official website (https://www.classicube.net/), in case ClassiCube requires MultiFactor, an extra GUI will open in ViaFabricPlus.
![](preview/classicube_login.png)
The ClassiCube account will be stored in **/minecraft./config/viafabricplus/accounts.json**.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 KiB

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 155 KiB

View File

Before

Width:  |  Height:  |  Size: 746 KiB

After

Width:  |  Height:  |  Size: 746 KiB

View File

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

@ -2,17 +2,33 @@
org.gradle.jvmargs=-Xmx8G
org.gradle.parallel=true
# Project Details
maven_group=de.florianmichael
maven_name=ViaFabricPlus
maven_version=3.5.2-SNAPSHOT
maven_description=Fabric mod to connect to EVERY Minecraft server version (Release, Beta, Alpha, Classic, Snapshots, Bedrock) with QoL fixes to the gameplay
# Minecraft/Fabric
minecraft_version=1.21.3
yarn_version=1.21.3+build.2
loader_version=0.16.9
fabric_api_version=0.108.0+1.21.3
minecraft_version=1.20.4
yarn_mappings=1.20.4+build.3
loader_version=0.15.3
fabric_api_version=0.91.3+1.20.4
# Set to empty to use the Minecraft version above
supported_versions=>=1.21.2 <=1.21.3
# Project Details
mod_version=3.0.5
maven_group=de.florianmichael
archives_base_name=viafabricplus
# ViaVersion Libraries
viaversion_version=4.10.0-23w51b-SNAPSHOT
viabackwards_version=4.10.0-23w51b-SNAPSHOT
vialegacy_version=2.2.22-SNAPSHOT
viaaprilfools_version=2.0.11-SNAPSHOT
viabedrock_version=0.0.4-SNAPSHOT
vialoader_version=2.2.13-SNAPSHOT
# RaphiMC Libraries
minecraftauth_version=3.1.0-SNAPSHOT
raknet_transport_version=1.0.0.CR1-SNAPSHOT
# Lenni0451 Libraries
reflect_version=1.3.1
mcping_version=1.4.0
# Misc Libraries
mod_menu_version=9.0.0
classic4j_version=2.0.1

Binary file not shown.

View File

@ -1,7 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=57dafb5c2622c6cc08b993c85b7c06956a2f53536432a30ead46166dbca0f1e9
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

21
gradlew vendored
View File

@ -15,8 +15,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@ -57,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -86,8 +84,7 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@ -148,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@ -156,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -205,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \

22
gradlew.bat vendored
View File

@ -13,8 +13,6 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@ -45,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
@ -59,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail

View File

@ -1,7 +1,6 @@
# Deploys the latest stable JDK 21 available and sets it to default without having to manually specify it here,
# Deploys the latest stable JDK available and sets it to default without having to manually specify it here,
# Which includes using temurin as the distribution.
before_install:
- curl -s "https://get.sdkman.io" | bash
- source ~/.sdkman/bin/sdkman-init.sh
- sdk install java 21.0.3-tem
- sdk use java 21.0.3-tem
- curl -s "https://get.sdkman.io" | bash
- source ~/.sdkman/bin/sdkman-init.sh
- sdk install java

View File

@ -21,7 +21,8 @@ package de.florianmichael.viafabricplus;
import de.florianmichael.viafabricplus.event.PostGameLoadCallback;
import de.florianmichael.viafabricplus.fixes.ClientsideFixes;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.protocolhack.util.VersionEnumExtension;
import de.florianmichael.viafabricplus.save.SaveManager;
import de.florianmichael.viafabricplus.settings.SettingsManager;
import de.florianmichael.viafabricplus.util.ClassLoaderPriorityUtil;
@ -33,36 +34,20 @@ import java.io.File;
import java.util.concurrent.CompletableFuture;
/*
* TODO | Port 1.21.3
* - VehicleMovePacket handling now has distance check in ClientPlayNetworkHandler
* - Illusioner/Sniffer don't override visibility bounding box anymore
* - AbstractFireabll/EyeOfEnder#shouldRender new
* - Entity#baseTick doesn't set prev rotation anymore at top
* - LivingEntity movement code got refactored completely
* - BundleItem#use, ConsumableComponent behaviour in use functions
* - Check all screen handlers for changes
*
* TODO | Port 1.20.6
* - ClientPlayerInteractionManager#interactBlockInternal added new condition
* - Command arguments (Probably not everything worth, but least them with nbt)
* - Entity attachment calculation got changed completely
* - Particle handling has slightly changed
* - BookViewScreen/BookEditScreen networking handling
* - SetEquipment packet now only accepts living entities
* - Wolf interaction
*
* TODO | General
* - Make recipe fixes dynamic instead of a data dump in java classes
* - Check if relevant for protocol translation: TakeItemEntityPacket isEmpty case (1.20 -> 1.20.1 change)
* - Check previous Donkey interaction fix (see git logs)
* - Window interactions in <= 1.16.5 has changed and can be detected by the server
* - Most CTS protocol features aren't supported (see https://github.com/ViaVersion/ViaFabricPlus/issues/181)
* - Most CPE features aren't implemented correctly (see https://github.com/ViaVersion/ViaFabricPlus/issues/152)
* - Via: 1.13 -> 1.12.2 block entities recode
* - OXYGEN_BONUS 1.21 -> 1.20.5 handling is missing (only visual)
* - Check if MixinPlayerScreenHandler.injectTransferSlot is needed? Check git log
*
* TODO | Movement
* - Blip-jumping is not supported in <= 1.13.2 (https://github.com/ViaVersion/ViaFabricPlus/issues/225)
* - 1.8 lava movement
* - 1.13.2 water movement
* - X/Z Face based jump movement in <= 1.13.2 is broken (https://github.com/ViaVersion/ViaFabricPlus/issues/189)
* - Collision hit boxes has been changed (https://github.com/ViaVersion/ViaFabricPlus/issues/195)
* - Blip-jumping is not supported in <= 1.8.9 (https://github.com/ViaVersion/ViaFabricPlus/issues/225)
* - Older versions don't clamp positions when teleporting (Is this important?)
*/
public class ViaFabricPlus {
@ -76,21 +61,19 @@ public class ViaFabricPlus {
private CompletableFuture<Void> loadingFuture;
public void init() {
@SuppressWarnings("ResultOfMethodCallIgnored")
public void bootstrap() {
directory.mkdir();
ClassLoaderPriorityUtil.loadOverridingJars(directory); // Load overriding jars first so other code can access the new classes
VersionEnumExtension.init(); // Register extra VersionEnum values
settingsManager = new SettingsManager();
saveManager = new SaveManager(settingsManager);
ClientsideFixes.init(); // Init clientside related fixes
loadingFuture = ProtocolTranslator.init(directory); // Init ViaVersion protocol translator platform
loadingFuture = ProtocolHack.init(directory); // Init ViaVersion protocol translator platform
// Block game loading until ViaVersion has loaded
PostGameLoadCallback.EVENT.register(() -> {
loadingFuture.join();
saveManager.postInit();
});
PostGameLoadCallback.EVENT.register(() -> loadingFuture.join()); // Block game loading until ViaVersion has loaded
}
public static ViaFabricPlus global() {

View File

@ -19,9 +19,9 @@
package de.florianmichael.viafabricplus.event;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.raphimc.vialoader.util.VersionEnum;
/**
* This event is fired when the user changes the target version in the screen, or if the user joins a server with a different version.
@ -35,6 +35,6 @@ public interface ChangeProtocolVersionCallback {
}
});
void onChangeProtocolVersion(final ProtocolVersion oldVersion, final ProtocolVersion newVersion);
void onChangeProtocolVersion(final VersionEnum oldVersion, final VersionEnum newVersion);
}

View File

@ -21,7 +21,7 @@ package de.florianmichael.viafabricplus.event;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.raphimc.vialegacy.protocol.classic.c0_30cpetoc0_28_30.data.ClassicProtocolExtension;
import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.data.ClassicProtocolExtension;
/**
* This event is fired when a classic protocol extension is loaded.

View File

@ -19,17 +19,12 @@
package de.florianmichael.viafabricplus.event;
import de.florianmichael.viafabricplus.save.AbstractSave;
import de.florianmichael.viafabricplus.save.SaveManager;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
/**
* This event is fired when loading save files:
* <ul>
* <li>{@link State#PRE} before loading save files</li>
* <li>{@link State#POST} after loading save files</li>
* <li>{@link State#POST_INIT} after loading save files and calling {@link AbstractSave#postInit()} functions</li>
* This event is fired when ViaFabricPlus has loaded its save files, and before it starts reading the values from the save files.
*/
public interface LoadSaveFilesCallback {
@ -42,7 +37,7 @@ public interface LoadSaveFilesCallback {
void onLoadSaveFiles(final SaveManager saveManager, final State state);
enum State {
PRE, POST, POST_INIT
PRE, POST
}
}

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned;
package de.florianmichael.viafabricplus.fixes;
import net.minecraft.util.ActionResult;

View File

@ -17,40 +17,38 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.visual;
package de.florianmichael.viafabricplus.fixes;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.protocols.v1_8to1_9.data.ArmorTypes1_8;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ArmorType;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.settings.impl.VisualSettings;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import org.jetbrains.annotations.ApiStatus;
import java.util.UUID;
@ApiStatus.Internal
public class ArmorHudEmulation1_8 {
private static final UUID ARMOR_POINTS_UUID = UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150");
private static double previousArmorPoints = 0;
static {
ClientTickEvents.START_WORLD_TICK.register(world -> {
public static void init() {
ClientTickEvents.START_CLIENT_TICK.register(world -> {
if (!VisualSettings.global().emulateArmorHud.isEnabled()) {
return;
}
if (MinecraftClient.getInstance().player != null) {
final UserConnection userConnection = ProtocolTranslator.getPlayNetworkUserConnection();
final UserConnection userConnection = ProtocolHack.getPlayNetworkUserConnection();
if (userConnection != null) {
try {
sendArmorUpdate(userConnection);
@ -64,15 +62,11 @@ public class ArmorHudEmulation1_8 {
});
}
public static void init() {
// Calls the static block
}
private static void sendArmorUpdate(final UserConnection userConnection) {
private static void sendArmorUpdate(final UserConnection userConnection) throws Exception {
// Calculate the armor points.
int armor = 0;
for (final ItemStack stack : MinecraftClient.getInstance().player.getInventory().armor) {
armor += ArmorTypes1_8.findByType(Registries.ITEM.getId(stack.getItem()).toString()).getArmorPoints();
armor += ArmorType.findByType(Registries.ITEM.getId(stack.getItem()).toString()).getArmorPoints();
}
// We only want to update the armor points if they actually changed.
@ -81,16 +75,16 @@ public class ArmorHudEmulation1_8 {
}
previousArmorPoints = armor;
final PacketWrapper updateAttributes = PacketWrapper.create(ClientboundPackets1_9.UPDATE_ATTRIBUTES, userConnection);
updateAttributes.write(Types.VAR_INT, MinecraftClient.getInstance().player.getId());
updateAttributes.write(Types.INT, 1);
updateAttributes.write(Types.STRING, "generic.armor");
updateAttributes.write(Types.DOUBLE, 0.0D);
updateAttributes.write(Types.VAR_INT, 1);
updateAttributes.write(Types.UUID, ARMOR_POINTS_UUID);
updateAttributes.write(Types.DOUBLE, (double) armor);
updateAttributes.write(Types.BYTE, (byte) 0);
updateAttributes.scheduleSend(Protocol1_8To1_9.class);
final PacketWrapper entityProperties = PacketWrapper.create(ClientboundPackets1_9.ENTITY_PROPERTIES, userConnection);
entityProperties.write(Type.VAR_INT, MinecraftClient.getInstance().player.getId());
entityProperties.write(Type.INT, 1);
entityProperties.write(Type.STRING, "generic.armor");
entityProperties.write(Type.DOUBLE, 0.0D);
entityProperties.write(Type.VAR_INT, 1);
entityProperties.write(Type.UUID, ARMOR_POINTS_UUID);
entityProperties.write(Type.DOUBLE, (double) armor);
entityProperties.write(Type.BYTE, (byte) 0);
entityProperties.scheduleSend(Protocol1_9To1_8.class);
}
}

View File

@ -17,20 +17,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned;
package de.florianmichael.viafabricplus.fixes;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec2f;
import net.minecraft.util.math.Vec3d;
import net.raphimc.vialoader.util.VersionEnum;
import org.apache.commons.lang3.tuple.Pair;
public class ClientPlayerInteractionManager1_18_2 {
@ -38,10 +37,10 @@ public class ClientPlayerInteractionManager1_18_2 {
private final Object2ObjectLinkedOpenHashMap<Pair<BlockPos, PlayerActionC2SPacket.Action>, Pair<Vec3d, Vec2f>> unAckedActions = new Object2ObjectLinkedOpenHashMap<>();
public void trackPlayerAction(final PlayerActionC2SPacket.Action action, final BlockPos blockPos) {
final ClientPlayerEntity player = MinecraftClient.getInstance().player;
final var player = MinecraftClient.getInstance().player;
final Vec2f rotation;
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_16_1)) {
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_16_1)) {
rotation = null;
} else {
rotation = new Vec2f(player.getYaw(), player.getPitch());
@ -52,15 +51,14 @@ public class ClientPlayerInteractionManager1_18_2 {
public void handleBlockBreakAck(final BlockPos blockPos, final BlockState expectedState, final PlayerActionC2SPacket.Action action, final boolean allGood) {
final var player = MinecraftClient.getInstance().player;
if (player == null) return;
final var world = MinecraftClient.getInstance().getNetworkHandler().getWorld();
final var oldPlayerState = unAckedActions.remove(Pair.of(blockPos, action));
final var actualState = world.getBlockState(blockPos);
if ((oldPlayerState == null || !allGood || action != PlayerActionC2SPacket.Action.START_DESTROY_BLOCK && actualState != expectedState) && (actualState != expectedState || ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_15_2))) {
if ((oldPlayerState == null || !allGood || action != PlayerActionC2SPacket.Action.START_DESTROY_BLOCK && actualState != expectedState) && (actualState != expectedState || ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_15_2))) {
world.setBlockState(blockPos, expectedState, Block.NOTIFY_ALL | Block.FORCE_STATE);
if (oldPlayerState != null && (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_16_1) || (world == player.getWorld() && player.collidesWithStateAtPos(blockPos, expectedState)))) {
if (oldPlayerState != null && (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_16_1) || (world == player.getWorld() && player.collidesWithStateAtPos(blockPos, expectedState)))) {
final Vec3d oldPlayerPosition = oldPlayerState.getKey();
if (oldPlayerState.getValue() != null) {
player.updatePositionAndAngles(oldPlayerPosition.x, oldPlayerPosition.y, oldPlayerPosition.z, oldPlayerState.getValue().x, oldPlayerState.getValue().y);

View File

@ -19,39 +19,24 @@
package de.florianmichael.viafabricplus.fixes;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback;
import de.florianmichael.viafabricplus.event.LoadClassicProtocolExtensionCallback;
import de.florianmichael.viafabricplus.event.PostGameLoadCallback;
import de.florianmichael.viafabricplus.fixes.data.EntityDimensionDiff;
import de.florianmichael.viafabricplus.fixes.classic.CPEAdditions;
import de.florianmichael.viafabricplus.fixes.classic.GridItemSelectionScreen;
import de.florianmichael.viafabricplus.fixes.data.ResourcePackHeaderDiff;
import de.florianmichael.viafabricplus.fixes.data.recipe.Recipes1_11_2;
import de.florianmichael.viafabricplus.fixes.versioned.EnchantmentAttributesEmulation1_20_6;
import de.florianmichael.viafabricplus.fixes.versioned.classic.CPEAdditions;
import de.florianmichael.viafabricplus.fixes.versioned.classic.GridItemSelectionScreen;
import de.florianmichael.viafabricplus.fixes.versioned.visual.ArmorHudEmulation1_8;
import de.florianmichael.viafabricplus.fixes.versioned.visual.FootStepParticle1_12_2;
import de.florianmichael.viafabricplus.fixes.versioned.visual.UnicodeFontFix1_12_2;
import de.florianmichael.viafabricplus.injection.access.IClientConnection;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.settings.impl.BedrockSettings;
import de.florianmichael.viafabricplus.settings.impl.VisualSettings;
import de.florianmichael.viafabricplus.util.DataCustomPayload;
import de.florianmichael.viafabricplus.fixes.entity.EntityDimensionReplacements;
import de.florianmichael.viafabricplus.fixes.particle.FootStepParticle;
import de.florianmichael.viafabricplus.injection.ViaFabricPlusMixinPlugin;
import net.minecraft.block.*;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.font.FontStorage;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.registry.Registries;
import net.raphimc.viaaprilfools.api.AprilFoolsProtocolVersion;
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
import net.raphimc.viabedrock.protocol.data.ProtocolConstants;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocol.classic.c0_30cpetoc0_28_30.data.ClassicProtocolExtension;
import net.raphimc.vialegacy.protocol.classic.c0_30cpetoc0_28_30.storage.ExtensionProtocolMetadataStorage;
import org.jetbrains.annotations.ApiStatus;
import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.data.ClassicProtocolExtension;
import net.raphimc.vialoader.util.VersionEnum;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
@ -64,35 +49,33 @@ public class ClientsideFixes {
/**
* Contains all tasks that are waiting for a packet to be received, this system can be used to sync ViaVersion tasks with the correct thread
*/
private static final Map<String, Consumer<RegistryByteBuf>> PENDING_EXECUTION_TASKS = new ConcurrentHashMap<>();
private static final Map<String, Consumer<PacketByteBuf>> PENDING_EXECUTION_TASKS = new ConcurrentHashMap<>();
/**
* This identifier is an internal identifier used to identify packets that are sent by ViaFabricPlus
* This identifier is an internal identifier that is used to identify packets that are sent by ViaFabricPlus
*/
@ApiStatus.Internal
public static final String PACKET_SYNC_IDENTIFIER = UUID.randomUUID() + ":" + UUID.randomUUID();
/**
* This is an incremental index used for tablist entries to implement FIFO behavior <= 1.7
* This identifier is an internal identifier used to store the item count in <= 1.10 to implement negative item counts
*/
@ApiStatus.Internal
public static int globalTablistIndex = 0;
public static final String ITEM_COUNT_NBT_TAG = "VFP_1_10_ItemCount_" + System.currentTimeMillis();
static {
/**
* The current chat limit
*/
private static int currentChatLength = 256;
public static void init() {
// Register additional CPE features
CPEAdditions.modifyMappings();
// Check if the pack format mappings are correct
ResourcePackHeaderDiff.checkOutdated();
UnicodeFontFix1_12_2.init();
PostGameLoadCallback.EVENT.register(() -> {
// Handle clientside enchantment calculations in <= 1.20.6
EnchantmentAttributesEmulation1_20_6.init();
// Handles and updates entity dimension changes in <= 1.17
EntityDimensionDiff.init();
EntityDimensionReplacements.init();
// Ticks the armor hud manually in <= 1.8.x
ArmorHudEmulation1_8.init();
@ -100,7 +83,24 @@ public class ClientsideFixes {
// Reloads some clientside stuff when the protocol version changes
ChangeProtocolVersionCallback.EVENT.register((oldVersion, newVersion) -> MinecraftClient.getInstance().execute(() -> {
VisualSettings.global().filterNonExistingGlyphs.onValueChanged();
// Calculates the current chat length limit
if (newVersion.isOlderThanOrEqualTo(VersionEnum.c0_28toc0_30)) {
currentChatLength = 64 - (MinecraftClient.getInstance().getSession().getUsername().length() + 2);
} else if (newVersion.equals(VersionEnum.bedrockLatest)) {
currentChatLength = 512;
} else if (newVersion.isOlderThanOrEqualTo(VersionEnum.r1_9_3tor1_9_4)) {
currentChatLength = 100;
} else {
currentChatLength = 256;
}
if (!ViaFabricPlusMixinPlugin.DASH_LOADER_PRESENT) {
// Clear all font caches to enforce a reload of all fonts (this is needed because we change the font renderer behavior)
for (FontStorage storage : MinecraftClient.getInstance().fontManager.fontStorages.values()) {
storage.glyphRendererCache.clear();
storage.glyphCache.clear();
}
}
// Reloads all bounding boxes of the blocks that we changed
for (Block block : Registries.BLOCK) {
@ -120,95 +120,47 @@ public class ClientsideFixes {
}
// Rebuilds the item selection screen grid
if (newVersion.olderThanOrEqualTo(LegacyProtocolVersion.c0_28toc0_30)) {
if (newVersion.isOlderThanOrEqualTo(VersionEnum.c0_28toc0_30)) {
GridItemSelectionScreen.INSTANCE.itemGrid = null;
}
// Reloads the clientside recipes
if (newVersion.olderThanOrEqualTo(ProtocolVersion.v1_11_1)) {
Recipes1_11_2.reset();
}
// Reload sound system when switching between 3D Shareware and normal versions
if (oldVersion.equals(AprilFoolsProtocolVersion.s3d_shareware) || newVersion.equals(AprilFoolsProtocolVersion.s3d_shareware)) {
MinecraftClient.getInstance().getSoundManager().reloadSounds();
}
}));
// Register the footstep particle
FootStepParticle1_12_2.init();
// Register the custom payload packet for sync tasks
DataCustomPayload.init();
}
public static void init() {
// Calls the static block
}
/**
* Calculates the maximum chat length for the selected protocol version in {@link ProtocolTranslator#getTargetVersion()}
*
* @return The maximum chat length
*/
public static int getChatLength() {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(LegacyProtocolVersion.c0_28toc0_30)) {
final ClientPlayNetworkHandler handler = MinecraftClient.getInstance().getNetworkHandler();
final ExtensionProtocolMetadataStorage extensionProtocol = ((IClientConnection) handler.getConnection()).viaFabricPlus$getUserConnection().get(ExtensionProtocolMetadataStorage.class);
if (extensionProtocol != null && extensionProtocol.hasServerExtension(ClassicProtocolExtension.LONGER_MESSAGES)) {
return Short.MAX_VALUE * 2;
} else {
return 64 - (MinecraftClient.getInstance().getSession().getUsername().length() + 2);
// Calculates the current chat limit, since it changes depending on the protocol version
LoadClassicProtocolExtensionCallback.EVENT.register(classicProtocolExtension -> {
if (classicProtocolExtension == ClassicProtocolExtension.LONGER_MESSAGES) {
currentChatLength = Short.MAX_VALUE * 2;
}
} else if (ProtocolTranslator.getTargetVersion().equals(BedrockProtocolVersion.bedrockLatest)) {
return 512;
} else if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_9_3)) {
return 100;
} else {
return 256;
}
});
// Register the footstep particle
FootStepParticle.init();
}
/**
* Replaces the default port when parsing a server address if the default port should be replaced
*
* @param address The original address of the server
* @param version The protocol version
* @return The server address with the replaced default port
*/
public static String replaceDefaultPort(final String address, final ProtocolVersion version) {
// If the default port for this entry should be replaced, check if the address already contains a port
// We can't just replace vanilla's default port because a bedrock server might be running on the same port
if (BedrockSettings.global().replaceDefaultPort.getValue() && Objects.equals(version, BedrockProtocolVersion.bedrockLatest) && !address.contains(":")) {
return address + ":" + ProtocolConstants.BEDROCK_DEFAULT_PORT;
} else {
return address;
}
}
/**
* Executes a task synchronized with the main thread from networking threads
* Executes a sync task and returns the uuid of the task
*
* @param task The task to execute
* @return The uuid of the task
*/
public static String executeSyncTask(final Consumer<RegistryByteBuf> task) {
final String uuid = UUID.randomUUID().toString();
public static String executeSyncTask(final Consumer<PacketByteBuf> task) {
final var uuid = UUID.randomUUID().toString();
PENDING_EXECUTION_TASKS.put(uuid, task);
return uuid;
}
@ApiStatus.Internal
public static void handleSyncTask(final PacketByteBuf buf) {
final String uuid = buf.readString();
final var uuid = buf.readString();
if (PENDING_EXECUTION_TASKS.containsKey(uuid)) {
MinecraftClient.getInstance().execute(() -> { // Execute the task on the main thread
final var task = PENDING_EXECUTION_TASKS.remove(uuid);
task.accept(new RegistryByteBuf(buf, MinecraftClient.getInstance().getNetworkHandler().getRegistryManager()));
task.accept(buf);
});
}
}
public static int getCurrentChatLength() {
return currentChatLength;
}
}

View File

@ -17,18 +17,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.classic;
package de.florianmichael.viafabricplus.fixes.classic;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import io.netty.buffer.ByteBuf;
import net.lenni0451.reflect.Enums;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocol.classic.c0_30cpetoc0_28_30.data.ClassicProtocolExtension;
import net.raphimc.vialegacy.protocol.classic.c0_30cpetoc0_28_30.packet.ClientboundPacketsc0_30cpe;
import org.jetbrains.annotations.ApiStatus;
import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.ClientboundPacketsc0_30cpe;
import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.data.ClassicProtocolExtension;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -36,29 +33,15 @@ import java.util.function.BiConsumer;
public class CPEAdditions {
public final static List<ClassicProtocolExtension> ALLOWED_EXTENSIONS = new ArrayList<>();
public final static List<ClassicProtocolExtension> ALLOWED_EXTENSIONS = Arrays.asList(ClassicProtocolExtension.ENV_WEATHER_TYPE);
public final static Map<Integer, ClientboundPacketsc0_30cpe> CUSTOM_PACKETS = new HashMap<>();
public static ClientboundPacketsc0_30cpe EXT_WEATHER_TYPE;
private static boolean snowing = false;
@ApiStatus.Internal
public static void modifyMappings() {
allowExtension(ClassicProtocolExtension.ENV_WEATHER_TYPE);
EXT_WEATHER_TYPE = createNewPacket(ClassicProtocolExtension.ENV_WEATHER_TYPE, 31, (user, buf) -> buf.readByte());
}
@ApiStatus.Internal
public static boolean isSnowing() {
return ProtocolTranslator.getTargetVersion().equals(LegacyProtocolVersion.c0_30cpe) && snowing;
}
@ApiStatus.Internal
public static void setSnowing(boolean snowing) {
CPEAdditions.snowing = snowing;
}
public static void allowExtension(final ClassicProtocolExtension classicProtocolExtension) {
ALLOWED_EXTENSIONS.add(classicProtocolExtension);
}

View File

@ -17,16 +17,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.classic;
package de.florianmichael.viafabricplus.fixes.classic;
import de.florianmichael.viafabricplus.fixes.data.ItemRegistryDiff;
import de.florianmichael.viafabricplus.screen.VFPScreen;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.resource.featuretoggle.FeatureFlags;
import net.minecraft.util.math.MathHelper;
import java.util.ArrayList;
@ -57,7 +55,6 @@ public class GridItemSelectionScreen extends VFPScreen {
final List<Item> allowedItems = new ArrayList<>();
// Calculate all visible items
for (Item item : Registries.ITEM) {
if (item == Items.AIR || !item.getRequiredFeatures().contains(FeatureFlags.VANILLA)) continue;
if (ItemRegistryDiff.keepItem(item)) {
allowedItems.add(item);
}
@ -90,15 +87,6 @@ public class GridItemSelectionScreen extends VFPScreen {
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (client.options.inventoryKey.matchesKey(keyCode, scanCode)) {
this.close();
return true;
}
return super.keyPressed(keyCode, scanCode, modifiers);
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
final int halfWidth = this.width / 2;

View File

@ -17,28 +17,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.classic;
package de.florianmichael.viafabricplus.fixes.classic;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_17;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocol.classic.c0_28_30toa1_0_15.model.ClassicLevel;
import net.raphimc.vialegacy.protocol.classic.c0_28_30toa1_0_15.provider.ClassicWorldHeightProvider;
import net.raphimc.vialegacy.protocol.classic.c0_28_30toa1_0_15.storage.ClassicLevelStorage;
import org.jetbrains.annotations.ApiStatus;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.IntTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.model.ClassicLevel;
import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicWorldHeightProvider;
import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.storage.ClassicLevelStorage;
import net.raphimc.vialoader.util.VersionEnum;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
@ApiStatus.Internal
public class WorldHeightSupport {
public static PacketHandler handleJoinGame(final PacketHandler parentHandler) {
@ -46,11 +47,11 @@ public class WorldHeightSupport {
parentHandler.handle(wrapper);
if (wrapper.isCancelled()) return;
if (wrapper.user().getProtocolInfo().serverProtocolVersion().olderThanOrEqualTo(LegacyProtocolVersion.c0_28toc0_30)) {
for (CompoundTag dimension : wrapper.get(Types.NAMED_COMPOUND_TAG, 0).getCompoundTag("minecraft:dimension_type").getListTag("value", CompoundTag.class)) {
changeDimensionTagHeight(wrapper.user(), dimension.getCompoundTag("element"));
if (VersionEnum.fromUserConnection(wrapper.user()).isOlderThanOrEqualTo(VersionEnum.c0_28toc0_30)) {
for (Tag dimension : wrapper.get(Type.NAMED_COMPOUND_TAG, 0).<CompoundTag>get("minecraft:dimension_type").<ListTag>get("value")) {
changeDimensionTagHeight(wrapper.user(), ((CompoundTag) dimension).get("element"));
}
changeDimensionTagHeight(wrapper.user(), wrapper.get(Types.NAMED_COMPOUND_TAG, 1));
changeDimensionTagHeight(wrapper.user(), wrapper.get(Type.NAMED_COMPOUND_TAG, 1));
}
};
}
@ -60,8 +61,8 @@ public class WorldHeightSupport {
parentHandler.handle(wrapper);
if (wrapper.isCancelled()) return;
if (wrapper.user().getProtocolInfo().serverProtocolVersion().olderThanOrEqualTo(LegacyProtocolVersion.c0_28toc0_30)) {
changeDimensionTagHeight(wrapper.user(), wrapper.get(Types.NAMED_COMPOUND_TAG, 0));
if (VersionEnum.fromUserConnection(wrapper.user()).isOlderThanOrEqualTo(VersionEnum.c0_28toc0_30)) {
changeDimensionTagHeight(wrapper.user(), wrapper.get(Type.NAMED_COMPOUND_TAG, 0));
}
};
}
@ -71,7 +72,7 @@ public class WorldHeightSupport {
parentHandler.handle(wrapper);
if (wrapper.isCancelled()) return;
if (wrapper.user().getProtocolInfo().serverProtocolVersion().olderThanOrEqualTo(LegacyProtocolVersion.c0_28toc0_30)) {
if (VersionEnum.fromUserConnection(wrapper.user()).isOlderThanOrEqualTo(VersionEnum.c0_28toc0_30)) {
wrapper.resetReader();
final Chunk chunk = wrapper.read(new ChunkType1_17(16));
wrapper.write(new ChunkType1_17(chunk.getSections().length), chunk);
@ -105,14 +106,14 @@ public class WorldHeightSupport {
final PacketHandler classicLightHandler = new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // x
map(Types.VAR_INT); // y
map(Types.BOOLEAN); // trust edges
map(Type.VAR_INT); // x
map(Type.VAR_INT); // y
map(Type.BOOLEAN); // trust edges
handler(wrapper -> {
wrapper.read(Types.VAR_INT); // sky light mask
wrapper.read(Types.VAR_INT); // block light mask
final int emptySkyLightMask = wrapper.read(Types.VAR_INT); // empty sky light mask
final int emptyBlockLightMask = wrapper.read(Types.VAR_INT); // empty block light mask
wrapper.read(Type.VAR_INT); // sky light mask
wrapper.read(Type.VAR_INT); // block light mask
final int emptySkyLightMask = wrapper.read(Type.VAR_INT); // empty sky light mask
final int emptyBlockLightMask = wrapper.read(Type.VAR_INT); // empty block light mask
final ClassicLevel level = wrapper.user().get(ClassicLevelStorage.class).getClassicLevel();
final ClassicWorldHeightProvider heightProvider = Via.getManager().getProviders().get(ClassicWorldHeightProvider.class);
@ -124,8 +125,8 @@ public class WorldHeightSupport {
}
final List<byte[]> lightArrays = new ArrayList<>();
while (wrapper.isReadable(Types.BYTE_ARRAY_PRIMITIVE, 0)) {
lightArrays.add(wrapper.read(Types.BYTE_ARRAY_PRIMITIVE));
while (wrapper.isReadable(Type.BYTE_ARRAY_PRIMITIVE, 0)) {
lightArrays.add(wrapper.read(Type.BYTE_ARRAY_PRIMITIVE));
}
int skyLightCount = 16;
@ -143,25 +144,25 @@ public class WorldHeightSupport {
skyLightMask.set(0, skyLightCount);
blockLightMask.set(0, blockLightCount);
wrapper.write(Types.LONG_ARRAY_PRIMITIVE, skyLightMask.toLongArray());
wrapper.write(Types.LONG_ARRAY_PRIMITIVE, blockLightMask.toLongArray());
wrapper.write(Types.LONG_ARRAY_PRIMITIVE, new long[emptySkyLightMask]);
wrapper.write(Types.LONG_ARRAY_PRIMITIVE, new long[emptyBlockLightMask]);
wrapper.write(Type.LONG_ARRAY_PRIMITIVE, skyLightMask.toLongArray());
wrapper.write(Type.LONG_ARRAY_PRIMITIVE, blockLightMask.toLongArray());
wrapper.write(Type.LONG_ARRAY_PRIMITIVE, new long[emptySkyLightMask]);
wrapper.write(Type.LONG_ARRAY_PRIMITIVE, new long[emptyBlockLightMask]);
wrapper.write(Types.VAR_INT, skyLightCount);
wrapper.write(Type.VAR_INT, skyLightCount);
for (int i = 0; i < skyLightCount; i++) {
wrapper.write(Types.BYTE_ARRAY_PRIMITIVE, lightArrays.remove(0));
wrapper.write(Type.BYTE_ARRAY_PRIMITIVE, lightArrays.remove(0));
}
wrapper.write(Types.VAR_INT, blockLightCount);
wrapper.write(Type.VAR_INT, blockLightCount);
for (int i = 0; i < blockLightCount; i++) {
wrapper.write(Types.BYTE_ARRAY_PRIMITIVE, lightArrays.remove(0));
wrapper.write(Type.BYTE_ARRAY_PRIMITIVE, lightArrays.remove(0));
}
});
}
};
return wrapper -> {
if (wrapper.user().getProtocolInfo().serverProtocolVersion().olderThanOrEqualTo(LegacyProtocolVersion.c0_28toc0_30)) {
if (VersionEnum.fromUserConnection(wrapper.user()).isOlderThanOrEqualTo(VersionEnum.c0_28toc0_30)) {
classicLightHandler.handle(wrapper);
} else {
parentHandler.handle(wrapper);
@ -170,7 +171,7 @@ public class WorldHeightSupport {
}
private static void changeDimensionTagHeight(final UserConnection user, final CompoundTag tag) {
tag.putInt("height", Via.getManager().getProviders().get(ClassicWorldHeightProvider.class).getMaxChunkSectionCount(user) << 4);
tag.put("height", new IntTag(Via.getManager().getProviders().get(ClassicWorldHeightProvider.class).getMaxChunkSectionCount(user) << 4));
}
}

View File

@ -17,16 +17,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.classic.command;
package de.florianmichael.viafabricplus.fixes.classic.command;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viafabricplus.injection.access.IExtensionProtocolMetadataStorage;
import de.florianmichael.viafabricplus.protocoltranslator.impl.command.VFPViaSubCommand;
import de.florianmichael.viafabricplus.protocolhack.impl.command.VFPViaSubCommand;
import net.minecraft.util.Formatting;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocol.classic.c0_30cpetoc0_28_30.storage.ExtensionProtocolMetadataStorage;
import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.storage.ExtensionProtocolMetadataStorage;
import net.raphimc.vialoader.util.VersionEnum;
public class ListExtensionsCommand implements VFPViaSubCommand {
public class ListExtensionsCommand extends VFPViaSubCommand {
@Override
public String name() {
@ -35,16 +36,17 @@ public class ListExtensionsCommand implements VFPViaSubCommand {
@Override
public String description() {
return "Shows all classic extensions (only for " + LegacyProtocolVersion.c0_30cpe.getName() + ")";
return "Shows all classic extensions (only for " + VersionEnum.c0_30cpe.getName() + ")";
}
@Override
public boolean execute(ViaCommandSender sender, String[] args) {
if (getUser() == null || !getUser().has(ExtensionProtocolMetadataStorage.class)) {
sendMessage(sender, Formatting.RED + "Only for " + LegacyProtocolVersion.c0_30cpe.getName());
final UserConnection connection = getUser();
if (!connection.has(ExtensionProtocolMetadataStorage.class)) {
sendMessage(sender, Formatting.RED + "Only for " + VersionEnum.c0_30cpe.getName());
return true;
}
((IExtensionProtocolMetadataStorage) getUser().get(ExtensionProtocolMetadataStorage.class)).viaFabricPlus$getServerExtensions().forEach((extension, version) -> {
((IExtensionProtocolMetadataStorage) connection.get(ExtensionProtocolMetadataStorage.class)).viaFabricPlus$getServerExtensions().forEach((extension, version) -> {
sendMessage(sender, Formatting.GREEN + extension.getName() + Formatting.GOLD + " v" + version);
});
return true;

View File

@ -17,15 +17,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.classic.command;
package de.florianmichael.viafabricplus.fixes.classic.command;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import de.florianmichael.viafabricplus.protocoltranslator.impl.command.VFPViaSubCommand;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viafabricplus.protocolhack.impl.command.VFPViaSubCommand;
import net.minecraft.util.Formatting;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocol.alpha.a1_0_16_2toa1_0_17_1_0_17_4.storage.TimeLockStorage;
import net.raphimc.vialegacy.protocols.alpha.protocola1_0_17_1_0_17_4toa1_0_16_2.storage.TimeLockStorage;
import net.raphimc.vialoader.util.VersionEnum;
public class SetTimeCommand implements VFPViaSubCommand {
public class SetTimeCommand extends VFPViaSubCommand {
@Override
public String name() {
@ -34,7 +35,7 @@ public class SetTimeCommand implements VFPViaSubCommand {
@Override
public String description() {
return "Changes the time (Only for <= " + LegacyProtocolVersion.a1_0_16toa1_0_16_2.getName() + ")";
return "Changes the time (Only for <= " + VersionEnum.a1_0_16toa1_0_16_2.getName() + ")";
}
@Override
@ -44,14 +45,15 @@ public class SetTimeCommand implements VFPViaSubCommand {
@Override
public boolean execute(ViaCommandSender sender, String[] args) {
if (getUser() == null || !getUser().has(TimeLockStorage.class)) {
sendMessage(sender, Formatting.RED + "Only for <= " + LegacyProtocolVersion.a1_0_16toa1_0_16_2.getName());
final UserConnection connection = getUser();
if (!connection.has(TimeLockStorage.class)) {
sendMessage(sender, Formatting.RED + "Only for <= " + VersionEnum.a1_0_16toa1_0_16_2.getName());
return true;
}
try {
if (args.length == 1) {
final long time = Long.parseLong(args[0]) % 24_000L;
getUser().get(TimeLockStorage.class).setTime(time);
connection.get(TimeLockStorage.class).setTime(time);
sendMessage(sender, Formatting.GREEN + "Time has been set to " + Formatting.GOLD + time);
} else {
return false;

View File

@ -1,215 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.data;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.EntityAttachmentType;
import net.minecraft.entity.EntityAttachments;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityType;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import java.util.Map;
import static de.florianmichael.viafabricplus.util.MapUtil.linkedHashMap;
/**
* Data dump for entity dimension changes between versions.
*/
public class EntityDimensionDiff {
/**
* A map of entity types to a map of versions to dimensions.
*/
private static final Map<EntityType<?>, Map<ProtocolVersion, EntityDimensions>> ENTITY_DIMENSIONS = linkedHashMap(
EntityType.WITHER, linkedHashMap(
ProtocolVersion.v1_7_6, EntityDimensionsBuilder.create(EntityType.WITHER).withChangingDimensions(0.9F, 4.0F).build(),
ProtocolVersion.v1_8, EntityType.WITHER.getDimensions()
),
EntityType.SILVERFISH, linkedHashMap(
ProtocolVersion.v1_7_6, EntityDimensionsBuilder.create(EntityType.SILVERFISH).withChangingDimensions(0.3F, 0.7F).build(),
ProtocolVersion.v1_8, EntityType.SILVERFISH.getDimensions()
),
EntityType.SNOW_GOLEM, linkedHashMap(
ProtocolVersion.v1_7_6, EntityDimensionsBuilder.create(EntityType.SNOW_GOLEM).withChangingDimensions(0.4F, 1.8F).build(),
ProtocolVersion.v1_8, EntityType.SNOW_GOLEM.getDimensions()
),
EntityType.ZOMBIE, linkedHashMap(
ProtocolVersion.v1_7_6, EntityDimensionsBuilder.create(EntityType.ZOMBIE).withChangingDimensions(0.6F, 1.8F).build(),
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.ZOMBIE).withFixedDimensions(0.6F, 1.95F).build(),
ProtocolVersion.v1_9, EntityType.ZOMBIE.getDimensions()
),
EntityType.CHICKEN, linkedHashMap(
LegacyProtocolVersion.b1_7tob1_7_3, EntityDimensionsBuilder.create(EntityType.CHICKEN).withChangingDimensions(0.3F, 0.4F).build(),
ProtocolVersion.v1_7_6, EntityDimensionsBuilder.create(EntityType.CHICKEN).withChangingDimensions(0.3F, 0.7F).build(),
ProtocolVersion.v1_8, EntityType.CHICKEN.getDimensions()
),
EntityType.SHEEP, linkedHashMap(
LegacyProtocolVersion.c0_28toc0_30, EntityDimensionsBuilder.create(EntityType.SHEEP).withChangingDimensions(1.4F, 1.72F).build(),
LegacyProtocolVersion.a1_0_15, EntityType.SHEEP.getDimensions()
),
EntityType.OCELOT, linkedHashMap(
ProtocolVersion.v1_7_6, EntityDimensionsBuilder.create(EntityType.OCELOT).withChangingDimensions(0.6F, 0.8F).build(),
ProtocolVersion.v1_8, EntityType.OCELOT.getDimensions()
),
EntityType.OAK_BOAT, linkedHashMap(
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.OAK_BOAT).withChangingDimensions(1.5F, 0.6F).build(),
ProtocolVersion.v1_9, EntityType.OAK_BOAT.getDimensions()
),
EntityType.CREEPER, linkedHashMap(
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.CREEPER).withChangingDimensions(0.6F, 1.8F).build(),
ProtocolVersion.v1_9, EntityType.CREEPER.getDimensions()
),
EntityType.IRON_GOLEM, linkedHashMap(
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.IRON_GOLEM).withChangingDimensions(1.4F, 2.9F).build(),
ProtocolVersion.v1_9, EntityType.IRON_GOLEM.getDimensions()
),
EntityType.SKELETON, linkedHashMap(
ProtocolVersion.v1_7_6, EntityDimensionsBuilder.create(EntityType.SKELETON).withChangingDimensions(0.6F, 1.8F).build(),
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.SKELETON).withChangingDimensions(0.6F, 1.95F).build(),
ProtocolVersion.v1_9, EntityType.SKELETON.getDimensions()
),
EntityType.WITHER_SKELETON, linkedHashMap(
LegacyProtocolVersion.r1_4_6tor1_4_7, EntityDimensionsBuilder.create(EntityType.WITHER_SKELETON).withChangingDimensions(0.72F, 2.16F).build(),
ProtocolVersion.v1_7_6, EntityDimensionsBuilder.create(EntityType.WITHER_SKELETON).withChangingDimensions(0.72F, 2.34F).build(),
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.WITHER_SKELETON).withChangingDimensions(0.72F, 2.535F).build(),
ProtocolVersion.v1_9, EntityType.WITHER_SKELETON.getDimensions()
),
EntityType.COW, linkedHashMap(
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.COW).withChangingDimensions(0.9F, 1.3F).build(),
ProtocolVersion.v1_9, EntityType.COW.getDimensions()
),
EntityType.HORSE, linkedHashMap(
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.HORSE).withChangingDimensions(1.4F, 1.6F).build(),
ProtocolVersion.v1_9, EntityType.HORSE.getDimensions()
),
EntityType.MOOSHROOM, linkedHashMap(
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.MOOSHROOM).withChangingDimensions(0.9F, 1.3F).build(),
ProtocolVersion.v1_9, EntityType.MOOSHROOM.getDimensions()
),
EntityType.RABBIT, linkedHashMap(
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.RABBIT).withChangingDimensions(0.6F, 0.7F).build(),
ProtocolVersion.v1_9, EntityType.RABBIT.getDimensions()
),
EntityType.SQUID, linkedHashMap(
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.SQUID).withChangingDimensions(0.95F, 0.95F).build(),
ProtocolVersion.v1_9, EntityType.SQUID.getDimensions()
),
EntityType.VILLAGER, linkedHashMap(
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.VILLAGER).withChangingDimensions(0.6F, 1.8F).build(),
ProtocolVersion.v1_9, EntityType.VILLAGER.getDimensions()
),
EntityType.WOLF, linkedHashMap(
LegacyProtocolVersion.r1_1, EntityDimensionsBuilder.create(EntityType.WOLF).withChangingDimensions(0.8F, 0.8F).build(),
ProtocolVersion.v1_8, EntityDimensionsBuilder.create(EntityType.WOLF).withChangingDimensions(0.6F, 0.8F).build(),
ProtocolVersion.v1_9, EntityType.WOLF.getDimensions()
),
EntityType.DRAGON_FIREBALL, linkedHashMap(
ProtocolVersion.v1_10, EntityDimensionsBuilder.create(EntityType.DRAGON_FIREBALL).withChangingDimensions(0.3125F, 0.3125F).build(),
ProtocolVersion.v1_11, EntityType.DRAGON_FIREBALL.getDimensions()
),
EntityType.LEASH_KNOT, linkedHashMap(
ProtocolVersion.v1_16_4, EntityDimensionsBuilder.create(EntityType.LEASH_KNOT).withChangingDimensions(0.5F, 0.5F).build(),
ProtocolVersion.v1_17, EntityType.LEASH_KNOT.getDimensions()
),
EntityType.SLIME, linkedHashMap(
ProtocolVersion.v1_13_2, EntityDimensionsBuilder.create(EntityType.SLIME).withChangingDimensions(2F * 0.255F, 2F * 0.255F).build(),
ProtocolVersion.v1_14, EntityDimensionsBuilder.create(EntityType.SLIME).withChangingDimensions(2.04F * 0.255F, 2.04F * 0.255F).build(),
ProtocolVersion.v1_20_5, EntityType.SLIME.getDimensions()
),
EntityType.MAGMA_CUBE, linkedHashMap(
ProtocolVersion.v1_13_2, EntityDimensionsBuilder.create(EntityType.MAGMA_CUBE).withChangingDimensions(2F * 0.255F, 2F * 0.255F).build(),
ProtocolVersion.v1_14, EntityDimensionsBuilder.create(EntityType.MAGMA_CUBE).withChangingDimensions(2.04F * 0.255F, 2.04F * 0.255F).build(),
ProtocolVersion.v1_20_5, EntityType.MAGMA_CUBE.getDimensions()
),
EntityType.ARROW, linkedHashMap(
LegacyProtocolVersion.c0_28toc0_30, EntityDimensionsBuilder.create(EntityType.ARROW).withChangingDimensions(0.3F, 0.5F).build(),
LegacyProtocolVersion.a1_0_15, EntityType.ARROW.getDimensions()
)
);
static {
ChangeProtocolVersionCallback.EVENT.register((oldVersion, newVersion) -> MinecraftClient.getInstance().execute(() -> ENTITY_DIMENSIONS.forEach((entityType, dimensionMap) -> {
for (Map.Entry<ProtocolVersion, EntityDimensions> entry : dimensionMap.entrySet()) {
final ProtocolVersion version = entry.getKey();
final EntityDimensions dimensions = entry.getValue();
if (oldVersion.newerThan(version) && newVersion.olderThanOrEqualTo(version)) {
entityType.dimensions = dimensions;
break;
}
if (newVersion.newerThanOrEqualTo(version) && oldVersion.olderThanOrEqualTo(version)) {
entityType.dimensions = dimensions;
}
}
})));
}
public static void init() {
// Calls the static block
}
private static class EntityDimensionsBuilder {
private EntityDimensions entityDimensions;
private EntityAttachments.Builder attachments = EntityAttachments.builder();
public static EntityDimensionsBuilder create() {
return new EntityDimensionsBuilder();
}
public static EntityDimensionsBuilder create(final EntityType<?> template) {
final EntityDimensionsBuilder entityDimensionsBuilder = new EntityDimensionsBuilder();
entityDimensionsBuilder.entityDimensions = template.getDimensions();
return entityDimensionsBuilder;
}
public EntityDimensionsBuilder withChangingDimensions(final float width, final float height) {
this.entityDimensions = new EntityDimensions(width, height, this.entityDimensions.eyeHeight(), this.entityDimensions.attachments(), false);
return this;
}
public EntityDimensionsBuilder withFixedDimensions(final float width, final float height) {
this.entityDimensions = new EntityDimensions(width, height, this.entityDimensions.eyeHeight(), this.entityDimensions.attachments(), true);
return this;
}
public EntityDimensionsBuilder withEyeHeight(final float eyeHeight) {
this.entityDimensions = this.entityDimensions.withEyeHeight(eyeHeight);
return this;
}
public EntityDimensionsBuilder withPassengerAttachments(final float... offsetYs) {
for (float f : offsetYs) {
this.attachments = this.attachments.add(EntityAttachmentType.PASSENGER, 0.0F, f, 0.0F);
}
this.entityDimensions = this.entityDimensions.withAttachments(this.attachments);
return this;
}
public EntityDimensions build() {
return this.entityDimensions;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -19,13 +19,11 @@
package de.florianmichael.viafabricplus.fixes.data;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import net.minecraft.GameVersion;
import net.minecraft.SaveVersion;
import net.minecraft.SharedConstants;
import net.minecraft.resource.ResourceType;
import org.jetbrains.annotations.ApiStatus;
import net.raphimc.vialoader.util.VersionEnum;
import java.util.Date;
import java.util.HashMap;
@ -36,78 +34,79 @@ import java.util.Map;
*/
public class ResourcePackHeaderDiff {
private final static Map<ProtocolVersion, GameVersion> GAME_VERSION_DIFF = new HashMap<>();
private final static Map<VersionEnum, GameVersion> GAME_VERSION_DIFF = new HashMap<>();
static {
registerVersion(ProtocolVersion.v1_21_2, 42, "1.21.3");
registerVersion(ProtocolVersion.v1_21, 34, "1.21.1");
registerVersion(ProtocolVersion.v1_20_5, 32, "1.20.6");
registerVersion(ProtocolVersion.v1_20_3, 22, "1.20.4");
registerVersion(ProtocolVersion.v1_20_2, 18, "1.20.2");
registerVersion(ProtocolVersion.v1_20, 15, "1.20.1");
registerVersion(ProtocolVersion.v1_19_4, 13, "1.19.4");
registerVersion(ProtocolVersion.v1_19_3, 12, "1.19.3");
registerVersion(ProtocolVersion.v1_19_1, 9, "1.19.2");
registerVersion(ProtocolVersion.v1_19, 9, "1.19");
registerVersion(ProtocolVersion.v1_18_2, 8, "1.18.2");
registerVersion(ProtocolVersion.v1_18, 8, "1.18.1");
registerVersion(ProtocolVersion.v1_17_1, 7, "1.17.1");
registerVersion(ProtocolVersion.v1_17, 7, "1.17");
registerVersion(ProtocolVersion.v1_16_4, 6, "1.16.5");
registerVersion(ProtocolVersion.v1_16_3, 6, "1.16.3");
registerVersion(ProtocolVersion.v1_16_2, 6, "1.16.2");
registerVersion(ProtocolVersion.v1_16_1, 5, "1.16.1");
registerVersion(ProtocolVersion.v1_16, 5, "1.16");
registerVersion(ProtocolVersion.v1_15_2, 5, "1.15.2");
registerVersion(ProtocolVersion.v1_15_1, 5, "1.15.1");
registerVersion(ProtocolVersion.v1_15, 5, "1.15");
registerVersion(ProtocolVersion.v1_14_4, 4, "1.14.4");
registerVersion(ProtocolVersion.v1_14_3, 4, "1.14.3");
registerVersion(ProtocolVersion.v1_14_2, 4, "1.14.2");
registerVersion(ProtocolVersion.v1_14_1, 4, "1.14.1");
registerVersion(ProtocolVersion.v1_14, 4, "1.14");
registerVersion(ProtocolVersion.v1_13_2, 4, "1.13.2");
registerVersion(ProtocolVersion.v1_13_1, 4, "1.13.1");
registerVersion(ProtocolVersion.v1_13, 4, "1.13");
registerVersion(ProtocolVersion.v1_12_2, 3, "1.12.2");
registerVersion(ProtocolVersion.v1_12_1, 3, "1.12.1");
registerVersion(ProtocolVersion.v1_12, 3, "1.12");
registerVersion(ProtocolVersion.v1_11_1, 3, "1.11.2");
registerVersion(ProtocolVersion.v1_11, 3, "1.11");
registerVersion(ProtocolVersion.v1_10, 2, "1.10.2");
registerVersion(ProtocolVersion.v1_9_3, 2, "1.9.4");
registerVersion(ProtocolVersion.v1_9_2, 2, "1.9.2");
registerVersion(ProtocolVersion.v1_9_1, 2, "1.9.1");
registerVersion(ProtocolVersion.v1_9, 2, "1.9");
registerVersion(ProtocolVersion.v1_8, 1, "1.8.9");
registerVersion(ProtocolVersion.v1_7_6, 1, "1.7.10");
registerVersion(ProtocolVersion.v1_7_2, 1, "1.7.5");
registerVersion(VersionEnum.r1_20_3tor1_20_4, 22, "1.20.4");
registerVersion(VersionEnum.r1_20_2, 18, "1.20.2");
registerVersion(VersionEnum.r1_20tor1_20_1, 15, "1.20.1");
registerVersion(VersionEnum.r1_19_4, 13, "1.19.4");
registerVersion(VersionEnum.r1_19_3, 12, "1.19.3");
registerVersion(VersionEnum.r1_19_1tor1_19_2, 9, "1.19.2");
registerVersion(VersionEnum.r1_19, 9, "1.19");
registerVersion(VersionEnum.r1_18_2, 8, "1.18.2");
registerVersion(VersionEnum.r1_18tor1_18_1, 8, "1.18.1");
registerVersion(VersionEnum.r1_17_1, 7, "1.17.1");
registerVersion(VersionEnum.r1_17, 7, "1.17");
registerVersion(VersionEnum.r1_16_4tor1_16_5, 6, "1.16.5");
registerVersion(VersionEnum.r1_16_3, 6, "1.16.3");
registerVersion(VersionEnum.r1_16_2, 6, "1.16.2");
registerVersion(VersionEnum.r1_16_1, 5, "1.16.1");
registerVersion(VersionEnum.r1_16, 5, "1.16");
registerVersion(VersionEnum.r1_15_2, 5, "1.15.2");
registerVersion(VersionEnum.r1_15_1, 5, "1.15.1");
registerVersion(VersionEnum.r1_15, 5, "1.15");
registerVersion(VersionEnum.r1_14_4, 4, "1.14.4");
registerVersion(VersionEnum.r1_14_3, 4, "1.14.3");
registerVersion(VersionEnum.r1_14_2, 4, "1.14.2");
registerVersion(VersionEnum.r1_14_1, 4, "1.14.1");
registerVersion(VersionEnum.r1_14, 4, "1.14");
registerVersion(VersionEnum.r1_13_2, 4, "1.13.2");
registerVersion(VersionEnum.r1_13_1, 4, "1.13.1");
registerVersion(VersionEnum.r1_13, 4, "1.13");
registerVersion(VersionEnum.r1_12_2, 3, "1.12.2");
registerVersion(VersionEnum.r1_12_1, 3, "1.12.1");
registerVersion(VersionEnum.r1_12, 3, "1.12");
registerVersion(VersionEnum.r1_11_1to1_11_2, 3, "1.11.2");
registerVersion(VersionEnum.r1_11, 3, "1.11");
registerVersion(VersionEnum.r1_10, 2, "1.10.2");
registerVersion(VersionEnum.r1_9_3tor1_9_4, 2, "1.9.4");
registerVersion(VersionEnum.r1_9_2, 2, "1.9.2");
registerVersion(VersionEnum.r1_9_1, 2, "1.9.1");
registerVersion(VersionEnum.r1_9, 2, "1.9");
registerVersion(VersionEnum.r1_8, 1, "1.8.9");
registerVersion(VersionEnum.r1_7_6tor1_7_10, 1, "1.7.10");
registerVersion(VersionEnum.r1_7_2tor1_7_5, 1, "1.7.5");
}
@ApiStatus.Internal
/**
* Checks if the registry is outdated.
*/
public static void checkOutdated() {
if (!GAME_VERSION_DIFF.containsKey(ProtocolTranslator.NATIVE_VERSION)) {
throw new RuntimeException("The native client version is not registered in the resource pack header diff!");
for (VersionEnum version : VersionEnum.OFFICIAL_SUPPORTED_PROTOCOLS) {
if (version.getProtocol().isSnapshot()) continue;
if (!GAME_VERSION_DIFF.containsKey(version)) {
throw new RuntimeException("The version " + version + " has no pack format registered");
}
}
}
/**
* @param version The {@link ProtocolVersion} to get the {@link GameVersion} for.
* @return The {@link GameVersion} for the given {@link ProtocolVersion}.
* @param version The {@link VersionEnum} to get the {@link GameVersion} for.
* @return The {@link GameVersion} for the given {@link VersionEnum}.
*/
public static GameVersion get(final ProtocolVersion version) {
public static GameVersion get(final VersionEnum version) {
if (!GAME_VERSION_DIFF.containsKey(version)) {
return SharedConstants.getGameVersion();
} else {
return GAME_VERSION_DIFF.get(version);
}
return GAME_VERSION_DIFF.get(version);
}
private static void registerVersion(final ProtocolVersion version, final int packFormat, final String name) {
private static void registerVersion(final VersionEnum version, final int packFormat, final String name) {
registerVersion(version, packFormat, name, name);
}
private static void registerVersion(final ProtocolVersion version, final int packFormat, final String name, final String id) {
private static void registerVersion(final VersionEnum version, final int packFormat, final String name, final String id) {
GAME_VERSION_DIFF.put(version, new GameVersion() {
@Override
@ -127,7 +126,7 @@ public class ResourcePackHeaderDiff {
@Override
public int getProtocolVersion() {
return version.getOriginalVersion();
return version.getProtocol().getOriginalVersion();
}
@Override

View File

@ -19,22 +19,23 @@
package de.florianmichael.viafabricplus.fixes.data.recipe;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.BannerPatternsComponent;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.minecraft.block.entity.BannerBlockEntity;
import net.minecraft.inventory.RecipeInputInventory;
import net.minecraft.item.BannerItem;
import net.minecraft.item.DyeItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.SpecialCraftingRecipe;
import net.minecraft.recipe.SpecialRecipeSerializer;
import net.minecraft.recipe.book.CraftingRecipeCategory;
import net.minecraft.recipe.input.CraftingRecipeInput;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.util.DyeColor;
import net.minecraft.world.World;
import net.raphimc.vialoader.util.VersionEnum;
public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
@ -45,27 +46,27 @@ public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
}
@Override
public boolean matches(CraftingRecipeInput input, World world) {
public boolean matches(RecipeInputInventory inv, World world) {
boolean foundBanner = false;
for (int i = 0; i < input.size(); i++) {
ItemStack stack = input.getStackInSlot(i);
for (int i = 0; i < inv.size(); i++) {
ItemStack stack = inv.getStack(i);
if (stack.getItem() instanceof BannerItem) {
if (foundBanner)
return false;
if (stack.getOrDefault(DataComponentTypes.BANNER_PATTERNS, BannerPatternsComponent.DEFAULT).layers().size() >= 6)
if (BannerBlockEntity.getPatternCount(stack) >= 6)
return false;
foundBanner = true;
}
}
return foundBanner && getBannerPattern(input) != null;
return foundBanner && getBannerPattern(inv) != null;
}
@Override
public ItemStack craft(CraftingRecipeInput input, RegistryWrapper.WrapperLookup lookup) {
public ItemStack craft(RecipeInputInventory inv, DynamicRegistryManager registryManager) {
ItemStack result = ItemStack.EMPTY;
for (int i = 0; i < input.size(); i++) {
ItemStack stack = input.getStackInSlot(i);
for (int i = 0; i < inv.size(); i++) {
ItemStack stack = inv.getStack(i);
if (!stack.isEmpty() && stack.getItem() instanceof BannerItem) {
result = stack.copy();
result.setCount(1);
@ -73,34 +74,44 @@ public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
}
}
final BannerPattern_1_13_2 pattern = getBannerPattern(input);
BannerPattern_1_13_2 pattern = getBannerPattern(inv);
if (pattern != null) {
final var patternKey = lookup.getOrThrow(RegistryKeys.BANNER_PATTERN).getOrThrow(pattern.getKey());
DyeColor color = ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_12_2) ? DyeColor.BLACK : DyeColor.WHITE;
for (int i = 0; i < input.size(); i++) {
Item item = input.getStackInSlot(i).getItem();
DyeColor color = ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_12_2) ? DyeColor.BLACK : DyeColor.WHITE;
for (int i = 0; i < inv.size(); i++) {
Item item = inv.getStack(i).getItem();
if (item instanceof DyeItem dyeItem) {
color = dyeItem.getColor();
}
}
final BannerPatternsComponent.Builder patternsBuilder = new BannerPatternsComponent.Builder();
if (result.contains(DataComponentTypes.BANNER_PATTERNS)) {
patternsBuilder.addAll(result.get(DataComponentTypes.BANNER_PATTERNS));
NbtCompound tileEntityNbt = result.getOrCreateSubNbt("BlockEntityTag");
NbtList patterns;
if (tileEntityNbt.contains("Patterns", 9)) {
patterns = tileEntityNbt.getList("Patterns", 10);
} else {
patterns = new NbtList();
tileEntityNbt.put("Patterns", patterns);
}
patternsBuilder.add(new BannerPatternsComponent.Layer(patternKey, color));
result.set(DataComponentTypes.BANNER_PATTERNS, patternsBuilder.build());
NbtCompound patternNbt = new NbtCompound();
patternNbt.putString("Pattern", pattern.getId());
patternNbt.putInt("Color", color.getId());
patterns.add(patternNbt);
}
return result;
}
@Override
public boolean fits(int width, int height) {
return width >= 3 && height >= 3;
}
@Override
public RecipeSerializer<AddBannerPatternRecipe> getSerializer() {
return SERIALIZER;
}
private static BannerPattern_1_13_2 getBannerPattern(CraftingRecipeInput input) {
private static BannerPattern_1_13_2 getBannerPattern(RecipeInputInventory inv) {
for (BannerPattern_1_13_2 pattern : BannerPattern_1_13_2.values()) {
if (!pattern.isCraftable())
continue;
@ -109,8 +120,8 @@ public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
if (pattern.hasBaseStack()) {
boolean foundBaseItem = false;
boolean foundDye = false;
for (int i = 0; i < input.size(); i++) {
ItemStack stack = input.getStackInSlot(i);
for (int i = 0; i < inv.size(); i++) {
ItemStack stack = inv.getStack(i);
if (!stack.isEmpty() && !(stack.getItem() instanceof BannerItem)) {
if (stack.getItem() instanceof DyeItem) {
if (foundDye) {
@ -127,13 +138,13 @@ public class AddBannerPatternRecipe extends SpecialCraftingRecipe {
}
}
}
if (!foundBaseItem || (!foundDye && ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_10))) matches = false;
} else if (input.size() == pattern.getRecipePattern().length * pattern.getRecipePattern()[0].length()) {
if (!foundBaseItem || (!foundDye && ProtocolHack.getTargetVersion().isNewerThan(VersionEnum.r1_10))) matches = false;
} else if (inv.size() == pattern.getRecipePattern().length * pattern.getRecipePattern()[0].length()) {
DyeColor patternColor = null;
for (int i = 0; i < input.size(); i++) {
for (int i = 0; i < inv.size(); i++) {
int row = i / 3;
int col = i % 3;
ItemStack stack = input.getStackInSlot(i);
ItemStack stack = inv.getStack(i);
Item item = stack.getItem();
if (!stack.isEmpty() && !(item instanceof BannerItem)) {
if (!(item instanceof DyeItem)) {

View File

@ -20,79 +20,76 @@
package de.florianmichael.viafabricplus.fixes.data.recipe;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BannerPattern;
import net.minecraft.block.entity.BannerPatterns;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.registry.RegistryKey;
public enum BannerPattern_1_13_2 {
BASE(BannerPatterns.BASE),
SQUARE_BOTTOM_LEFT(BannerPatterns.SQUARE_BOTTOM_LEFT, " ", " ", "# "),
SQUARE_BOTTOM_RIGHT(BannerPatterns.SQUARE_BOTTOM_RIGHT, " ", " ", " #"),
SQUARE_TOP_LEFT(BannerPatterns.SQUARE_TOP_LEFT, "# ", " ", " "),
SQUARE_TOP_RIGHT(BannerPatterns.SQUARE_TOP_RIGHT, " #", " ", " "),
STRIPE_BOTTOM(BannerPatterns.STRIPE_BOTTOM, " ", " ", "###"),
STRIPE_TOP(BannerPatterns.STRIPE_TOP, "###", " ", " "),
STRIPE_LEFT(BannerPatterns.STRIPE_LEFT, "# ", "# ", "# "),
STRIPE_RIGHT(BannerPatterns.STRIPE_RIGHT, " #", " #", " #"),
STRIPE_CENTER(BannerPatterns.STRIPE_CENTER, " # ", " # ", " # "),
STRIPE_MIDDLE(BannerPatterns.STRIPE_MIDDLE, " ", "###", " "),
STRIPE_DOWNRIGHT(BannerPatterns.STRIPE_DOWNRIGHT, "# ", " # ", " #"),
STRIPE_DOWNLEFT(BannerPatterns.STRIPE_DOWNLEFT, " #", " # ", "# "),
STRIPE_SMALL(BannerPatterns.SMALL_STRIPES, "# #", "# #", " "),
CROSS(BannerPatterns.CROSS, "# #", " # ", "# #"),
STRAIGHT_CROSS(BannerPatterns.STRAIGHT_CROSS, " # ", "###", " # "),
TRIANGLE_BOTTOM(BannerPatterns.TRIANGLE_BOTTOM, " ", " # ", "# #"),
TRIANGLE_TOP(BannerPatterns.TRIANGLE_TOP, "# #", " # ", " "),
TRIANGLES_BOTTOM(BannerPatterns.TRIANGLES_BOTTOM, " ", "# #", " # "),
TRIANGLES_TOP(BannerPatterns.TRIANGLES_TOP, " # ", "# #", " "),
DIAGONAL_LEFT(BannerPatterns.DIAGONAL_LEFT, "## ", "# ", " "),
DIAGONAL_RIGHT(BannerPatterns.DIAGONAL_RIGHT, " ", " #", " ##"),
DIAGONAL_LEFT_MIRROR(BannerPatterns.DIAGONAL_UP_LEFT, " ", "# ", "## "),
DIAGONAL_RIGHT_MIRROR(BannerPatterns.DIAGONAL_UP_RIGHT, " ##", " #", " "),
CIRCLE_MIDDLE(BannerPatterns.CIRCLE, " ", " # ", " "),
RHOMBUS_MIDDLE(BannerPatterns.RHOMBUS, " # ", "# #", " # "),
HALF_VERTICAL(BannerPatterns.HALF_VERTICAL, "## ", "## ", "## "),
HALF_HORIZONTAL(BannerPatterns.HALF_HORIZONTAL, "###", "###", " "),
HALF_VERTICAL_MIRROR(BannerPatterns.HALF_VERTICAL_RIGHT, " ##", " ##", " ##"),
HALF_HORIZONTAL_MIRROR(BannerPatterns.HALF_HORIZONTAL_BOTTOM, " ", "###", "###"),
BORDER(BannerPatterns.BORDER, "###", "# #", "###"),
CURLY_BORDER(BannerPatterns.CURLY_BORDER, new ItemStack(Blocks.VINE)),
GRADIENT(BannerPatterns.GRADIENT, "# #", " # ", " # "),
GRADIENT_UP(BannerPatterns.GRADIENT_UP, " # ", " # ", "# #"),
BRICKS(BannerPatterns.BRICKS, new ItemStack(Blocks.BRICKS)),
GLOBE(BannerPatterns.GLOBE),
CREEPER(BannerPatterns.CREEPER, new ItemStack(Items.CREEPER_HEAD)),
SKULL(BannerPatterns.SKULL, new ItemStack(Items.WITHER_SKELETON_SKULL)),
FLOWER(BannerPatterns.FLOWER, new ItemStack(Blocks.OXEYE_DAISY)),
MOJANG(BannerPatterns.MOJANG, new ItemStack(Items.ENCHANTED_GOLDEN_APPLE));
BASE("b"),
SQUARE_BOTTOM_LEFT("bl", " ", " ", "# "),
SQUARE_BOTTOM_RIGHT("br", " ", " ", " #"),
SQUARE_TOP_LEFT("tl", "# ", " ", " "),
SQUARE_TOP_RIGHT("tr", " #", " ", " "),
STRIPE_BOTTOM("bs", " ", " ", "###"),
STRIPE_TOP("ts", "###", " ", " "),
STRIPE_LEFT("ls", "# ", "# ", "# "),
STRIPE_RIGHT("rs", " #", " #", " #"),
STRIPE_CENTER("cs", " # ", " # ", " # "),
STRIPE_MIDDLE("ms", " ", "###", " "),
STRIPE_DOWNRIGHT("drs", "# ", " # ", " #"),
STRIPE_DOWNLEFT("dls", " #", " # ", "# "),
STRIPE_SMALL("ss", "# #", "# #", " "),
CROSS("cr", "# #", " # ", "# #"),
STRAIGHT_CROSS("sc", " # ", "###", " # "),
TRIANGLE_BOTTOM("bt", " ", " # ", "# #"),
TRIANGLE_TOP("tt", "# #", " # ", " "),
TRIANGLES_BOTTOM("bts", " ", "# #", " # "),
TRIANGLES_TOP("tts", " # ", "# #", " "),
DIAGONAL_LEFT("ld", "## ", "# ", " "),
DIAGONAL_RIGHT("rd", " ", " #", " ##"),
DIAGONAL_LEFT_MIRROR("lud", " ", "# ", "## "),
DIAGONAL_RIGHT_MIRROR("rud", " ##", " #", " "),
CIRCLE_MIDDLE("mc", " ", " # ", " "),
RHOMBUS_MIDDLE("mr", " # ", "# #", " # "),
HALF_VERTICAL("vh", "## ", "## ", "## "),
HALF_HORIZONTAL("hh", "###", "###", " "),
HALF_VERTICAL_MIRROR("vhr", " ##", " ##", " ##"),
HALF_HORIZONTAL_MIRROR("hhb", " ", "###", "###"),
BORDER("bo", "###", "# #", "###"),
CURLY_BORDER("cbo", new ItemStack(Blocks.VINE)),
GRADIENT("gra", "# #", " # ", " # "),
GRADIENT_UP("gru", " # ", " # ", "# #"),
BRICKS("bri", new ItemStack(Blocks.BRICKS)),
GLOBE("glb"),
CREEPER("cre", new ItemStack(Items.CREEPER_HEAD)),
SKULL("sku", new ItemStack(Items.WITHER_SKELETON_SKULL)),
FLOWER("flo", new ItemStack(Blocks.OXEYE_DAISY)),
MOJANG("moj", new ItemStack(Items.ENCHANTED_GOLDEN_APPLE));
private final RegistryKey<BannerPattern> pattern;
private final String id;
private final String[] recipePattern;
private ItemStack baseStack;
BannerPattern_1_13_2(final RegistryKey<BannerPattern> pattern) {
BannerPattern_1_13_2(String id) {
this.recipePattern = new String[3];
this.baseStack = ItemStack.EMPTY;
this.pattern = pattern;
this.id = id;
}
BannerPattern_1_13_2(final RegistryKey<BannerPattern> pattern, final ItemStack baseStack) {
this(pattern);
BannerPattern_1_13_2(String id, ItemStack baseStack) {
this(id);
this.baseStack = baseStack;
}
BannerPattern_1_13_2(final RegistryKey<BannerPattern> pattern, final String recipe1, final String recipe2, final String recipe3) {
this(pattern);
BannerPattern_1_13_2(String id, String recipe1, String recipe2, String recipe3) {
this(id);
this.recipePattern[0] = recipe1;
this.recipePattern[1] = recipe2;
this.recipePattern[2] = recipe3;
}
public RegistryKey<BannerPattern> getKey() {
return this.pattern;
public String getId() {
return this.id;
}
public boolean isCraftable() {

View File

@ -24,7 +24,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.recipe.*;
import net.minecraft.recipe.book.CookingRecipeCategory;
import net.minecraft.recipe.book.CraftingRecipeCategory;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.Identifier;
import net.minecraft.util.collection.DefaultedList;
import java.util.*;
@ -109,20 +109,19 @@ public final class RecipeInfo {
}
final int height = shape.size();
final DefaultedList<Optional<Ingredient>> ingredients = DefaultedList.of();
final DefaultedList<Ingredient> ingredients = DefaultedList.of();
for (String row : shape) {
for (int x = 0; x < width; x++) {
final char key = row.charAt(x);
Ingredient ingredient = legend.get(key);
if (ingredient == null) {
if (key == ' ') {
ingredients.add(Optional.empty());
ingredient = Ingredient.EMPTY;
} else {
throw new IllegalArgumentException("Unknown character in shape: " + key);
}
} else {
ingredients.add(Optional.of(ingredient));
}
ingredients.add(ingredient);
}
}
@ -316,8 +315,8 @@ public final class RecipeInfo {
* @param id The id
* @return The recipe info
*/
public RecipeEntry<?> create(RegistryKey<Recipe<?>> id) {
return new RecipeEntry<>(id, this.creator.get());
public RecipeEntry<?> create(Identifier id) {
return new RecipeEntry<Recipe<?>>(id, this.creator.get());
}
}

View File

@ -1,76 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.data.recipe;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeEntry;
import net.minecraft.recipe.RecipeType;
import net.minecraft.recipe.input.RecipeInput;
import net.minecraft.registry.RegistryKey;
import net.minecraft.world.World;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
public class RecipeManager1_11_2 {
private final Multimap<RecipeType<?>, RecipeEntry<?>> recipesByType;
private final Map<RegistryKey<Recipe<?>>, RecipeEntry<?>> recipesById;
public RecipeManager1_11_2(final Iterable<RecipeEntry<?>> recipes) {
final ImmutableMultimap.Builder<RecipeType<?>, RecipeEntry<?>> recipesByTypeBuilder = ImmutableMultimap.builder();
final ImmutableMap.Builder<RegistryKey<Recipe<?>>, RecipeEntry<?>> recipesByIdBuilder = ImmutableMap.builder();
for (RecipeEntry<?> recipeEntry : recipes) {
final RecipeType<?> recipeType = recipeEntry.value().getType();
recipesByTypeBuilder.put(recipeType, recipeEntry);
recipesByIdBuilder.put(recipeEntry.id(), recipeEntry);
}
this.recipesByType = recipesByTypeBuilder.build();
this.recipesById = recipesByIdBuilder.build();
}
public <I extends RecipeInput, T extends Recipe<I>> Optional<RecipeEntry<T>> getFirstMatch(final RecipeType<T> type, final I input, final World world) {
if (input.isEmpty()) {
return Optional.empty();
} else {
return this.recipesByType.get(type).stream().map(e -> (RecipeEntry<T>) e).filter(recipe -> recipe.value().matches(input, world)).findFirst();
}
}
public Optional<RecipeEntry<?>> get(final RegistryKey<Recipe<?>> id) {
return Optional.ofNullable(this.recipesById.get(id));
}
public Collection<RecipeEntry<?>> values() {
return this.recipesById.values();
}
public Stream<RegistryKey<Recipe<?>>> keys() {
return this.recipesById.keySet().stream();
}
}

View File

@ -19,8 +19,6 @@
package de.florianmichael.viafabricplus.fixes.data.recipe;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
import net.minecraft.inventory.RecipeInputInventory;
@ -30,12 +28,9 @@ import net.minecraft.item.Items;
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
import net.minecraft.recipe.*;
import net.minecraft.recipe.book.CraftingRecipeCategory;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.util.Identifier;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import org.jetbrains.annotations.ApiStatus;
import net.raphimc.vialoader.util.VersionEnum;
import java.util.ArrayList;
import java.util.List;
@ -45,53 +40,33 @@ import java.util.List;
*/
public class Recipes1_11_2 {
private static RecipeManager1_11_2 RECIPE_MANAGER;
public static RecipeManager1_11_2 getRecipeManager() {
if (RECIPE_MANAGER == null) {
final List<RecipeInfo> recipeInfos = Recipes1_11_2.getRecipes(ProtocolTranslator.getTargetVersion());
final List<RecipeEntry<?>> recipes = new ArrayList<>(recipeInfos.size());
for (int i = 0; i < recipeInfos.size(); i++) {
final RegistryKey<Recipe<?>> key = RegistryKey.of(RegistryKeys.RECIPE, Identifier.of("viafabricplus", "recipe/" + i));
recipes.add(recipeInfos.get(i).create(key));
}
RECIPE_MANAGER = new RecipeManager1_11_2(recipes);
}
return RECIPE_MANAGER;
}
public static void reset() {
RECIPE_MANAGER = null;
}
/**
* @return A list of all recipes for the given version.
*/
public static List<RecipeInfo> getRecipes(final ProtocolVersion targetVersion) {
public static List<RecipeInfo> getRecipes(final VersionEnum targetVersion) {
final List<RecipeInfo> recipes = new ArrayList<>();
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_4_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_4_2)) {
recipes.add(RecipeInfo.of(() -> new ArmorDyeRecipe(CraftingRecipeCategory.MISC)));
recipes.add(RecipeInfo.of(() -> new MapCloningRecipe(CraftingRecipeCategory.MISC)));
recipes.add(RecipeInfo.of(() -> new MapExtendingRecipe(CraftingRecipeCategory.MISC)));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_4_6tor1_4_7)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_4_6tor1_4_7)) {
recipes.add(RecipeInfo.of(() -> new FireworkRocketRecipe(CraftingRecipeCategory.MISC)));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_11)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_11)) {
recipes.add(RecipeInfo.of(() -> new ShulkerBoxColoringRecipe(CraftingRecipeCategory.MISC)));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_9)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_9)) {
recipes.add(RecipeInfo.of(() -> new TippedArrowRecipe(CraftingRecipeCategory.MISC)));
recipes.add(RecipeInfo.of(() -> new ShieldDecorationRecipe(CraftingRecipeCategory.MISC)));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_8)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_8)) {
recipes.add(RecipeInfo.of(() -> new RepairItemRecipe(CraftingRecipeCategory.MISC)));
recipes.add(RecipeInfo.of(() -> new BannerDuplicateRecipe(CraftingRecipeCategory.MISC)));
recipes.add(RecipeInfo.of(() -> new AddBannerPatternRecipe(CraftingRecipeCategory.MISC)));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_7_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_7_2tor1_7_5)) {
recipes.add(RecipeInfo.of(() -> new BookCloningRecipe(CraftingRecipeCategory.MISC)));
}
@ -169,7 +144,7 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(Blocks.BOOKSHELF, "###", "XXX", "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Items.BOOK));
recipes.add(RecipeInfo.shaped(4, Items.ARROW, "X", "#", "Y", '#', Items.STICK, 'X', Items.FLINT, 'Y', Items.FEATHER));
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_12)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_12)) {
recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.YELLOW_CONCRETE_POWDER, Items.YELLOW_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL));
recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.WHITE_CONCRETE_POWDER, Items.BONE_MEAL, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL));
recipes.add(RecipeInfo.shapeless("concrete_powder", 8, Blocks.RED_CONCRETE_POWDER, Items.RED_DYE, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.SAND, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL, Blocks.GRAVEL));
@ -219,26 +194,26 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped("bed", Blocks.BLACK_BED, "###", "XXX", '#', Blocks.BLACK_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS));
} else {
recipes.add(RecipeInfo.shapeless(Blocks.WHITE_WOOL, Blocks.WHITE_WOOL, Items.BONE_MEAL));
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_3tob1_3_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_3tob1_3_1)) {
recipes.add(RecipeInfo.shaped("bed", Blocks.RED_BED, "###", "XXX", '#', Blocks.YELLOW_WOOL, Blocks.BLACK_WOOL, Blocks.BLUE_WOOL, Blocks.BROWN_WOOL, Blocks.CYAN_WOOL, Blocks.GRAY_WOOL, Blocks.GREEN_WOOL, Blocks.LIGHT_BLUE_WOOL, Blocks.LIGHT_GRAY_WOOL, Blocks.WHITE_WOOL, Blocks.RED_WOOL, Blocks.PURPLE_WOOL, Blocks.PINK_WOOL, Blocks.ORANGE_WOOL, Blocks.LIME_WOOL, Blocks.MAGENTA_WOOL, 'X', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS));
}
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_11_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_11_1to1_11_2)) {
recipes.add(RecipeInfo.shaped(9, Items.IRON_NUGGET, "#", '#', Items.IRON_INGOT));
recipes.add(RecipeInfo.shaped("iron_ingot", Items.IRON_INGOT, "###", "###", "###", '#', Items.IRON_NUGGET));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_11)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_11)) {
recipes.add(RecipeInfo.shaped(Blocks.OBSERVER, "###", "RRQ", "###", 'Q', Items.QUARTZ, 'R', Blocks.REDSTONE_WIRE, '#', Blocks.COBBLESTONE));
recipes.add(RecipeInfo.shaped(Blocks.PURPLE_SHULKER_BOX, "-", "#", "-", '#', Blocks.CHEST, '-', Items.SHULKER_SHELL));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_10)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_10)) {
recipes.add(RecipeInfo.shapeless("bonemeal", 9, Items.BONE_MEAL, Blocks.BONE_BLOCK));
recipes.add(RecipeInfo.shaped(Blocks.BONE_BLOCK, "XXX", "XXX", "XXX", 'X', Items.BONE_MEAL));
recipes.add(RecipeInfo.shaped(Blocks.MAGMA_BLOCK, "##", "##", '#', Items.MAGMA_CREAM));
recipes.add(RecipeInfo.shaped(Blocks.NETHER_WART_BLOCK, "###", "###", "###", '#', Blocks.NETHER_WART));
recipes.add(RecipeInfo.shaped(Blocks.RED_NETHER_BRICKS, "NW", "WN", 'W', Blocks.NETHER_WART, 'N', Items.NETHER_BRICK));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_9)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_9)) {
recipes.add(RecipeInfo.shapeless(Blocks.TRAPPED_CHEST, Blocks.CHEST, Blocks.TRIPWIRE_HOOK));
recipes.add(RecipeInfo.shaped(Items.SHIELD, "WoW", "WWW", " W ", 'W', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'o', Items.IRON_INGOT));
recipes.add(RecipeInfo.shaped(4, Blocks.PURPUR_BLOCK, "FF", "FF", 'F', Items.POPPED_CHORUS_FRUIT));
@ -258,15 +233,15 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shapeless("red_dye", Items.RED_DYE, Items.BEETROOT));
recipes.add(RecipeInfo.shaped(Items.BEETROOT_SOUP, "OOO", "OOO", " B ", 'B', Items.BOWL, 'O', Items.BEETROOT));
} else {
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_5tor1_5_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_5tor1_5_1)) {
recipes.add(RecipeInfo.shaped(Blocks.TRAPPED_CHEST, "#-", '#', Blocks.CHEST, '-', Blocks.TRIPWIRE_HOOK));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_3_1tor1_3_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_3_1tor1_3_2)) {
recipes.add(RecipeInfo.shaped(Items.ENCHANTED_GOLDEN_APPLE, "###", "#X#", "###", '#', Items.GOLD_BLOCK, 'X', Items.APPLE));
}
recipes.add(RecipeInfo.shaped("boat", Items.OAK_BOAT, "# #", "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.DARK_OAK_PLANKS, Blocks.BIRCH_PLANKS, Blocks.ACACIA_PLANKS));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_8)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_8)) {
recipes.add(RecipeInfo.shapeless(Blocks.MOSSY_COBBLESTONE, Blocks.COBBLESTONE, Blocks.VINE));
recipes.add(RecipeInfo.shapeless(Blocks.MOSSY_STONE_BRICKS, Blocks.STONE_BRICKS, Blocks.VINE));
recipes.add(RecipeInfo.shaped(Blocks.CHISELED_STONE_BRICKS, "#", "#", '#', Blocks.STONE_BRICK_SLAB));
@ -330,13 +305,13 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(4, Blocks.POLISHED_ANDESITE, "SS", "SS", 'S', Blocks.ANDESITE));
} else {
recipes.add(RecipeInfo.shaped("wooden_fence", 2, Blocks.OAK_FENCE, "###", "###", '#', Items.STICK));
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_8tob1_8_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_8tob1_8_1)) {
recipes.add(RecipeInfo.shaped("wooden_fence_gate", Blocks.OAK_FENCE_GATE, "#W#", "#W#", '#', Items.STICK, 'W', Blocks.OAK_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.DARK_OAK_PLANKS, Blocks.BIRCH_PLANKS, Blocks.ACACIA_PLANKS));
}
recipes.add(RecipeInfo.shaped(Blocks.IRON_DOOR, "##", "##", "##", '#', Items.IRON_INGOT));
recipes.add(RecipeInfo.shaped("wooden_door", Blocks.OAK_DOOR, "##", "##", "##", '#', Blocks.OAK_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.DARK_OAK_PLANKS, Blocks.BIRCH_PLANKS, Blocks.ACACIA_PLANKS));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_7_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_7_2tor1_7_5)) {
recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.YELLOW_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.YELLOW_DYE));
recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.WHITE_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.BONE_MEAL));
recipes.add(RecipeInfo.shaped("stained_glass", 8, Blocks.RED_STAINED_GLASS, "###", "#X#", "###", '#', Blocks.GLASS, 'X', Items.RED_DYE));
@ -393,7 +368,7 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(Items.FLINT_AND_STEEL, "A ", " B", 'A', Items.IRON_INGOT, 'B', Items.FLINT));
recipes.add(RecipeInfo.shaped(Blocks.TNT, "X#X", "#X#", "X#X", '#', Blocks.SAND, 'X', Items.GUNPOWDER));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_6_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_6_1)) {
recipes.add(RecipeInfo.shaped(Items.GOLDEN_APPLE, "###", "#X#", "###", '#', Items.GOLD_INGOT, 'X', Items.APPLE));
recipes.add(RecipeInfo.shaped(Items.GLISTERING_MELON_SLICE, "###", "#X#", "###", '#', Items.GOLD_NUGGET, 'X', Items.MELON_SLICE));
recipes.add(RecipeInfo.shaped("carpet", 3, Blocks.YELLOW_CARPET, "##", '#', Blocks.YELLOW_WOOL));
@ -435,11 +410,11 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(9, Items.COAL, "#", '#', Blocks.COAL_BLOCK));
} else {
recipes.add(RecipeInfo.shaped(Items.GOLDEN_APPLE, "###", "#X#", "###", '#', Items.GOLD_NUGGET, 'X', Items.APPLE));
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_0_0tor1_0_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_0_0tor1_0_1)) {
recipes.add(RecipeInfo.shapeless(Items.GLISTERING_MELON_SLICE, Items.GOLD_NUGGET, Items.MELON_SLICE));
}
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_5tor1_5_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_5tor1_5_1)) {
recipes.add(RecipeInfo.shaped(6, Blocks.SNOW, "###", '#', Blocks.SNOW_BLOCK));
recipes.add(RecipeInfo.shaped(Blocks.QUARTZ_BLOCK, "##", "##", '#', Items.QUARTZ));
recipes.add(RecipeInfo.shaped(2, Blocks.QUARTZ_PILLAR, "#", "#", '#', Blocks.QUARTZ_BLOCK));
@ -459,10 +434,10 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(Blocks.REDSTONE_BLOCK, "###", "###", "###", '#', Blocks.REDSTONE_WIRE));
recipes.add(RecipeInfo.shaped(9, Blocks.REDSTONE_WIRE, "#", '#', Blocks.REDSTONE_BLOCK));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_4_6tor1_4_7)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_4_6tor1_4_7)) {
recipes.add(RecipeInfo.shaped(6, Blocks.NETHER_BRICK_SLAB, "###", '#', Blocks.NETHER_BRICKS));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_4_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_4_2)) {
recipes.add(RecipeInfo.shaped(6, Blocks.COBBLESTONE_WALL, "###", "###", '#', Blocks.COBBLESTONE));
recipes.add(RecipeInfo.shaped(6, Blocks.MOSSY_COBBLESTONE_WALL, "###", "###", '#', Blocks.MOSSY_COBBLESTONE));
recipes.add(RecipeInfo.shaped(Blocks.FLOWER_POT, "# #", " # ", '#', Items.BRICK));
@ -474,7 +449,7 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(Blocks.BEACON, "GGG", "GSG", "OOO", 'S', Items.NETHER_STAR, 'G', Blocks.GLASS, 'O', Blocks.OBSIDIAN));
recipes.add(RecipeInfo.shapeless(Items.PUMPKIN_PIE, Blocks.CARVED_PUMPKIN, Items.SUGAR, Items.EGG));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_3_1tor1_3_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_3_1tor1_3_2)) {
recipes.add(RecipeInfo.shapeless(Items.WRITABLE_BOOK, Items.BOOK, Items.INK_SAC, Items.FEATHER));
recipes.add(RecipeInfo.shapeless(Items.BOOK, Items.PAPER, Items.PAPER, Items.PAPER, Items.LEATHER));
recipes.add(RecipeInfo.shaped(3, Blocks.OAK_SIGN, "###", "###", " X ", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Items.STICK));
@ -491,17 +466,17 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(Blocks.EMERALD_BLOCK, "###", "###", "###", '#', Items.EMERALD));
recipes.add(RecipeInfo.shaped(9, Items.EMERALD, "#", '#', Blocks.EMERALD_BLOCK));
} else {
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_2_1tor1_2_3)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_2_1tor1_2_3)) {
recipes.add(RecipeInfo.shaped("wooden_slab", 6, Blocks.OAK_SLAB, "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS));
} else {
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_3tob1_3_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_3tob1_3_1)) {
recipes.add(RecipeInfo.shaped("wooden_slab", 3, Blocks.OAK_SLAB, "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS));
}
}
recipes.add(RecipeInfo.shaped(Items.BOOK, "#", "#", "#", '#', Items.PAPER));
recipes.add(RecipeInfo.shaped(Blocks.OAK_SIGN, "###", "###", " X ", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Items.STICK));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_2_4tor1_2_5)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_2_4tor1_2_5)) {
recipes.add(RecipeInfo.shaped("planks", 4, Blocks.BIRCH_PLANKS, "#", '#', Blocks.BIRCH_LOG));
recipes.add(RecipeInfo.shaped("planks", 4, Blocks.SPRUCE_PLANKS, "#", '#', Blocks.SPRUCE_LOG));
recipes.add(RecipeInfo.shaped("planks", 4, Blocks.JUNGLE_PLANKS, "#", '#', Blocks.JUNGLE_LOG));
@ -510,7 +485,7 @@ public class Recipes1_11_2 {
} else {
recipes.add(RecipeInfo.shaped("planks", 4, Blocks.OAK_PLANKS, "#", '#', Blocks.BIRCH_LOG, Blocks.SPRUCE_LOG, Blocks.JUNGLE_LOG));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_2_1tor1_2_3)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_2_1tor1_2_3)) {
recipes.add(RecipeInfo.shaped(3, Blocks.LADDER, "# #", "###", "# #", '#', Items.STICK));
recipes.add(RecipeInfo.shaped(6, Blocks.SMOOTH_STONE_SLAB, "###", '#', Blocks.STONE));
recipes.add(RecipeInfo.shaped(6, Blocks.SANDSTONE_SLAB, "###", '#', Blocks.SANDSTONE, Blocks.CHISELED_SANDSTONE, Blocks.CUT_SANDSTONE));
@ -520,22 +495,22 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(Blocks.REDSTONE_LAMP, " R ", "RGR", " R ", 'R', Blocks.REDSTONE_WIRE, 'G', Blocks.GLOWSTONE));
recipes.add(RecipeInfo.shapeless(3, Items.FIRE_CHARGE, new ItemConvertible[]{Items.GUNPOWDER}, new ItemConvertible[]{Items.BLAZE_POWDER}, new ItemConvertible[]{Items.COAL, Items.CHARCOAL}));
} else {
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_5tob1_5_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_5tob1_5_2)) {
recipes.add(RecipeInfo.shaped(2, Blocks.LADDER, "# #", "###", "# #", '#', Items.STICK));
} else {
recipes.add(RecipeInfo.shaped(1, Blocks.LADDER, "# #", "###", "# #", '#', Items.STICK));
}
recipes.add(RecipeInfo.shaped(3, Blocks.SMOOTH_STONE_SLAB, "###", '#', Blocks.STONE));
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_3tob1_3_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_3tob1_3_1)) {
recipes.add(RecipeInfo.shaped(3, Blocks.SANDSTONE_SLAB, "###", '#', Blocks.SANDSTONE, Blocks.CHISELED_SANDSTONE, Blocks.CUT_SANDSTONE));
recipes.add(RecipeInfo.shaped(3, Blocks.COBBLESTONE_SLAB, "###", '#', Blocks.COBBLESTONE));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_8tob1_8_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_8tob1_8_1)) {
recipes.add(RecipeInfo.shaped(3, Blocks.BRICK_SLAB, "###", '#', Blocks.BRICKS));
recipes.add(RecipeInfo.shaped(3, Blocks.STONE_BRICK_SLAB, "###", '#', Blocks.STONE_BRICKS, Blocks.MOSSY_STONE_BRICKS, Blocks.CRACKED_STONE_BRICKS, Blocks.CHISELED_STONE_BRICKS));
}
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_0_0tor1_0_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_0_0tor1_0_1)) {
recipes.add(RecipeInfo.shapeless(Items.MUSHROOM_STEW, Blocks.BROWN_MUSHROOM, Blocks.RED_MUSHROOM, Items.BOWL));
recipes.add(RecipeInfo.shaped(4, Blocks.NETHER_BRICK_STAIRS, "# ", "## ", "###", '#', Blocks.NETHER_BRICKS));
recipes.add(RecipeInfo.shaped(6, Blocks.NETHER_BRICK_FENCE, "###", "###", '#', Blocks.NETHER_BRICKS));
@ -554,7 +529,7 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(Items.MUSHROOM_STEW, "Y", "X", "#", 'X', Blocks.BROWN_MUSHROOM, 'Y', Blocks.RED_MUSHROOM, '#', Items.BOWL));
recipes.add(RecipeInfo.shaped(Items.MUSHROOM_STEW, "Y", "X", "#", 'X', Blocks.RED_MUSHROOM, 'Y', Blocks.BROWN_MUSHROOM, '#', Items.BOWL));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_8tob1_8_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_8tob1_8_1)) {
recipes.add(RecipeInfo.shaped(4, Blocks.BRICK_STAIRS, "# ", "## ", "###", '#', Blocks.BRICKS));
recipes.add(RecipeInfo.shaped(4, Blocks.STONE_BRICK_STAIRS, "# ", "## ", "###", '#', Blocks.STONE_BRICKS, Blocks.MOSSY_STONE_BRICKS, Blocks.CRACKED_STONE_BRICKS, Blocks.CHISELED_STONE_BRICKS));
recipes.add(RecipeInfo.shaped(4, Blocks.STONE_BRICKS, "##", "##", '#', Blocks.STONE));
@ -563,30 +538,30 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(Blocks.MELON, "MMM", "MMM", "MMM", 'M', Items.MELON_SLICE));
recipes.add(RecipeInfo.shaped(Blocks.MELON_STEM, "M", 'M', Items.MELON_SLICE));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_7tob1_7_3)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_7tob1_7_3)) {
recipes.add(RecipeInfo.shaped(Blocks.STICKY_PISTON, "S", "P", 'P', Blocks.PISTON, 'S', Items.SLIME_BALL));
recipes.add(RecipeInfo.shaped(Blocks.PISTON, "TTT", "#X#", "#R#", 'R', Blocks.REDSTONE_WIRE, '#', Blocks.COBBLESTONE, 'T', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Items.IRON_INGOT));
recipes.add(RecipeInfo.shaped(Items.SHEARS, " #", "# ", '#', Items.IRON_INGOT));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_6tob1_6_6)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_6tob1_6_6)) {
recipes.add(RecipeInfo.shaped(Blocks.GLOWSTONE, "##", "##", '#', Items.GLOWSTONE_DUST));
recipes.add(RecipeInfo.shaped(Blocks.WHITE_WOOL, "##", "##", '#', Blocks.TRIPWIRE));
recipes.add(RecipeInfo.shaped(2, Blocks.OAK_TRAPDOOR, "###", "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS));
recipes.add(RecipeInfo.shaped(Items.MAP, "###", "#X#", "###", '#', Items.PAPER, 'X', Items.COMPASS));
} else {
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.a1_2_0toa1_2_1_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.a1_2_0toa1_2_1_1)) {
recipes.add(RecipeInfo.shaped(Blocks.GLOWSTONE, "###", "###", "###", '#', Items.GLOWSTONE_DUST));
}
recipes.add(RecipeInfo.shaped(Blocks.WHITE_WOOL, "###", "###", "###", '#', Blocks.TRIPWIRE));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_5tob1_5_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_5tob1_5_2)) {
recipes.add(RecipeInfo.shaped(6, Blocks.DETECTOR_RAIL, "X X", "X#X", "XRX", 'R', Blocks.REDSTONE_WIRE, '#', Blocks.STONE_PRESSURE_PLATE, 'X', Items.IRON_INGOT));
recipes.add(RecipeInfo.shaped(6, Blocks.POWERED_RAIL, "X X", "X#X", "XRX", 'R', Blocks.REDSTONE_WIRE, '#', Items.STICK, 'X', Items.GOLD_INGOT));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_4tob1_4_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_4tob1_4_1)) {
recipes.add(RecipeInfo.shaped(8, Items.COOKIE, "#X#", '#', Items.WHEAT, 'X', Blocks.COCOA));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_3tob1_3_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_3tob1_3_1)) {
recipes.add(RecipeInfo.shaped(Blocks.REPEATER, "#X#", "III", '#', Blocks.REDSTONE_TORCH, 'X', Blocks.REDSTONE_WIRE, 'I', Blocks.STONE));
recipes.add(RecipeInfo.shaped(Blocks.OAK_PRESSURE_PLATE, "##", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS));
recipes.add(RecipeInfo.shaped(Blocks.STONE_PRESSURE_PLATE, "##", '#', Blocks.STONE));
@ -594,7 +569,7 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.shaped(Blocks.OAK_PRESSURE_PLATE, "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS));
recipes.add(RecipeInfo.shaped(Blocks.STONE_PRESSURE_PLATE, "###", '#', Blocks.STONE));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_2_0tob1_2_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_2_0tob1_2_2)) {
recipes.add(RecipeInfo.shaped(Blocks.NOTE_BLOCK, "###", "#X#", "###", '#', Blocks.OAK_PLANKS, Blocks.SPRUCE_PLANKS, Blocks.BIRCH_PLANKS, Blocks.JUNGLE_PLANKS, Blocks.ACACIA_PLANKS, Blocks.DARK_OAK_PLANKS, 'X', Blocks.REDSTONE_WIRE));
recipes.add(RecipeInfo.shaped(Blocks.CAKE, "AAA", "BEB", "CCC", 'A', Items.MILK_BUCKET, 'B', Items.SUGAR, 'C', Items.WHEAT, 'E', Items.EGG));
recipes.add(RecipeInfo.shaped(Items.SUGAR, "#", '#', Blocks.SUGAR_CANE));
@ -636,11 +611,11 @@ public class Recipes1_11_2 {
} else {
recipes.add(RecipeInfo.shaped(4, Blocks.TORCH, "X", "#", '#', Items.STICK, 'X', Items.COAL));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.a1_2_0toa1_2_1_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.a1_2_0toa1_2_1_1)) {
recipes.add(RecipeInfo.shaped(Blocks.JACK_O_LANTERN, "A", "B", 'A', Blocks.CARVED_PUMPKIN, 'B', Blocks.TORCH));
recipes.add(RecipeInfo.shaped(Items.CLOCK, " # ", "#X#", " # ", '#', Items.GOLD_INGOT, 'X', Blocks.REDSTONE_WIRE));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.a1_1_0toa1_1_2_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.a1_1_0toa1_1_2_1)) {
recipes.add(RecipeInfo.shaped(Items.FISHING_ROD, " #", " #X", "# X", '#', Items.STICK, 'X', Blocks.TRIPWIRE));
recipes.add(RecipeInfo.shaped(Items.COMPASS, " # ", "#X#", " # ", '#', Items.IRON_INGOT, 'X', Blocks.REDSTONE_WIRE));
}
@ -648,12 +623,12 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.smelting(Items.IRON_INGOT, Items.IRON_ORE, 0.7F));
recipes.add(RecipeInfo.smelting(Items.GOLD_INGOT, Items.GOLD_ORE, 1.0F));
recipes.add(RecipeInfo.smelting(Items.DIAMOND, Items.DIAMOND_ORE, 1.0F));
recipes.add(RecipeInfo.smelting(Items.GLASS, Ingredient.ofItems(Items.SAND, Items.RED_SAND), 0.1F));
recipes.add(RecipeInfo.smelting(Items.GLASS, Ingredient.fromTag(ItemTags.SAND), 0.1F));
recipes.add(RecipeInfo.smelting(Items.COOKED_PORKCHOP, Items.PORKCHOP, 0.35F));
recipes.add(RecipeInfo.smelting(Items.STONE, Items.COBBLESTONE, 0.1F));
recipes.add(RecipeInfo.smelting(Items.BRICK, Items.CLAY_BALL, 0.3F));
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_12)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_12)) {
recipes.add(RecipeInfo.smelting(Items.WHITE_GLAZED_TERRACOTTA, Items.WHITE_TERRACOTTA, 0.1F));
recipes.add(RecipeInfo.smelting(Items.ORANGE_GLAZED_TERRACOTTA, Items.ORANGE_TERRACOTTA, 0.1F));
recipes.add(RecipeInfo.smelting(Items.MAGENTA_GLAZED_TERRACOTTA, Items.MAGENTA_TERRACOTTA, 0.1F));
@ -671,47 +646,47 @@ public class Recipes1_11_2 {
recipes.add(RecipeInfo.smelting(Items.RED_GLAZED_TERRACOTTA, Items.RED_TERRACOTTA, 0.1F));
recipes.add(RecipeInfo.smelting(Items.BLACK_GLAZED_TERRACOTTA, Items.BLACK_TERRACOTTA, 0.1F));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_11_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_11_1to1_11_2)) {
recipes.add(RecipeInfo.smelting(Items.IRON_NUGGET, Ingredient.ofItems(Items.CHAINMAIL_HELMET, Items.CHAINMAIL_CHESTPLATE, Items.CHAINMAIL_LEGGINGS, Items.CHAINMAIL_BOOTS, Items.IRON_PICKAXE, Items.IRON_SHOVEL, Items.IRON_AXE, Items.IRON_HOE, Items.IRON_SWORD, Items.IRON_HELMET, Items.IRON_CHESTPLATE, Items.IRON_LEGGINGS, Items.IRON_BOOTS, Items.IRON_HORSE_ARMOR), 0.1F));
recipes.add(RecipeInfo.smelting(Items.GOLD_NUGGET, Ingredient.ofItems(Items.GOLDEN_PICKAXE, Items.GOLDEN_SHOVEL, Items.GOLDEN_AXE, Items.GOLDEN_HOE, Items.GOLDEN_SWORD, Items.GOLDEN_HELMET, Items.GOLDEN_CHESTPLATE, Items.GOLDEN_LEGGINGS, Items.GOLDEN_BOOTS, Items.GOLDEN_HORSE_ARMOR), 0.1F));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_9)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_9)) {
recipes.add(RecipeInfo.smelting(Items.POPPED_CHORUS_FRUIT, Items.CHORUS_FRUIT, 0.1F));
}
if (targetVersion.newerThanOrEqualTo(ProtocolVersion.v1_7_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_7_2tor1_7_5)) {
recipes.add(RecipeInfo.smelting(Items.COOKED_RABBIT, Items.RABBIT, 0.35F));
recipes.add(RecipeInfo.smelting(Items.COOKED_MUTTON, Items.MUTTON, 0.35F));
recipes.add(RecipeInfo.smelting(Items.CRACKED_STONE_BRICKS, Items.STONE_BRICKS, 0.1F));
recipes.add(RecipeInfo.smelting(Items.SPONGE, Items.WET_SPONGE, 0.15F));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_6_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_6_1)) {
recipes.add(RecipeInfo.smelting(Items.TERRACOTTA, Items.CLAY, 0.35F));
recipes.add(RecipeInfo.smelting(Items.COOKED_SALMON, Items.SALMON, 0.35F));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_5tor1_5_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_5tor1_5_1)) {
recipes.add(RecipeInfo.smelting(Items.NETHER_BRICK, Items.NETHERRACK, 0.1F));
recipes.add(RecipeInfo.smelting(Items.QUARTZ, Items.NETHER_QUARTZ_ORE, 0.2F));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_4_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_4_2)) {
recipes.add(RecipeInfo.smelting(Items.BAKED_POTATO, Items.POTATO, 0.35F));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_3_1tor1_3_2)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_3_1tor1_3_2)) {
recipes.add(RecipeInfo.smelting(Items.EMERALD, Items.EMERALD_ORE, 1.0F));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.r1_0_0tor1_0_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.r1_0_0tor1_0_1)) {
recipes.add(RecipeInfo.smelting(Items.COAL, Items.COAL_ORE, 0.1F));
recipes.add(RecipeInfo.smelting(Items.REDSTONE, Items.REDSTONE_ORE, 0.7F));
recipes.add(RecipeInfo.smelting(Items.LAPIS_LAZULI, Items.LAPIS_ORE, 0.2F));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_8tob1_8_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_8tob1_8_1)) {
recipes.add(RecipeInfo.smelting(Items.COOKED_CHICKEN, Items.CHICKEN, 0.35F));
recipes.add(RecipeInfo.smelting(Items.COOKED_BEEF, Items.BEEF, 0.35F));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.b1_2_0tob1_2_2)) {
recipes.add(RecipeInfo.smelting(Items.CHARCOAL, Ingredient.ofItems(Items.OAK_LOG, Items.SPRUCE_LOG, Items.BIRCH_LOG, Items.JUNGLE_LOG, Items.ACACIA_LOG, Items.DARK_OAK_LOG), 0.15F));
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.b1_2_0tob1_2_2)) {
recipes.add(RecipeInfo.smelting(Items.CHARCOAL, Ingredient.fromTag(ItemTags.LOGS), 0.15F));
recipes.add(RecipeInfo.smelting(Items.GREEN_DYE, Items.CACTUS, 0.2F));
}
if (targetVersion.newerThanOrEqualTo(LegacyProtocolVersion.a1_2_0toa1_2_1_1)) {
if (targetVersion.isNewerThanOrEqualTo(VersionEnum.a1_2_0toa1_2_1_1)) {
recipes.add(RecipeInfo.smelting(Items.COOKED_COD, Items.COD, 0.35F));
}
@ -727,15 +702,13 @@ public class Recipes1_11_2 {
* @param screenHandler The screen handler
* @param inventory The inventory of the screen handler
*/
@ApiStatus.Internal
public static void setCraftingResultSlot(final int syncId, final ScreenHandler screenHandler, final RecipeInputInventory inventory) {
final var network = MinecraftClient.getInstance().getNetworkHandler();
final var world = MinecraftClient.getInstance().world;
final var craftingRecipeInput = inventory.createRecipeInput();
final var result = getRecipeManager()
.getFirstMatch(RecipeType.CRAFTING, craftingRecipeInput, world) // Get the first matching recipe
.map(recipe -> recipe.value().craft(craftingRecipeInput, network.getRegistryManager())) // Craft the recipe to get the result
final var result = network.getRecipeManager()
.getFirstMatch(RecipeType.CRAFTING, inventory, world) // Get the first matching recipe
.map(recipe -> recipe.value().craft(inventory, network.getRegistryManager())) // Craft the recipe to get the result
.orElse(ItemStack.EMPTY); // If there is no recipe, set the result to air
// Update the result slot

View File

@ -1,93 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.data.recipe;
import net.minecraft.block.Block;
import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.item.DyeItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.SpecialCraftingRecipe;
import net.minecraft.recipe.book.CraftingRecipeCategory;
import net.minecraft.recipe.input.CraftingRecipeInput;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.world.World;
public class ShulkerBoxColoringRecipe extends SpecialCraftingRecipe {
public static final RecipeSerializer<ShulkerBoxColoringRecipe> SERIALIZER = new SpecialRecipeSerializer<>(ShulkerBoxColoringRecipe::new);
public ShulkerBoxColoringRecipe(CraftingRecipeCategory craftingRecipeCategory) {
super(craftingRecipeCategory);
}
public boolean matches(CraftingRecipeInput input, World world) {
int i = 0;
int j = 0;
for (int k = 0; k < input.size(); k++) {
ItemStack stack = input.getStackInSlot(k);
if (!stack.isEmpty()) {
if (Block.getBlockFromItem(stack.getItem()) instanceof ShulkerBoxBlock) {
i++;
} else {
if (!(stack.getItem() instanceof DyeItem)) {
return false;
}
j++;
}
if (j > 1 || i > 1) {
return false;
}
}
}
return i == 1 && j == 1;
}
public ItemStack craft(CraftingRecipeInput input, RegistryWrapper.WrapperLookup wrapperLookup) {
ItemStack result = ItemStack.EMPTY;
DyeItem dyeItem = (DyeItem) Items.WHITE_DYE;
for (int i = 0; i < input.size(); i++) {
ItemStack stack = input.getStackInSlot(i);
if (!stack.isEmpty()) {
Item item = stack.getItem();
if (Block.getBlockFromItem(item) instanceof ShulkerBoxBlock) {
result = stack;
} else if (item instanceof DyeItem) {
dyeItem = (DyeItem) item;
}
}
}
return result.copyComponentsToNewStack(ShulkerBoxBlock.get(dyeItem.getColor()), 1);
}
@Override
public RecipeSerializer<ShulkerBoxColoringRecipe> getSerializer() {
return SERIALIZER;
}
}

View File

@ -17,23 +17,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.visual;
package de.florianmichael.viafabricplus.fixes.entity;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.model.*;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.render.entity.model.CompositeEntityModel;
import net.minecraft.client.render.entity.model.EntityModelLayer;
import net.minecraft.client.render.entity.state.BoatEntityRenderState;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.util.Identifier;
/**
* Model for boats in 1.8 and lower.
*/
public class BoatModel1_8 extends EntityModel<BoatEntityRenderState> {
public class BoatModel1_8 extends CompositeEntityModel<BoatEntity> {
public static final EntityModelLayer MODEL_LAYER = new EntityModelLayer(Identifier.of("viafabricplus", "boat1_8"), "main");
public static final EntityModelLayer MODEL_LAYER = new EntityModelLayer(new Identifier("viafabricplus", "boat1_8"), "main");
private final ImmutableList<ModelPart> parts;
public BoatModel1_8(ModelPart root) {
super(root);
this.parts = ImmutableList.of(root.getChild("bottom"), root.getChild("back"), root.getChild("front"), root.getChild("right"), root.getChild("left"));
}
public static TexturedModelData getTexturedModelData() {
@ -52,7 +54,12 @@ public class BoatModel1_8 extends EntityModel<BoatEntityRenderState> {
}
@Override
public void setAngles(BoatEntityRenderState state) {
public Iterable<ModelPart> getParts() {
return parts;
}
@Override
public void setAngles(BoatEntity entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) {
}
}

View File

@ -17,17 +17,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.visual;
package de.florianmichael.viafabricplus.fixes.entity;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.AbstractBoatEntityRenderer;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.render.entity.state.BoatEntityRenderState;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
@ -35,9 +33,9 @@ import net.minecraft.util.math.RotationAxis;
/**
* Renderer for boats in 1.8 and lower.
*/
public class BoatRenderer1_8 extends AbstractBoatEntityRenderer {
public class BoatRenderer1_8 extends EntityRenderer<BoatEntity> {
private static final Identifier TEXTURE = Identifier.of("viafabricplus", "textures/boat1_8.png");
private static final Identifier TEXTURE = new Identifier("viafabricplus", "textures/boat1_8.png");
private final BoatModel1_8 model;
public BoatRenderer1_8(EntityRendererFactory.Context ctx) {
@ -47,31 +45,33 @@ public class BoatRenderer1_8 extends AbstractBoatEntityRenderer {
}
@Override
protected EntityModel<BoatEntityRenderState> getModel() {
return this.model;
public Identifier getTexture(BoatEntity entity) {
return TEXTURE;
}
@Override
protected RenderLayer getRenderLayer() {
return this.model.getLayer(TEXTURE);
}
@Override
public void render(BoatEntityRenderState state, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) {
public void render(BoatEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) {
matrices.push();
matrices.translate(0, 0.25, 0);
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - state.yaw));
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - yaw));
if (state.damageWobbleTicks > 0) {
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(MathHelper.sin(state.damageWobbleTicks) * state.damageWobbleTicks * state.damageWobbleStrength / 10 * state.damageWobbleSide));
float damageWobbleTicks = entity.getDamageWobbleTicks() - tickDelta;
float damageWobbleStrength = entity.getDamageWobbleStrength() - tickDelta;
if (damageWobbleStrength < 0) {
damageWobbleStrength = 0;
}
if (damageWobbleTicks > 0) {
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(MathHelper.sin(damageWobbleTicks) * damageWobbleTicks * damageWobbleStrength / 10 * entity.getDamageWobbleSide()));
}
matrices.scale(-1, -1, 1);
model.setAngles(state);
model.setAngles(entity, tickDelta, 0, -0.1f, 0, 0);
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(model.getLayer(TEXTURE));
model.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV);
model.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
matrices.pop();
super.render(entity, yaw, tickDelta, matrices, vertexConsumers, light);
}
}

View File

@ -0,0 +1,209 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.entity;
import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityType;
import net.raphimc.vialoader.util.VersionEnum;
import java.util.Collections;
import java.util.Map;
import static de.florianmichael.viafabricplus.util.MapUtil.linkedHashMap;
/**
* Data dump for entity dimension changes between versions.
*/
public class EntityDimensionReplacements {
/**
* A map of entity types to a map of versions to dimensions.
*/
private static final Map<EntityType<?>, Map<VersionEnum, EntityDimensions>> ENTITY_DIMENSIONS = linkedHashMap(
EntityType.WITHER, linkedHashMap(
VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.9F, 4.0F),
VersionEnum.r1_8, EntityType.WITHER.getDimensions()
),
EntityType.SILVERFISH, linkedHashMap(
VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.3F, 0.7F),
VersionEnum.r1_8, EntityType.SILVERFISH.getDimensions()
),
EntityType.SNOW_GOLEM, linkedHashMap(
VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.4F, 1.8F),
VersionEnum.r1_8, EntityType.SNOW_GOLEM.getDimensions()
),
EntityType.ZOMBIE, linkedHashMap(
VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.6F, 1.8F),
VersionEnum.r1_8, EntityDimensions.fixed(EntityType.ZOMBIE.getDimensions().width, EntityType.ZOMBIE.getDimensions().height),
VersionEnum.r1_9, EntityType.ZOMBIE.getDimensions()
),
EntityType.CHICKEN, linkedHashMap(
VersionEnum.b1_7tob1_7_3, EntityDimensions.changing(0.3F, 0.4F),
VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.3F, 0.7F),
VersionEnum.r1_8, EntityType.CHICKEN.getDimensions()
),
EntityType.SHEEP, linkedHashMap(
VersionEnum.c0_28toc0_30, EntityDimensions.changing(1.4F, 1.72F),
VersionEnum.a1_0_15, EntityType.SHEEP.getDimensions()
),
EntityType.OCELOT, linkedHashMap(
VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.6F, 0.8F),
VersionEnum.r1_8, EntityType.OCELOT.getDimensions()
),
EntityType.BOAT, linkedHashMap(
VersionEnum.r1_8, EntityDimensions.changing(1.5F, 0.6F),
VersionEnum.r1_9, EntityType.BOAT.getDimensions()
),
EntityType.CREEPER, linkedHashMap(
VersionEnum.r1_8, EntityDimensions.changing(0.6F, 1.8F),
VersionEnum.r1_9, EntityType.CREEPER.getDimensions()
),
EntityType.IRON_GOLEM, linkedHashMap(
VersionEnum.r1_8, EntityDimensions.changing(1.4F, 2.9F),
VersionEnum.r1_9, EntityType.IRON_GOLEM.getDimensions()
),
EntityType.SKELETON, linkedHashMap(
VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.6F, 1.8F),
VersionEnum.r1_8, EntityDimensions.changing(0.6F, 1.95F),
VersionEnum.r1_9, EntityType.SKELETON.getDimensions()
),
EntityType.WITHER_SKELETON, linkedHashMap(
VersionEnum.r1_4_6tor1_4_7, EntityDimensions.changing(0.72F, 2.16F),
VersionEnum.r1_7_6tor1_7_10, EntityDimensions.changing(0.72F, 2.34F),
VersionEnum.r1_8, EntityDimensions.changing(0.72F, 2.535F),
VersionEnum.r1_9, EntityType.WITHER_SKELETON.getDimensions()
),
EntityType.COW, linkedHashMap(
VersionEnum.r1_8, EntityDimensions.changing(0.9F, 1.3F),
VersionEnum.r1_9, EntityType.COW.getDimensions()
),
EntityType.HORSE, linkedHashMap(
VersionEnum.r1_8, EntityDimensions.changing(1.4F, 1.6F),
VersionEnum.r1_9, EntityType.HORSE.getDimensions()
),
EntityType.MOOSHROOM, linkedHashMap(
VersionEnum.r1_8, EntityDimensions.changing(0.9F, 1.3F),
VersionEnum.r1_9, EntityType.MOOSHROOM.getDimensions()
),
EntityType.RABBIT, linkedHashMap(
VersionEnum.r1_8, EntityDimensions.changing(0.6F, 0.7F),
VersionEnum.r1_9, EntityType.RABBIT.getDimensions()
),
EntityType.SQUID, linkedHashMap(
VersionEnum.r1_8, EntityDimensions.changing(0.95F, 0.95F),
VersionEnum.r1_9, EntityType.SQUID.getDimensions()
),
EntityType.VILLAGER, linkedHashMap(
VersionEnum.r1_8, EntityDimensions.changing(0.6F, 1.8F),
VersionEnum.r1_9, EntityType.VILLAGER.getDimensions()
),
EntityType.WOLF, linkedHashMap(
VersionEnum.r1_1, EntityDimensions.changing(0.8F, 0.8F),
VersionEnum.r1_8, EntityDimensions.changing(0.6F, 0.8F),
VersionEnum.r1_9, EntityType.WOLF.getDimensions()
),
EntityType.DRAGON_FIREBALL, linkedHashMap(
VersionEnum.r1_10, EntityDimensions.changing(0.3125F, 0.3125F),
VersionEnum.r1_11, EntityType.DRAGON_FIREBALL.getDimensions()
),
EntityType.LEASH_KNOT, linkedHashMap(
VersionEnum.r1_16_4tor1_16_5, EntityDimensions.changing(0.5F, 0.5F),
VersionEnum.r1_17, EntityType.LEASH_KNOT.getDimensions()
),
EntityType.SLIME, linkedHashMap(
VersionEnum.r1_13_2, EntityDimensions.changing(2F, 2F),
VersionEnum.r1_14, EntityType.SLIME.getDimensions()
),
EntityType.MAGMA_CUBE, linkedHashMap(
VersionEnum.r1_13_2, EntityDimensions.changing(2F, 2F),
VersionEnum.r1_14, EntityType.MAGMA_CUBE.getDimensions()
),
EntityType.ARROW, linkedHashMap(
VersionEnum.c0_28toc0_30, EntityDimensions.changing(0.3F, 0.5F),
VersionEnum.a1_0_15, EntityType.ARROW.getDimensions()
)
);
static {
ChangeProtocolVersionCallback.EVENT.register((oldVersion, newVersion) -> MinecraftClient.getInstance().execute(() -> ENTITY_DIMENSIONS.forEach((entityType, dimensionMap) -> {
for (Map.Entry<VersionEnum, EntityDimensions> entry : dimensionMap.entrySet()) {
final VersionEnum version = entry.getKey();
final EntityDimensions dimensions = entry.getValue();
if (oldVersion.isNewerThan(version) && newVersion.isOlderThanOrEqualTo(version)) {
entityType.dimensions = dimensions;
break;
}
if (newVersion.isNewerThanOrEqualTo(version) && oldVersion.isOlderThanOrEqualTo(version)) {
entityType.dimensions = dimensions;
}
}
})));
}
public static void init() {
// Loads the class and triggers the static initializer.
}
/**
* @param entityType The {@link EntityType} to get the dimensions for.
* @return The dimensions for the given {@link EntityType} or null if there are none. The map is unmodifiable.
*/
public static Map<VersionEnum, EntityDimensions> getEntityDimensions(final EntityType<?> entityType) {
if (!ENTITY_DIMENSIONS.containsKey(entityType)) {
return null;
}
return Collections.unmodifiableMap(ENTITY_DIMENSIONS.get(entityType));
}
/**
* @param entityType The {@link EntityType} to get the dimensions for.
* @param version The {@link VersionEnum} to get the dimensions for.
* @return The closest dimensions for the given {@link EntityType} and {@link VersionEnum} or null if there are none.
*/
public static EntityDimensions getEntityDimensions(final EntityType<?> entityType, final VersionEnum version) {
final Map<VersionEnum, EntityDimensions> dimensionMap = getEntityDimensions(entityType);
if (dimensionMap == null) {
return null;
}
EntityDimensions closestDimensions = null;
VersionEnum closestVersion = null;
for (Map.Entry<VersionEnum, EntityDimensions> entry : dimensionMap.entrySet()) {
final var currentVersion = entry.getKey();
final var currentDimensions = entry.getValue();
if (currentVersion == version) { // If the version is exactly the same, return the dimensions
return currentDimensions;
}
// If the current version is closer to the version you are looking for
if (closestVersion == null || Math.abs(version.ordinal() - currentVersion.ordinal()) < Math.abs(version.ordinal() - closestVersion.ordinal())) {
closestVersion = currentVersion;
closestDimensions = currentDimensions;
}
}
return closestDimensions;
}
}

View File

@ -17,10 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.visual;
package de.florianmichael.viafabricplus.fixes.entity;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityPose;
@ -30,12 +29,12 @@ import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.entity.mob.*;
import net.minecraft.entity.passive.*;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.vehicle.AbstractBoatEntity;
import net.minecraft.entity.vehicle.AbstractChestBoatEntity;
import net.minecraft.entity.vehicle.AbstractMinecartEntity;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.entity.vehicle.ChestBoatEntity;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.raphimc.vialoader.util.VersionEnum;
import org.joml.Vector3f;
/**
* Minecraft 1.20.2 changed the calculation of the mounted height offset for all entities, this class contains the old
@ -50,28 +49,28 @@ public class EntityRidingOffsetsPre1_20_2 {
* @param passenger The passenger of the entity.
* @return The mounted height offset.
*/
public static Vec3d getMountedHeightOffset(final Entity entity, final Entity passenger) {
double yOffset = entity.getHeight() * 0.75F;
public static Vector3f getMountedHeightOffset(final Entity entity, final Entity passenger) {
float yOffset = entity.getHeight() * 0.75F;
if (entity instanceof AbstractBoatEntity abstractBoatEntity) {
if (!abstractBoatEntity.hasPassenger(passenger)) return Vec3d.ZERO;
if (entity instanceof BoatEntity boatEntity) {
if (!boatEntity.hasPassenger(passenger)) return new Vector3f();
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
yOffset = -0.3F;
final double xOffset = MathHelper.cos(abstractBoatEntity.getYaw() * MathHelper.PI / 180F);
final double zOffset = MathHelper.sin(abstractBoatEntity.getYaw() * MathHelper.PI / 180F);
final float xOffset = MathHelper.cos(boatEntity.getYaw() * MathHelper.PI / 180F);
final float zOffset = MathHelper.sin(boatEntity.getYaw() * MathHelper.PI / 180F);
return new Vec3d(0.4F * xOffset, yOffset, 0.4F * zOffset);
return new Vector3f(0.4F * xOffset, yOffset, 0.4F * zOffset);
} else {
if (abstractBoatEntity.isRemoved()) {
if (boatEntity.isRemoved()) {
yOffset = 0.01F;
} else {
yOffset = abstractBoatEntity.getType() == EntityType.BAMBOO_RAFT || abstractBoatEntity.getType() == EntityType.BAMBOO_CHEST_RAFT ? 0.25F : -0.1F;
yOffset = boatEntity.getVariant() == BoatEntity.Type.BAMBOO ? 0.25F : -0.1F;
}
double xOffset = abstractBoatEntity instanceof AbstractChestBoatEntity ? 0.15F : 0F;
if (abstractBoatEntity.getPassengerList().size() > 1) {
final int idx = abstractBoatEntity.getPassengerList().indexOf(passenger);
float xOffset = boatEntity instanceof ChestBoatEntity ? 0.15F : 0F;
if (boatEntity.getPassengerList().size() > 1) {
final int idx = boatEntity.getPassengerList().indexOf(passenger);
if (idx == 0) {
xOffset = 0.2F;
} else {
@ -81,34 +80,34 @@ public class EntityRidingOffsetsPre1_20_2 {
if (passenger instanceof AnimalEntity) xOffset += 0.2F;
}
return new Vec3d(xOffset, yOffset, 0F).rotateY(-(float) (Math.PI / 2));
return new Vector3f(xOffset, yOffset, 0F);
}
} else if (entity instanceof CamelEntity camelEntity) {
if (!camelEntity.hasPassenger(passenger)) return Vec3d.ZERO;
if (!camelEntity.hasPassenger(passenger)) return new Vector3f();
final boolean firstPassenger = camelEntity.getPassengerList().indexOf(passenger) == 0;
yOffset = camelEntity.getDimensions(camelEntity.isSitting() ? EntityPose.SITTING : EntityPose.STANDING).height() - (camelEntity.isBaby() ? 0.35F : 0.6F);
yOffset = camelEntity.getDimensions(camelEntity.isSitting() ? EntityPose.SITTING : EntityPose.STANDING).height - (camelEntity.isBaby() ? 0.35F : 0.6F);
if (camelEntity.isRemoved()) {
yOffset = 0.01F;
} else {
yOffset = camelEntity.getPassengerAttachmentY(firstPassenger, 0F, EntityDimensions.fixed(0F, (float) ((0.375F * camelEntity.getScaleFactor()) + yOffset)), camelEntity.getScaleFactor());
yOffset = (float) camelEntity.getPassengerAttachmentY(firstPassenger, 0F, EntityDimensions.fixed(0F, (0.375F * camelEntity.getScaleFactor()) + yOffset), camelEntity.getScaleFactor());
}
double zOffset = 0.5F;
float zOffset = 0.5F;
if (camelEntity.getPassengerList().size() > 1) {
if (!firstPassenger) zOffset = -0.7F;
if (passenger instanceof AnimalEntity) zOffset += 0.2F;
}
return new Vec3d(0, yOffset, zOffset);
return new Vector3f(0, yOffset, zOffset);
} else if (entity instanceof ChickenEntity chickenEntity) {
return new Vec3d(0, chickenEntity.getBodyY(0.5D) - chickenEntity.getY(), -0.1F);
return new Vector3f(0, (float) (chickenEntity.getBodyY(0.5D) - chickenEntity.getY()), -0.1F);
} else if (entity instanceof EnderDragonEntity enderDragonEntity) {
yOffset = enderDragonEntity.body.getHeight();
} else if (entity instanceof HoglinEntity hoglinEntity) {
yOffset = hoglinEntity.getHeight() - (hoglinEntity.isBaby() ? 0.2F : 0.15F);
} else if (entity instanceof LlamaEntity) {
return new Vec3d(0, entity.getHeight() * 0.6F, -0.3F);
return new Vector3f(0, entity.getHeight() * 0.6F, -0.3F);
} else if (entity instanceof PhantomEntity) {
yOffset = entity.getStandingEyeHeight();
} else if (entity instanceof PiglinEntity) {
@ -134,12 +133,12 @@ public class EntityRidingOffsetsPre1_20_2 {
}
if (entity instanceof AbstractHorseEntity abstractHorseEntity) {
if (abstractHorseEntity.lastAngryAnimationProgress > 0.0F) {
return new Vec3d(0, yOffset + 0.15F * abstractHorseEntity.lastAngryAnimationProgress, -0.7F * abstractHorseEntity.lastAngryAnimationProgress);
if (abstractHorseEntity.lastAngryAnimationProgress > 0.0f) {
return new Vector3f(0, yOffset + 0.15F * abstractHorseEntity.lastAngryAnimationProgress, -0.7F * abstractHorseEntity.lastAngryAnimationProgress);
}
}
return new Vec3d(0, yOffset, 0);
return new Vector3f(0, yOffset, 0);
}
/**
@ -150,7 +149,7 @@ public class EntityRidingOffsetsPre1_20_2 {
*/
public static double getHeightOffset(final Entity entity) {
if (entity instanceof AllayEntity || entity instanceof VexEntity) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_19_1)) {
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_19_1tor1_19_2)) {
return 0D;
} else {
return 0.4D;

View File

@ -17,40 +17,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.visual;
package de.florianmichael.viafabricplus.fixes.particle;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes;
import net.minecraft.client.particle.*;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.SimpleParticleType;
import net.minecraft.particle.DefaultParticleType;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import org.jetbrains.annotations.ApiStatus;
import net.raphimc.vialoader.util.VersionEnum;
@ApiStatus.Internal
public class FootStepParticle1_12_2 extends SpriteBillboardParticle {
public class FootStepParticle extends SpriteBillboardParticle {
public static final Identifier ID = Identifier.of("viafabricplus", "footstep");
public static int RAW_ID;
public static int ID;
static {
final SimpleParticleType footStepType = FabricParticleTypes.simple(true);
Registry.register(Registries.PARTICLE_TYPE, ID, footStepType);
ParticleFactoryRegistry.getInstance().register(footStepType, FootStepParticle1_12_2.Factory::new);
RAW_ID = Registries.PARTICLE_TYPE.getRawId(footStepType);
}
protected FootStepParticle1_12_2(ClientWorld clientWorld, double x, double y, double z) {
protected FootStepParticle(ClientWorld clientWorld, double x, double y, double z) {
super(clientWorld, x, y, z);
this.scale = 0.125F;
@ -83,17 +71,22 @@ public class FootStepParticle1_12_2 extends SpriteBillboardParticle {
final float maxV = this.getMaxV();
final int light = this.getBrightness(tickDelta); // This is missing in the original code, that's why the particles are broken
vertexConsumer.vertex(x - scale, y, z + scale).texture(maxU, maxV).color(this.red, this.green, this.blue, this.alpha).light(light);
vertexConsumer.vertex(x + scale, y, z + scale).texture(maxU, minV).color(this.red, this.green, this.blue, this.alpha).light(light);
vertexConsumer.vertex(x + scale, y, z - scale).texture(minU, minV).color(this.red, this.green, this.blue, this.alpha).light(light);
vertexConsumer.vertex(x - scale, y, z - scale).texture(minU, maxV).color(this.red, this.green, this.blue, this.alpha).light(light);
vertexConsumer.vertex(x - scale, y, z + scale).texture(maxU, maxV).color(this.red, this.green, this.blue, this.alpha).light(light).next();
vertexConsumer.vertex(x + scale, y, z + scale).texture(maxU, minV).color(this.red, this.green, this.blue, this.alpha).light(light).next();
vertexConsumer.vertex(x + scale, y, z - scale).texture(minU, minV).color(this.red, this.green, this.blue, this.alpha).light(light).next();
vertexConsumer.vertex(x - scale, y, z - scale).texture(minU, maxV).color(this.red, this.green, this.blue, this.alpha).light(light).next();
}
public static void init() {
// Calls the static block
final DefaultParticleType footStepType = FabricParticleTypes.simple(true);
Registry.register(Registries.PARTICLE_TYPE, new Identifier("viafabricplus", "footstep"), footStepType);
ParticleFactoryRegistry.getInstance().register(footStepType, FootStepParticle.Factory::new);
ID = Registries.PARTICLE_TYPE.getRawId(footStepType);
}
public static class Factory implements ParticleFactory<SimpleParticleType> {
public static class Factory implements ParticleFactory<DefaultParticleType> {
private final SpriteProvider spriteProvider;
@ -102,12 +95,12 @@ public class FootStepParticle1_12_2 extends SpriteBillboardParticle {
}
@Override
public Particle createParticle(SimpleParticleType parameters, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) {
if (ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_12_2)) {
public Particle createParticle(DefaultParticleType parameters, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) {
if (ProtocolHack.getTargetVersion().isNewerThan(VersionEnum.r1_12_2)) {
throw new UnsupportedOperationException("FootStepParticle is not supported on versions newer than 1.12.2");
}
final FootStepParticle1_12_2 particle = new FootStepParticle1_12_2(world, x, y, z);
final FootStepParticle particle = new FootStepParticle(world, x, y, z);
particle.setSprite(this.spriteProvider);
return particle;
}

View File

@ -17,10 +17,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.visual;
package de.florianmichael.viafabricplus.fixes.replacement;
import net.minecraft.client.font.BakedGlyph;
import net.minecraft.client.font.Glyph;
import net.minecraft.client.font.GlyphRenderer;
import net.minecraft.client.font.RenderableGlyph;
import java.util.function.Function;
@ -41,7 +41,7 @@ public enum BuiltinEmptyGlyph1_12_2 implements Glyph {
}
@Override
public BakedGlyph bake(Function<RenderableGlyph, BakedGlyph> glyphRendererGetter) {
public GlyphRenderer bake(Function<RenderableGlyph, GlyphRenderer> glyphRendererGetter) {
return glyphRendererGetter.apply(new RenderableGlyph() {
@Override

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned;
package de.florianmichael.viafabricplus.fixes.replacement;
import com.mojang.authlib.yggdrasil.response.KeyPairResponse;

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned;
package de.florianmichael.viafabricplus.fixes.replacement;
import net.minecraft.block.BlockState;
import net.minecraft.client.network.ClientPlayerEntity;

View File

@ -17,16 +17,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.viaversion;
package de.florianmichael.viafabricplus.fixes.tracker;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class BedrockJoinGameTracker implements StorableObject {
public class JoinGameDataTracker extends StoredObject {
private long seed;
private String levelId;
private long enchantmentSeed;
public JoinGameDataTracker(UserConnection user) {
super(user);
}
public long getSeed() {
return seed;
}

View File

@ -17,14 +17,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.viaversion;
package de.florianmichael.viafabricplus.fixes.tracker;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
public class TeleportTracker1_7_6_10 implements StorableObject {
public class TeleportTracker extends StoredObject {
private Boolean onGround = null;
public TeleportTracker(UserConnection user) {
super(user);
}
public Boolean getPending() {
return onGround;
}

View File

@ -17,16 +17,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.viaversion;
package de.florianmichael.viafabricplus.fixes.tracker;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.StoredObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public class WolfHealthTracker1_14_4 implements StorableObject {
public class WolfHealthTracker extends StoredObject {
private final Int2FloatMap healthDataMap = new Int2FloatOpenHashMap();
public WolfHealthTracker(UserConnection user) {
super(user);
}
public float getWolfHealth(final int entityId, final float fallback) {
return this.healthDataMap.getOrDefault(entityId, fallback);
}
@ -35,4 +40,13 @@ public class WolfHealthTracker1_14_4 implements StorableObject {
this.healthDataMap.put(entityId, wolfHealth);
}
public static WolfHealthTracker get(final UserConnection userConnection) {
var tracker = userConnection.get(WolfHealthTracker.class);
if (tracker == null) {
userConnection.put(tracker = new WolfHealthTracker(userConnection));
}
return tracker;
}
}

View File

@ -1,96 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.registry.tag.BlockTags;
import org.jetbrains.annotations.ApiStatus;
import java.util.Optional;
@ApiStatus.Internal
public class EnchantmentAttributesEmulation1_20_6 {
static {
ClientTickEvents.START_WORLD_TICK.register(world -> {
if (ProtocolTranslator.getTargetVersion().newerThan(ProtocolVersion.v1_20_5)) {
return;
}
// Update generic attributes for all entities
for (Entity entity : world.getEntities()) {
if (entity.isLogicalSideForUpdatingMovement() && entity instanceof LivingEntity livingEntity) {
livingEntity.getAttributeInstance(EntityAttributes.WATER_MOVEMENT_EFFICIENCY).setBaseValue(getEquipmentLevel(Enchantments.DEPTH_STRIDER, livingEntity) / 3F);
setGenericMovementEfficiencyAttribute(livingEntity);
}
}
// Update player specific attributes for all players
for (PlayerEntity player : world.getPlayers()) {
if (!player.isLogicalSideForUpdatingMovement()) {
continue;
}
final int efficiencyLevel = getEquipmentLevel(Enchantments.EFFICIENCY, player);
if (efficiencyLevel > 0) {
player.getAttributeInstance(EntityAttributes.MINING_EFFICIENCY).setBaseValue(efficiencyLevel * efficiencyLevel + 1);
} else {
player.getAttributeInstance(EntityAttributes.MINING_EFFICIENCY).setBaseValue(0);
}
player.getAttributeInstance(EntityAttributes.SNEAKING_SPEED).setBaseValue(0.3F + getEquipmentLevel(Enchantments.SWIFT_SNEAK, player) * 0.15F);
player.getAttributeInstance(EntityAttributes.SUBMERGED_MINING_SPEED).setBaseValue(getEquipmentLevel(Enchantments.AQUA_AFFINITY, player) <= 0 ? 0.2F : 1F);
}
});
}
public static void init() {
// Calls the static block
}
/**
* Called from MixinLivingEntity as well to ensure the attribute value is set at the correct place in the entity tick logic.
* Called above just as a fallback if a mod accesses the raw attribute value directly.
*/
public static void setGenericMovementEfficiencyAttribute(final LivingEntity entity) {
final boolean isOnSoulSpeedBlock = entity.getWorld().getBlockState(entity.getVelocityAffectingPos()).isIn(BlockTags.SOUL_SPEED_BLOCKS);
if (isOnSoulSpeedBlock && getEquipmentLevel(Enchantments.SOUL_SPEED, entity) > 0) {
entity.getAttributeInstance(EntityAttributes.MOVEMENT_EFFICIENCY).setBaseValue(1);
} else {
entity.getAttributeInstance(EntityAttributes.MOVEMENT_EFFICIENCY).setBaseValue(0);
}
}
private static int getEquipmentLevel(final RegistryKey<Enchantment> enchantment, final LivingEntity entity) {
final Optional<RegistryEntry.Reference<Enchantment>> enchantmentRef = entity.getWorld().getRegistryManager().getOrThrow(RegistryKeys.ENCHANTMENT).getOptional(enchantment);
return enchantmentRef.map(e -> EnchantmentHelper.getEquipmentLevel(e, entity)).orElse(0);
}
}

View File

@ -1,82 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned;
import com.viaversion.viaversion.util.Key;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.registry.RegistryKey;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class Enchantments1_14_4 {
private static final Map<String, RegistryKey<Enchantment>> ENCHANTMENT_REGISTRY = new HashMap<>();
static {
ENCHANTMENT_REGISTRY.put("protection", Enchantments.PROTECTION);
ENCHANTMENT_REGISTRY.put("fire_protection", Enchantments.FIRE_PROTECTION);
ENCHANTMENT_REGISTRY.put("feather_falling", Enchantments.FEATHER_FALLING);
ENCHANTMENT_REGISTRY.put("blast_protection", Enchantments.BLAST_PROTECTION);
ENCHANTMENT_REGISTRY.put("projectile_protection", Enchantments.PROJECTILE_PROTECTION);
ENCHANTMENT_REGISTRY.put("respiration", Enchantments.RESPIRATION);
ENCHANTMENT_REGISTRY.put("aqua_affinity", Enchantments.AQUA_AFFINITY);
ENCHANTMENT_REGISTRY.put("thorns", Enchantments.THORNS);
ENCHANTMENT_REGISTRY.put("depth_strider", Enchantments.DEPTH_STRIDER);
ENCHANTMENT_REGISTRY.put("frost_walker", Enchantments.FROST_WALKER);
ENCHANTMENT_REGISTRY.put("binding_curse", Enchantments.BINDING_CURSE);
ENCHANTMENT_REGISTRY.put("sharpness", Enchantments.SHARPNESS);
ENCHANTMENT_REGISTRY.put("smite", Enchantments.SMITE);
ENCHANTMENT_REGISTRY.put("bane_of_arthropods", Enchantments.BANE_OF_ARTHROPODS);
ENCHANTMENT_REGISTRY.put("knockback", Enchantments.KNOCKBACK);
ENCHANTMENT_REGISTRY.put("fire_aspect", Enchantments.FIRE_ASPECT);
ENCHANTMENT_REGISTRY.put("looting", Enchantments.LOOTING);
ENCHANTMENT_REGISTRY.put("sweeping", Enchantments.SWEEPING_EDGE);
ENCHANTMENT_REGISTRY.put("efficiency", Enchantments.EFFICIENCY);
ENCHANTMENT_REGISTRY.put("silk_touch", Enchantments.SILK_TOUCH);
ENCHANTMENT_REGISTRY.put("unbreaking", Enchantments.UNBREAKING);
ENCHANTMENT_REGISTRY.put("fortune", Enchantments.FORTUNE);
ENCHANTMENT_REGISTRY.put("power", Enchantments.POWER);
ENCHANTMENT_REGISTRY.put("punch", Enchantments.PUNCH);
ENCHANTMENT_REGISTRY.put("flame", Enchantments.FLAME);
ENCHANTMENT_REGISTRY.put("infinity", Enchantments.INFINITY);
ENCHANTMENT_REGISTRY.put("luck_of_the_sea", Enchantments.LUCK_OF_THE_SEA);
ENCHANTMENT_REGISTRY.put("lure", Enchantments.LURE);
ENCHANTMENT_REGISTRY.put("loyalty", Enchantments.LOYALTY);
ENCHANTMENT_REGISTRY.put("impaling", Enchantments.IMPALING);
ENCHANTMENT_REGISTRY.put("riptide", Enchantments.RIPTIDE);
ENCHANTMENT_REGISTRY.put("channeling", Enchantments.CHANNELING);
ENCHANTMENT_REGISTRY.put("multishot", Enchantments.MULTISHOT);
ENCHANTMENT_REGISTRY.put("quick_charge", Enchantments.QUICK_CHARGE);
ENCHANTMENT_REGISTRY.put("piercing", Enchantments.PIERCING);
ENCHANTMENT_REGISTRY.put("mending", Enchantments.MENDING);
ENCHANTMENT_REGISTRY.put("vanishing_curse", Enchantments.VANISHING_CURSE);
}
public static Optional<RegistryKey<Enchantment>> getOrEmpty(final String identifier) {
if (identifier == null) {
return Optional.empty();
}
return Optional.ofNullable(ENCHANTMENT_REGISTRY.get(Key.stripMinecraftNamespace(identifier)));
}
}

View File

@ -1,73 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.versioned.visual;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.event.ChangeProtocolVersionCallback;
import de.florianmichael.viafabricplus.protocoltranslator.util.LanguageUtil;
import de.florianmichael.viafabricplus.settings.impl.VisualSettings;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.SimpleOption;
import net.minecraft.client.resource.language.TranslationStorage;
import net.minecraft.util.Language;
import org.jetbrains.annotations.ApiStatus;
/**
* Older versions only had unicode font support for some languages and therefore servers are expecting the client
* to use a unicode font, not using it on older versions can cause issues with wrong dimensions in chat components.
*/
@ApiStatus.Internal
public class UnicodeFontFix1_12_2 {
private static boolean enabled = false;
private static Runnable task = null;
static {
ChangeProtocolVersionCallback.EVENT.register((oldVersion, newVersion) -> updateUnicodeFontOverride(newVersion));
ClientTickEvents.START_CLIENT_TICK.register(client -> {
// Prevent usages of RenderSystem.recordRenderCall()
if (task != null) {
task.run();
task = null;
}
});
}
public static void init() {
// Calls the static block
}
public static void updateUnicodeFontOverride(final ProtocolVersion version) {
final SimpleOption<Boolean> option = MinecraftClient.getInstance().options.getForceUnicodeFont();
if (VisualSettings.global().forceUnicodeFontForNonAsciiLanguages.isEnabled(version)) {
if (Language.getInstance() instanceof TranslationStorage storage) {
enabled = LanguageUtil.isUnicodeFont1_12_2(storage.translations);
task = () -> option.setValue(enabled);
}
} else if (enabled) {
enabled = false;
task = () -> option.setValue(false);
}
}
}

View File

@ -1,136 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.fixes.viaversion;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.AbstractSimpleProtocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import com.viaversion.viaversion.util.Key;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import net.minecraft.network.packet.BrandCustomPayload;
import net.minecraft.network.packet.CustomPayload;
import net.minecraft.network.packet.s2c.custom.DebugGameTestAddMarkerCustomPayload;
import net.minecraft.network.packet.s2c.custom.DebugGameTestClearCustomPayload;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import java.util.HashMap;
import java.util.Map;
// Protocol to handle error handling changes in older protocols, always last element of the pipeline
public class ViaFabricPlusProtocol extends AbstractSimpleProtocol {
public static final ViaFabricPlusProtocol INSTANCE = new ViaFabricPlusProtocol();
private final Map<String, Pair<ProtocolVersion, PacketReader>> payloadDiff = new HashMap<>();
public ViaFabricPlusProtocol() {
registerMapping(BrandCustomPayload.ID, LegacyProtocolVersion.c0_0_15a_1, wrapper -> wrapper.passthrough(Types.STRING));
registerMapping(DebugGameTestAddMarkerCustomPayload.ID, ProtocolVersion.v1_14, wrapper -> {
wrapper.passthrough(Types.BLOCK_POSITION1_14);
wrapper.passthrough(Types.INT);
wrapper.passthrough(Types.STRING);
wrapper.passthrough(Types.INT);
});
registerMapping(DebugGameTestClearCustomPayload.ID, ProtocolVersion.v1_14, wrapper -> {
});
}
@Override
protected void registerPackets() {
registerClientbound(State.PLAY, getCustomPayload().getId(), getCustomPayload().getId(), wrapper -> {
final String channel = Key.namespaced(wrapper.passthrough(Types.STRING));
if (!channel.startsWith(Identifier.DEFAULT_NAMESPACE)) {
// Mods might add custom payloads that we don't want to filter, so we check for the namespace.
// Mods should NEVER use the default namespace of the game, not only to not break this code,
// but also to not break other mods and the game itself.
return;
}
final ProtocolVersion version = wrapper.user().getProtocolInfo().serverProtocolVersion();
if (!payloadDiff.containsKey(channel) || version.olderThan(payloadDiff.get(channel).getLeft())) {
// Technically, it's wrong to just drop all payloads. However, ViaVersion doesn't translate them and the server can't detect if
// we handled the payload or not, so dropping them is easier than adding a bunch of useless translations for payloads
// which don't do anything on the client anyway.
wrapper.cancel();
return;
}
if (version.olderThanOrEqualTo(ProtocolVersion.v1_20)) {
// Skip all remaining bytes after reading the payload and cancel if the payload fails to read
final PacketReader reader = payloadDiff.get(channel).getRight();
try {
reader.read(wrapper);
wrapper.read(Types.REMAINING_BYTES);
} catch (Exception ignored) {
wrapper.cancel();
}
}
});
}
@Override
public void init(UserConnection connection) {
super.init(connection);
final ProtocolVersion serverVersion = ProtocolTranslator.getTargetVersion(connection.getChannel());
// Add storages we need for different fixes here
if (serverVersion.equals(BedrockProtocolVersion.bedrockLatest)) {
connection.put(new BedrockJoinGameTracker());
} else {
if (serverVersion.olderThanOrEqualTo(ProtocolVersion.v1_14_4)) {
connection.put(new WolfHealthTracker1_14_4());
}
if (serverVersion.olderThanOrEqualTo(ProtocolVersion.v1_7_6)) {
connection.put(new TeleportTracker1_7_6_10());
}
}
}
private void registerMapping(final CustomPayload.Id<?> id, final ProtocolVersion version, final PacketReader reader) {
payloadDiff.put(id.id().toString(), new Pair<>(version, reader));
}
public static ServerboundPacketType getSetCreativeModeSlot() {
return ServerboundPackets1_21_2.SET_CREATIVE_MODE_SLOT;
}
public static ClientboundPacketType getCustomPayload() {
return ClientboundPackets1_21_2.CUSTOM_PAYLOAD;
}
@FunctionalInterface
interface PacketReader {
void read(PacketWrapper wrapper);
}
}

View File

@ -20,7 +20,6 @@
package de.florianmichael.viafabricplus.injection;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.metadata.ModMetadata;
import net.lenni0451.reflect.stream.RStream;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
@ -33,26 +32,24 @@ public class ViaFabricPlusMixinPlugin implements IMixinConfigPlugin {
public static final String INJECTOR_PACKAGE = "de.florianmichael.viafabricplus.injection.mixin.";
private static final String MC_FIXES_PACKAGE = "fixes.minecraft.";
private static final String COMPAT_PACKAGE = "compat.";
public static String VFP_VERSION;
public static String VFP_IMPL_VERSION;
public static boolean DASH_LOADER_PRESENT;
public static boolean ARMOR_SKIN_PRESENT;
public static boolean IPNEXT_PRESENT;
public static boolean MORE_CULLING_PRESENT;
public static boolean LITHIUM_PRESENT;
@Override
public void onLoad(String mixinPackage) {
final FabricLoader loader = FabricLoader.getInstance();
final ModMetadata metadata = loader.getModContainer("viafabricplus").get().getMetadata();
VFP_VERSION = metadata.getVersion().getFriendlyString();
VFP_IMPL_VERSION = metadata.getCustomValue("vfp:implVersion").getAsString();
VFP_VERSION = loader.getModContainer("viafabricplus").get().getMetadata().getVersion().getFriendlyString();
DASH_LOADER_PRESENT = loader.isModLoaded("dashloader");
ARMOR_SKIN_PRESENT = loader.isModLoaded("armorskin");
IPNEXT_PRESENT = loader.isModLoaded("inventoryprofilesnext");
MORE_CULLING_PRESENT = loader.isModLoaded("moreculling");
LITHIUM_PRESENT = loader.isModLoaded("lithium");
// Force unload some FabricAPI mixins because FabricAPI overwrites some of the elytra code
final Set<String> loadedMixins = RStream.of("org.spongepowered.asm.mixin.transformer.MixinConfig").fields().by("globalMixinList").get();
@ -68,11 +65,17 @@ public class ViaFabricPlusMixinPlugin implements IMixinConfigPlugin {
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return switch (mixinClassName) {
case INJECTOR_PACKAGE + COMPAT_PACKAGE + "ipnext.MixinAutoRefillHandler_ItemSlotMonitor" -> IPNEXT_PRESENT;
case INJECTOR_PACKAGE + COMPAT_PACKAGE + "lithium.MixinEntity" -> LITHIUM_PRESENT;
default -> true;
};
if (mixinClassName.equals(INJECTOR_PACKAGE + MC_FIXES_PACKAGE + "MixinFontStorage")) {
return !DASH_LOADER_PRESENT;
}
if (mixinClassName.equals(INJECTOR_PACKAGE + MC_FIXES_PACKAGE + "MixinInGameHud")) {
return !ARMOR_SKIN_PRESENT;
}
if (mixinClassName.equals(INJECTOR_PACKAGE + COMPAT_PACKAGE + "ipnext.MixinAutoRefillHandler_ItemSlotMonitor")) {
return IPNEXT_PRESENT;
}
return true;
}
@Override

View File

@ -20,14 +20,14 @@
package de.florianmichael.viafabricplus.injection.access;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.raphimc.vialoader.util.VersionEnum;
public interface IClientConnection {
void viaFabricPlus$setupPreNettyDecryption();
ProtocolVersion viaFabricPlus$getTargetVersion();
void viaFabricPlus$setTargetVersion(final ProtocolVersion serverVersion);
VersionEnum viaFabricPlus$getTargetVersion();
void viaFabricPlus$setTargetVersion(final VersionEnum serverVersion);
UserConnection viaFabricPlus$getUserConnection();
void viaFabricPlus$setUserConnection(final UserConnection userConnection);

View File

@ -19,7 +19,7 @@
package de.florianmichael.viafabricplus.injection.access;
import de.florianmichael.viafabricplus.fixes.versioned.ClientPlayerInteractionManager1_18_2;
import de.florianmichael.viafabricplus.fixes.ClientPlayerInteractionManager1_18_2;
public interface IClientPlayerInteractionManager {

View File

@ -19,12 +19,11 @@
package de.florianmichael.viafabricplus.injection.access;
import net.raphimc.vialegacy.protocol.classic.c0_30cpetoc0_28_30.data.ClassicProtocolExtension;
import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.data.ClassicProtocolExtension;
import java.util.EnumMap;
public interface IExtensionProtocolMetadataStorage {
EnumMap<ClassicProtocolExtension, Integer> viaFabricPlus$getServerExtensions();
}

View File

@ -19,10 +19,12 @@
package de.florianmichael.viafabricplus.injection.access;
import net.minecraft.text.Text;
public interface IItemStack {
public interface IConfirmScreen {
boolean viaFabricPlus$has1_10ViaFabricPlusTag();
void viaFabricPlus$setMessage(final Text message);
int viaFabricPlus$get1_10Count();
void viaFabricPlus$set1_10Count(final int count);
}

View File

@ -1,29 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.access;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
public interface IMultiValueDebugSampleLogImpl {
ProtocolVersion viaFabricPlus$getForcedVersion();
void viaFabricPlus$setForcedVersion(final ProtocolVersion version);
}

View File

@ -19,8 +19,11 @@
package de.florianmichael.viafabricplus.injection.access;
public interface IPlayerListHud {
import net.raphimc.vialoader.util.VersionEnum;
void viaFabricPlus$setMaxPlayers(final int maxPlayers);
public interface IPerformanceLog {
VersionEnum viaFabricPlus$getForcedVersion();
void viaFabricPlus$setForcedVersion(final VersionEnum version);
}

View File

@ -1,26 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.access;
public interface IPlayerListEntry {
int viaFabricPlus$getIndex();
}

View File

@ -19,17 +19,17 @@
package de.florianmichael.viafabricplus.injection.access;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import net.raphimc.vialoader.util.VersionEnum;
public interface IServerInfo {
ProtocolVersion viaFabricPlus$forcedVersion();
void viaFabricPlus$forceVersion(final ProtocolVersion version);
VersionEnum viaFabricPlus$forcedVersion();
void viaFabricPlus$forceVersion(final VersionEnum version);
boolean viaFabricPlus$passedDirectConnectScreen();
void viaFabricPlus$passDirectConnectScreen(final boolean state);
void viaFabricPlus$passDirectConnectScreen();
ProtocolVersion viaFabricPlus$translatingVersion();
void viaFabricPlus$setTranslatingVersion(final ProtocolVersion version);
VersionEnum viaFabricPlus$translatingVersion();
void viaFabricPlus$setTranslatingVersion(final VersionEnum version);
}

View File

@ -33,7 +33,7 @@ public abstract class MixinMain {
@Inject(method = "main", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Util;startTimerHack()V"))
private static void bootstrap(CallbackInfo ci) {
LoadCallback.EVENT.invoker().onLoad(LoadCallback.State.PRE);
ViaFabricPlus.global().init();
ViaFabricPlus.global().bootstrap();
LoadCallback.EVENT.invoker().onLoad(LoadCallback.State.POST);
}

View File

@ -19,16 +19,13 @@
package de.florianmichael.viafabricplus.injection.mixin.base.connect;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.injection.access.IClientConnection;
import de.florianmichael.viafabricplus.injection.access.IMultiValueDebugSampleLogImpl;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocoltranslator.netty.ViaFabricPlusVLLegacyPipeline;
import de.florianmichael.viafabricplus.injection.access.IPerformanceLog;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.protocolhack.netty.ViaFabricPlusVLLegacyPipeline;
import de.florianmichael.viafabricplus.protocolhack.util.VersionEnumExtension;
import io.netty.bootstrap.AbstractBootstrap;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
@ -38,15 +35,13 @@ import io.netty.channel.socket.nio.NioDatagramChannel;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.encryption.PacketDecryptor;
import net.minecraft.network.encryption.PacketEncryptor;
import net.minecraft.network.handler.HandlerNames;
import net.minecraft.network.packet.Packet;
import net.minecraft.util.profiler.MultiValueDebugSampleLogImpl;
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.minecraft.util.profiler.PerformanceLog;
import net.raphimc.vialoader.netty.CompressionReorderEvent;
import net.raphimc.vialoader.netty.VLLegacyPipeline;
import net.raphimc.vialoader.netty.VLPipeline;
import net.raphimc.vialoader.netty.viabedrock.PingEncapsulationCodec;
import net.raphimc.vialoader.util.VersionEnum;
import org.cloudburstmc.netty.channel.raknet.RakChannelFactory;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
@ -78,7 +73,7 @@ public abstract class MixinClientConnection extends SimpleChannelInboundHandler<
private UserConnection viaFabricPlus$userConnection;
@Unique
private ProtocolVersion viaFabricPlus$serverVersion;
private VersionEnum viaFabricPlus$serverVersion;
@Unique
private Cipher viaFabricPlus$decryptionCipher;
@ -91,13 +86,13 @@ public abstract class MixinClientConnection extends SimpleChannelInboundHandler<
@Inject(method = "setupEncryption", at = @At("HEAD"), cancellable = true)
private void storeDecryptionCipher(Cipher decryptionCipher, Cipher encryptionCipher, CallbackInfo ci) {
if (this.viaFabricPlus$serverVersion != null /* This happens when opening a lan server and people are joining */ && this.viaFabricPlus$serverVersion.olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
if (this.viaFabricPlus$serverVersion != null /* This happens when opening a lan server and people are joining */ && this.viaFabricPlus$serverVersion.isOlderThanOrEqualTo(VersionEnum.r1_6_4)) {
// Minecraft's encryption code is bad for us, we need to reorder the pipeline
ci.cancel();
// Minecraft 1.6.4 supports split encryption/decryption which means the server can only enable one side of the encryption
// So we only enable the encryption side and later enable the decryption side if the 1.7 -> 1.6 protocol
// tells us to do, therefore, we need to store the cipher instance.
// tells us to do, therefore we need to store the cipher instance.
this.viaFabricPlus$decryptionCipher = decryptionCipher;
// Enabling the encryption side
@ -106,77 +101,88 @@ public abstract class MixinClientConnection extends SimpleChannelInboundHandler<
}
this.encrypted = true;
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_REMOVER_NAME, HandlerNames.ENCRYPT, new PacketEncryptor(encryptionCipher));
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_REMOVER_NAME, "encrypt", new PacketEncryptor(encryptionCipher));
}
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
super.channelRegistered(ctx);
if (BedrockProtocolVersion.bedrockLatest.equals(this.viaFabricPlus$serverVersion)) { // Call channelActive manually when the channel is registered
if (VersionEnum.bedrockLatest.equals(this.viaFabricPlus$serverVersion)) {
// Call channelActive manually when the channel is registered
this.channelActive(ctx);
}
}
@WrapWithCondition(method = "channelActive", at = @At(value = "INVOKE", target = "Lio/netty/channel/SimpleChannelInboundHandler;channelActive(Lio/netty/channel/ChannelHandlerContext;)V", remap = false))
private boolean dontCallChannelActiveTwice(SimpleChannelInboundHandler<Packet<?>> instance, ChannelHandlerContext channelHandlerContext) {
return !BedrockProtocolVersion.bedrockLatest.equals(this.viaFabricPlus$serverVersion);
}
@Inject(method = "connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/util/profiler/MultiValueDebugSampleLogImpl;)Lnet/minecraft/network/ClientConnection;", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;", shift = At.Shift.BEFORE))
private static void setTargetVersion(InetSocketAddress address, boolean useEpoll, MultiValueDebugSampleLogImpl packetSizeLog, CallbackInfoReturnable<ClientConnection> cir, @Local ClientConnection clientConnection) {
// Set the target version stored in the PerformanceLog field to the ClientConnection instance
if (packetSizeLog instanceof IMultiValueDebugSampleLogImpl mixinMultiValueDebugSampleLogImpl && mixinMultiValueDebugSampleLogImpl.viaFabricPlus$getForcedVersion() != null) {
((IClientConnection) clientConnection).viaFabricPlus$setTargetVersion(mixinMultiValueDebugSampleLogImpl.viaFabricPlus$getForcedVersion());
@Redirect(method = "channelActive", at = @At(value = "INVOKE", target = "Lio/netty/channel/SimpleChannelInboundHandler;channelActive(Lio/netty/channel/ChannelHandlerContext;)V"), remap = false)
private void dontCallChannelActive(SimpleChannelInboundHandler<Packet<?>> instance, ChannelHandlerContext ctx) throws Exception {
if (!VersionEnum.bedrockLatest.equals(this.viaFabricPlus$serverVersion)) { // Don't call channelActive twice
super.channelActive(ctx);
}
}
@WrapWithCondition(method = "connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/util/profiler/MultiValueDebugSampleLogImpl;)Lnet/minecraft/network/ClientConnection;", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;resetPacketSizeLog(Lnet/minecraft/util/profiler/MultiValueDebugSampleLogImpl;)V"))
private static boolean dontSetPerformanceLog(ClientConnection instance, MultiValueDebugSampleLogImpl packetSizeLog) {
// We need to restore vanilla behaviour since we use the PerformanceLog as a way to store the target version
return !(packetSizeLog instanceof IMultiValueDebugSampleLogImpl mixinMultiValueDebugSampleLogImpl) || mixinMultiValueDebugSampleLogImpl.viaFabricPlus$getForcedVersion() == null;
@Inject(method = "connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/util/profiler/PerformanceLog;)Lnet/minecraft/network/ClientConnection;", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;", shift = At.Shift.BEFORE))
private static void setTargetVersion(InetSocketAddress address, boolean useEpoll, PerformanceLog packetSizeLog, CallbackInfoReturnable<ClientConnection> cir, @Local ClientConnection clientConnection) {
// Set the target version stored in the PerformanceLog field to the ClientConnection instance
if (packetSizeLog instanceof IPerformanceLog mixinPerformanceLog && mixinPerformanceLog.viaFabricPlus$getForcedVersion() != null) {
((IClientConnection) clientConnection).viaFabricPlus$setTargetVersion(mixinPerformanceLog.viaFabricPlus$getForcedVersion());
}
}
@Redirect(method = "connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/util/profiler/PerformanceLog;)Lnet/minecraft/network/ClientConnection;", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;resetPacketSizeLog(Lnet/minecraft/util/profiler/PerformanceLog;)V"))
private static void dontSetPerformanceLog(ClientConnection instance, PerformanceLog performanceLog) {
// Since the PerformanceLog is never null due to our changes, we need to restore vanilla behavior
if (performanceLog instanceof IPerformanceLog mixinPerformanceLog && mixinPerformanceLog.viaFabricPlus$getForcedVersion() != null) {
return;
}
instance.resetPacketSizeLog(performanceLog);
}
@Inject(method = "connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;", at = @At("HEAD"))
private static void setTargetVersion(InetSocketAddress address, boolean useEpoll, ClientConnection connection, CallbackInfoReturnable<ChannelFuture> cir) {
ProtocolVersion targetVersion = ((IClientConnection) connection).viaFabricPlus$getTargetVersion();
VersionEnum targetVersion = ((IClientConnection) connection).viaFabricPlus$getTargetVersion();
if (targetVersion == null) { // No server specific override
targetVersion = ProtocolTranslator.getTargetVersion();
targetVersion = ProtocolHack.getTargetVersion();
}
if (targetVersion == ProtocolTranslator.AUTO_DETECT_PROTOCOL) { // Auto-detect enabled (when pinging always use native version). Auto-detect is resolved in ConnectScreen mixin
targetVersion = ProtocolTranslator.NATIVE_VERSION;
if (targetVersion == VersionEnumExtension.AUTO_DETECT) { // Auto-detect enabled (when pinging always use native version). Auto-detect is resolved in ConnectScreen mixin
targetVersion = ProtocolHack.NATIVE_VERSION;
}
((IClientConnection) connection).viaFabricPlus$setTargetVersion(targetVersion);
}
@WrapOperation(method = "connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;", at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;channel(Ljava/lang/Class;)Lio/netty/bootstrap/AbstractBootstrap;", remap = false))
private static AbstractBootstrap<?, ?> useRakNetChannelFactory(Bootstrap instance, Class<? extends Channel> channelTypeClass, Operation<AbstractBootstrap<Bootstrap, Channel>> original, @Local(argsOnly = true) ClientConnection clientConnection) {
if (BedrockProtocolVersion.bedrockLatest.equals(((IClientConnection) clientConnection).viaFabricPlus$getTargetVersion())) {
return instance.channelFactory(channelTypeClass == EpollSocketChannel.class ? RakChannelFactory.client(EpollDatagramChannel.class) : RakChannelFactory.client(NioDatagramChannel.class));
} else {
return original.call(instance, channelTypeClass);
@Redirect(method = "connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;", at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;channel(Ljava/lang/Class;)Lio/netty/bootstrap/AbstractBootstrap;", remap = false))
private static AbstractBootstrap<?, ?> useRakNetChannelFactory(Bootstrap instance, Class<? extends Channel> channelTypeClass, @Local(argsOnly = true) ClientConnection clientConnection) {
if (VersionEnum.bedrockLatest.equals(((IClientConnection) clientConnection).viaFabricPlus$getTargetVersion())) {
return instance.channelFactory(channelTypeClass == EpollSocketChannel.class ?
RakChannelFactory.client(EpollDatagramChannel.class) :
RakChannelFactory.client(NioDatagramChannel.class)
);
}
return instance.channel(channelTypeClass);
}
@Redirect(method = "connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/network/ClientConnection;)Lio/netty/channel/ChannelFuture;", at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;connect(Ljava/net/InetAddress;I)Lio/netty/channel/ChannelFuture;", remap = false))
private static ChannelFuture useRakNetPingHandlers(Bootstrap instance, InetAddress inetHost, int inetPort, @Local(argsOnly = true) ClientConnection clientConnection, @Local(argsOnly = true) boolean isConnecting) {
if (BedrockProtocolVersion.bedrockLatest.equals(((IClientConnection) clientConnection).viaFabricPlus$getTargetVersion()) && !isConnecting) {
if (VersionEnum.bedrockLatest.equals(((IClientConnection) clientConnection).viaFabricPlus$getTargetVersion()) && !isConnecting) {
// Bedrock edition / RakNet has different handlers for pinging a server
return instance.register().syncUninterruptibly().channel().bind(new InetSocketAddress(0)).addListeners(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE, (ChannelFutureListener) f -> {
if (f.isSuccess()) {
f.channel().pipeline().replace(
VLPipeline.VIABEDROCK_FRAME_ENCAPSULATION_HANDLER_NAME,
ViaFabricPlusVLLegacyPipeline.VIABEDROCK_PING_ENCAPSULATION_HANDLER_NAME,
new PingEncapsulationCodec(new InetSocketAddress(inetHost, inetPort))
);
f.channel().pipeline().remove(VLPipeline.VIABEDROCK_PACKET_ENCAPSULATION_HANDLER_NAME);
f.channel().pipeline().remove(HandlerNames.SPLITTER);
}
});
} else {
return instance.connect(inetHost, inetPort);
return instance.register().syncUninterruptibly().channel().bind(new InetSocketAddress(0)).
addListeners(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE, (ChannelFutureListener) f -> {
if (f.isSuccess()) {
f.channel().pipeline().replace(
VLPipeline.VIABEDROCK_FRAME_ENCAPSULATION_HANDLER_NAME,
ViaFabricPlusVLLegacyPipeline.VIABEDROCK_PING_ENCAPSULATION_HANDLER_NAME,
new PingEncapsulationCodec(new InetSocketAddress(inetHost, inetPort))
);
f.channel().pipeline().remove(VLPipeline.VIABEDROCK_PACKET_ENCAPSULATION_HANDLER_NAME);
f.channel().pipeline().remove("splitter");
}
});
}
return instance.connect(inetHost, inetPort);
}
@Override
@ -187,7 +193,7 @@ public abstract class MixinClientConnection extends SimpleChannelInboundHandler<
this.encrypted = true;
// Enabling the decryption side for 1.6.4 if the 1.7 -> 1.6 protocol tells us to do
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_PREPENDER_NAME, HandlerNames.DECRYPT, new PacketDecryptor(this.viaFabricPlus$decryptionCipher));
this.channel.pipeline().addBefore(VLLegacyPipeline.VIALEGACY_PRE_NETTY_LENGTH_PREPENDER_NAME, "decrypt", new PacketDecryptor(this.viaFabricPlus$decryptionCipher));
}
@Override
@ -201,12 +207,12 @@ public abstract class MixinClientConnection extends SimpleChannelInboundHandler<
}
@Override
public ProtocolVersion viaFabricPlus$getTargetVersion() {
public VersionEnum viaFabricPlus$getTargetVersion() {
return this.viaFabricPlus$serverVersion;
}
@Override
public void viaFabricPlus$setTargetVersion(final ProtocolVersion serverVersion) {
public void viaFabricPlus$setTargetVersion(final VersionEnum serverVersion) {
this.viaFabricPlus$serverVersion = serverVersion;
}

View File

@ -19,7 +19,7 @@
package de.florianmichael.viafabricplus.injection.mixin.base.connect;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import io.netty.channel.Channel;
import net.minecraft.network.ClientConnection;
import org.spongepowered.asm.mixin.Final;
@ -38,7 +38,7 @@ public abstract class MixinClientConnection_1 {
@Inject(method = "initChannel", at = @At("RETURN"))
private void injectViaIntoPipeline(Channel channel, CallbackInfo ci) {
ProtocolTranslator.injectViaPipeline(this.field_11663, channel);
ProtocolHack.injectViaPipeline(this.field_11663, channel);
}
}

View File

@ -23,8 +23,8 @@ import de.florianmichael.viafabricplus.injection.access.IClientConnection;
import net.minecraft.client.network.ClientLoginNetworkHandler;
import net.minecraft.network.ClientConnection;
import net.minecraft.text.Text;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocol.release.r1_6_4tor1_7_2_5.storage.ProtocolMetadataStorage;
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.storage.ProtocolMetadataStorage;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -43,7 +43,7 @@ public abstract class MixinClientLoginNetworkHandler {
@Inject(method = "joinServerSession", at = @At("HEAD"), cancellable = true)
public void onlyVerifySessionInOnlineMode(String serverId, CallbackInfoReturnable<Text> cir) {
final IClientConnection mixinClientConnection = (IClientConnection) connection;
if (mixinClientConnection.viaFabricPlus$getTargetVersion().olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
if (mixinClientConnection.viaFabricPlus$getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_6_4)) {
// We are in the 1.7 -> 1.6 protocol, so we need to skip the joinServer call
// if the server is in offline mode, due the packet changes <-> networking changes
// Minecraft's networking code is bad for us.

View File

@ -1,46 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.base.connect;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import net.minecraft.client.option.GameOptions;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(GameOptions.class)
public abstract class MixinGameOptions {
@Shadow
public boolean useNativeTransport;
/**
* @author RK_01
* @reason Needed as an indicator if the client wants to ping a server or connect to a server
*/
@Overwrite
public boolean shouldUseNativeTransport() {
if (!this.useNativeTransport) {
ViaFabricPlus.global().getLogger().error("Native transport is disabled, but enabling it anyway since we use it as an indicator if the client wants to ping a server or connect to a server.");
}
return true;
}
}

View File

@ -19,7 +19,6 @@
package de.florianmichael.viafabricplus.injection.mixin.base.integration;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import de.florianmichael.viafabricplus.screen.base.PerServerVersionScreen;
import de.florianmichael.viafabricplus.settings.impl.GeneralSettings;
@ -29,6 +28,7 @@ import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.text.Text;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -62,12 +62,7 @@ public abstract class MixinAddServerScreen extends Screen {
@Inject(method = "init", at = @At("RETURN"))
private void addVersionSetterButton(CallbackInfo ci) {
final int buttonPosition = GeneralSettings.global().addServerScreenButtonOrientation.getIndex();
if (buttonPosition == 0) { // Off
return;
}
final ProtocolVersion forcedVersion = ((IServerInfo) server).viaFabricPlus$forcedVersion();
final VersionEnum forcedVersion = ((IServerInfo) server).viaFabricPlus$forcedVersion();
// Restore input if the user cancels the version selection screen (or if the user is editing an existing server)
if (viaFabricPlus$nameField != null && viaFabricPlus$addressField != null) {
@ -78,7 +73,8 @@ public abstract class MixinAddServerScreen extends Screen {
viaFabricPlus$addressField = null;
}
ButtonWidget.Builder buttonBuilder = ButtonWidget.builder(forcedVersion == null ? Text.translatable("base.viafabricplus.set_version") : Text.of(forcedVersion.getName()), button -> {
// Create the button
ButtonWidget.Builder buttonBuilder = ButtonWidget.builder(forcedVersion == null ? Text.translatable("base.viafabricplus.set_version") : Text.literal(forcedVersion.getName()), button -> {
// Store current input in case the user cancels the version selection
viaFabricPlus$nameField = serverNameField.getText();
viaFabricPlus$addressField = addressField.getText();
@ -86,8 +82,11 @@ public abstract class MixinAddServerScreen extends Screen {
client.setScreen(new PerServerVersionScreen(this, version -> ((IServerInfo) server).viaFabricPlus$forceVersion(version)));
}).size(98, 20);
// Set the button's position according to the configured orientation and add the button to the screen
this.addDrawableChild(GeneralSettings.withOrientation(buttonBuilder, buttonPosition, width, height).build());
// Set the button's position according to the configured orientation
buttonBuilder = GeneralSettings.withOrientation(buttonBuilder, GeneralSettings.global().addServerScreenButtonOrientation.getIndex(), width, height);
// Add the button to the screen
this.addDrawableChild(buttonBuilder.build());
}
}

View File

@ -1,48 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.base.integration;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.settings.impl.DebugSettings;
import io.netty.channel.ChannelHandlerContext;
import net.minecraft.network.ClientConnection;
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.net.ConnectException;
import java.net.SocketException;
@Mixin(ClientConnection.class)
public abstract class MixinClientConnection {
@Inject(method = "exceptionCaught", at = @At("HEAD"))
private void printNetworkingErrors(ChannelHandlerContext context, Throwable ex, CallbackInfo ci) {
if (DebugSettings.global().printNetworkingErrorsToLogs.getValue()) {
if (ex instanceof SocketException || ex instanceof ConnectException) {
// Thrown when server is not reachable
return;
}
ViaFabricPlus.global().getLogger().error("An exception occurred while handling a packet", ex);
}
}
}

View File

@ -1,59 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.base.integration;
import de.florianmichael.viafabricplus.injection.access.IConfirmScreen;
import net.minecraft.client.gui.screen.ConfirmScreen;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ConfirmScreen.class)
public abstract class MixinConfirmScreen implements IConfirmScreen {
@Mutable
@Shadow
@Final
private Text message;
@Shadow
protected abstract void init();
@Unique
private boolean viaFabricPlus$selfInflicted = false;
@Inject(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;clamp(III)I", shift = At.Shift.AFTER), cancellable = true)
private void preventButtonClearing(CallbackInfo ci) {
if (viaFabricPlus$selfInflicted) {
viaFabricPlus$selfInflicted = false;
ci.cancel();
}
}
@Override
public void viaFabricPlus$setMessage(Text message) {
viaFabricPlus$selfInflicted = true;
this.message = message;
this.init();
}
}

View File

@ -21,12 +21,12 @@ package de.florianmichael.viafabricplus.injection.mixin.base.integration;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocoltranslator.impl.provider.vialegacy.ViaFabricPlusClassicMPPassProvider;
import de.florianmichael.viafabricplus.protocoltranslator.util.ProtocolVersionDetector;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.protocolhack.impl.provider.vialegacy.ViaFabricPlusClassicMPPassProvider;
import de.florianmichael.viafabricplus.protocolhack.util.ProtocolVersionDetector;
import de.florianmichael.viafabricplus.protocolhack.util.VersionEnumExtension;
import de.florianmichael.viafabricplus.settings.impl.AuthenticationSettings;
import io.netty.channel.ChannelFuture;
import net.minecraft.client.gui.screen.multiplayer.ConnectScreen;
@ -34,6 +34,7 @@ import net.minecraft.client.network.ServerInfo;
import net.minecraft.client.session.Session;
import net.minecraft.network.ClientConnection;
import net.minecraft.text.Text;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -61,21 +62,20 @@ public abstract class MixinConnectScreen_1 {
private ChannelFuture setServerInfoAndHandleDisconnect(InetSocketAddress address, boolean useEpoll, ClientConnection connection, Operation<ChannelFuture> original) {
final IServerInfo mixinServerInfo = (IServerInfo) this.field_40415;
ProtocolVersion targetVersion = ProtocolTranslator.getTargetVersion();
VersionEnum targetVersion = ProtocolHack.getTargetVersion();
if (mixinServerInfo.viaFabricPlus$forcedVersion() != null && !mixinServerInfo.viaFabricPlus$passedDirectConnectScreen()) {
targetVersion = mixinServerInfo.viaFabricPlus$forcedVersion();
mixinServerInfo.viaFabricPlus$passDirectConnectScreen(false); // reset state
}
if (targetVersion == ProtocolTranslator.AUTO_DETECT_PROTOCOL) {
if (targetVersion == VersionEnumExtension.AUTO_DETECT) {
this.field_2416.setStatus(Text.translatable("base.viafabricplus.detecting_server_version"));
targetVersion = ProtocolVersionDetector.get(address, ProtocolTranslator.NATIVE_VERSION);
targetVersion = ProtocolVersionDetector.get(address, ProtocolHack.NATIVE_VERSION);
}
ProtocolTranslator.setTargetVersion(targetVersion, true);
ProtocolHack.setTargetVersion(targetVersion, true);
this.viaFabricPlus$useClassiCubeAccount = AuthenticationSettings.global().setSessionNameToClassiCubeNameInServerList.getValue() && ViaFabricPlusClassicMPPassProvider.classicubeMPPass != null;
this.viaFabricPlus$useClassiCubeAccount = AuthenticationSettings.global().setSessionNameToClassiCubeNameInServerList.getValue() && ViaFabricPlusClassicMPPassProvider.classicMpPassForNextJoin != null;
final ChannelFuture future = original.call(address, useEpoll, connection);
ProtocolTranslator.injectPreviousVersionReset(future.channel());
future.channel().closeFuture().addListener(channel -> ProtocolHack.resetPreviousVersion());
return future;
}
@ -84,8 +84,11 @@ public abstract class MixinConnectScreen_1 {
private String useClassiCubeUsername(Session instance) {
if (this.viaFabricPlus$useClassiCubeAccount) {
final var account = ViaFabricPlus.global().getSaveManager().getAccountsSave().getClassicubeAccount();
if (account != null) return account.username();
if (account != null) {
return account.username();
}
}
return instance.getUsername();
}

View File

@ -21,23 +21,23 @@ package de.florianmichael.viafabricplus.injection.mixin.base.integration;
import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viafabricplus.fixes.viaversion.BedrockJoinGameTracker;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.fixes.tracker.JoinGameDataTracker;
import de.florianmichael.viafabricplus.injection.ViaFabricPlusMixinPlugin;
import de.florianmichael.viafabricplus.injection.access.IChunkTracker;
import de.florianmichael.viafabricplus.injection.access.IRakSessionCodec;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.settings.impl.GeneralSettings;
import de.florianmichael.viafabricplus.util.ChatUtil;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.hud.DebugHud;
import net.minecraft.util.Formatting;
import net.raphimc.viabedrock.protocol.data.enums.bedrock.ServerAuthMovementMode;
import net.raphimc.viabedrock.protocol.data.enums.bedrock.ServerMovementModes;
import net.raphimc.viabedrock.protocol.storage.ChunkTracker;
import net.raphimc.viabedrock.protocol.storage.GameSessionStorage;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialegacy.protocol.classic.c0_30cpetoc0_28_30.storage.ExtensionProtocolMetadataStorage;
import net.raphimc.vialegacy.protocol.release.r1_1tor1_2_1_3.storage.SeedStorage;
import net.raphimc.vialegacy.protocol.release.r1_7_6_10tor1_8.storage.EntityTracker;
import net.raphimc.vialegacy.protocols.classic.protocolc0_28_30toc0_28_30cpe.storage.ExtensionProtocolMetadataStorage;
import net.raphimc.vialegacy.protocols.release.protocol1_2_1_3to1_1.storage.SeedStorage;
import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.storage.EntityTracker;
import org.cloudburstmc.netty.channel.raknet.RakClientChannel;
import org.cloudburstmc.netty.handler.codec.raknet.common.RakSessionCodec;
import org.spongepowered.asm.mixin.Mixin;
@ -54,14 +54,14 @@ public abstract class MixinDebugHud {
@Inject(method = "getLeftText", at = @At("RETURN"))
public void addViaFabricPlusInformation(CallbackInfoReturnable<List<String>> cir) {
if (!GeneralSettings.global().showExtraInformationInDebugHud.getValue()) { // Only show if enabled
if (!GeneralSettings.global().showExtraInformationInDebugHud.getValue()) {
return;
}
if (MinecraftClient.getInstance().isInSingleplayer() && MinecraftClient.getInstance().player != null) { // Don't show in singleplayer
if (MinecraftClient.getInstance().isInSingleplayer() && MinecraftClient.getInstance().player != null) {
return;
}
final UserConnection userConnection = ProtocolTranslator.getPlayNetworkUserConnection();
if (userConnection == null) { // Only show if ViaVersion is active
final UserConnection userConnection = ProtocolHack.getPlayNetworkUserConnection();
if (userConnection == null) { // Via is not translating this session
return;
}
@ -71,33 +71,47 @@ public abstract class MixinDebugHud {
// Title
information.add(ChatUtil.PREFIX + Formatting.RESET + " " + ViaFabricPlusMixinPlugin.VFP_VERSION);
// Connection
// common
final ProtocolInfo info = userConnection.getProtocolInfo();
information.add("P: " + info.getPipeline().pipes().size() + " C: " + info.protocolVersion() + " S: " + info.serverProtocolVersion());
information.add(
"P: " + info.getPipeline().pipes().size() +
" C: " + ProtocolVersion.getProtocol(info.getProtocolVersion()) +
" S: " + ProtocolVersion.getProtocol(info.getServerProtocolVersion())
);
// 1.7.10
// r1_7_10
final EntityTracker entityTracker1_7_10 = userConnection.get(EntityTracker.class);
if (entityTracker1_7_10 != null) {
information.add("1.7 Entities: " + entityTracker1_7_10.getTrackedEntities().size() + ", Virtual holograms: " + entityTracker1_7_10.getVirtualHolograms().size());
information.add(
"1.7 Entities: " + entityTracker1_7_10.getTrackedEntities().size() +
", Virtual holograms: " + entityTracker1_7_10.getVirtualHolograms().size()
);
}
// 1.1
// r1_1
final SeedStorage seedStorage = userConnection.get(SeedStorage.class);
if (seedStorage != null && userConnection.getProtocolInfo().serverProtocolVersion().newerThanOrEqualTo(LegacyProtocolVersion.a1_2_0toa1_2_1_1)) {
if (seedStorage != null) {
information.add("World Seed: " + seedStorage.seed);
}
// c0.30 cpe
// c0.30cpe
final ExtensionProtocolMetadataStorage extensionProtocolMetadataStorage = userConnection.get(ExtensionProtocolMetadataStorage.class);
if (extensionProtocolMetadataStorage != null) {
information.add("CPE extensions: " + extensionProtocolMetadataStorage.getExtensionCount());
}
// Bedrock
final BedrockJoinGameTracker joinGameDataTracker = userConnection.get(BedrockJoinGameTracker.class);
// bedrock
final JoinGameDataTracker joinGameDataTracker = userConnection.get(JoinGameDataTracker.class);
if (joinGameDataTracker != null) {
final ServerAuthMovementMode movementMode = userConnection.get(GameSessionStorage.class).getMovementMode();
information.add("Bedrock Level: " + joinGameDataTracker.getLevelId() + ", Enchantment Seed: " + joinGameDataTracker.getEnchantmentSeed() + ", Movement: " + movementMode.name());
final int movementMode = userConnection.get(GameSessionStorage.class).getMovementMode();
String movement = "Server with rewind";
if (movementMode == ServerMovementModes.CLIENT) {
movement = "Client";
} else if (movementMode == ServerMovementModes.SERVER) {
movement = "Server";
}
information.add("Bedrock Level: " + joinGameDataTracker.getLevelId() + ", Enchantment Seed: " + joinGameDataTracker.getEnchantmentSeed() + ", Movement: " + movement);
}
if (joinGameDataTracker != null) {
information.add("World Seed: " + joinGameDataTracker.getSeed());

View File

@ -20,14 +20,14 @@
package de.florianmichael.viafabricplus.injection.mixin.base.integration;
import com.viaversion.viaversion.api.connection.UserConnection;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import de.florianmichael.viafabricplus.settings.impl.GeneralSettings;
import de.florianmichael.viafabricplus.util.ChatUtil;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;
import net.raphimc.vialegacy.protocol.classic.c0_28_30toa1_0_15.storage.ClassicProgressStorage;
import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.storage.ClassicProgressStorage;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -44,7 +44,7 @@ public abstract class MixinDownloadingTerrainScreen extends Screen {
private void renderClassicProgress(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
if (GeneralSettings.global().showClassicLoadingProgressInConnectScreen.getValue()) {
// Check if ViaVersion is translating
final UserConnection connection = ProtocolTranslator.getPlayNetworkUserConnection();
final UserConnection connection = ProtocolHack.getPlayNetworkUserConnection();
if (connection == null) {
return;
}

View File

@ -19,15 +19,10 @@
package de.florianmichael.viafabricplus.injection.mixin.base.integration;
import com.llamalad7.mixinextras.sugar.Local;
import de.florianmichael.viafabricplus.event.PostGameLoadCallback;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.RunArgs;
import net.minecraft.network.ClientConnection;
import net.minecraft.resource.ResourcePackManager;
import net.minecraft.server.SaveLoader;
import net.minecraft.world.level.storage.LevelStorage;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -41,10 +36,11 @@ public abstract class MixinMinecraftClient {
PostGameLoadCallback.EVENT.invoker().postGameLoad();
}
@Inject(method = "startIntegratedServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;connect(Ljava/lang/String;ILnet/minecraft/network/listener/ClientLoginPacketListener;)V", shift = At.Shift.BEFORE))
private void disableProtocolTranslator(LevelStorage.Session session, ResourcePackManager dataPackManager, SaveLoader saveLoader, boolean newWorld, CallbackInfo ci, @Local ClientConnection clientConnection) {
ProtocolTranslator.setTargetVersion(ProtocolTranslator.NATIVE_VERSION, true);
ProtocolTranslator.injectPreviousVersionReset(clientConnection.channel);
@Inject(method = "startIntegratedServer", at = @At("HEAD"))
private void disableProtocolHack(CallbackInfo ci) {
// Set the target version to the native version when starting a singleplayer world
// This will automatically reload all the mappings and reset the target version to the forced version
ProtocolHack.setTargetVersion(ProtocolHack.NATIVE_VERSION);
}
}

View File

@ -19,20 +19,11 @@
package de.florianmichael.viafabricplus.injection.mixin.base.integration;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.fixes.ClientsideFixes;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.screen.base.ProtocolSelectionScreen;
import de.florianmichael.viafabricplus.settings.impl.GeneralSettings;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.network.ServerAddress;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -48,27 +39,14 @@ public abstract class MixinMultiplayerScreen extends Screen {
@Inject(method = "init", at = @At("RETURN"))
private void addProtocolSelectionButton(CallbackInfo ci) {
final int buttonPosition = GeneralSettings.global().multiplayerScreenButtonOrientation.getIndex();
if (buttonPosition == 0) { // Off
return;
}
ButtonWidget.Builder builder = ButtonWidget.builder(Text.of("ViaFabricPlus"), button -> ProtocolSelectionScreen.INSTANCE.open(this)).size(98, 20);
// Create the button
var builder = ButtonWidget.builder(Text.literal("ViaFabricPlus"), button -> ProtocolSelectionScreen.INSTANCE.open(this)).size(98, 20);
// Set the button's position according to the configured orientation and add the button to the screen
this.addDrawableChild(GeneralSettings.withOrientation(builder, buttonPosition, width, height).build());
}
// Set the button's position according to the configured orientation
builder = GeneralSettings.withOrientation(builder, GeneralSettings.global().multiplayerScreenButtonOrientation.getIndex(), width, height);
@WrapOperation(method = "connect(Lnet/minecraft/client/network/ServerInfo;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ServerAddress;parse(Ljava/lang/String;)Lnet/minecraft/client/network/ServerAddress;"))
private ServerAddress replaceDefaultPort(String address, Operation<ServerAddress> original, @Local(argsOnly = true) ServerInfo entry) {
final IServerInfo mixinServerInfo = (IServerInfo) entry;
ProtocolVersion version;
if (mixinServerInfo.viaFabricPlus$passedDirectConnectScreen()) {
version = ProtocolTranslator.getTargetVersion();
} else {
version = mixinServerInfo.viaFabricPlus$forcedVersion();
}
return original.call(ClientsideFixes.replaceDefaultPort(address, version));
// Add the button to the screen
this.addDrawableChild(builder.build());
}
}

View File

@ -19,7 +19,6 @@
package de.florianmichael.viafabricplus.injection.mixin.base.integration;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.injection.access.IClientConnection;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import net.minecraft.SharedConstants;
@ -27,6 +26,9 @@ import net.minecraft.client.network.ServerInfo;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.listener.ClientQueryPacketListener;
import net.minecraft.network.packet.s2c.query.QueryResponseS2CPacket;
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -55,11 +57,31 @@ public abstract class MixinMultiplayerServerListPinger_1 implements ClientQueryP
}
@Inject(method = "onResponse", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;send(Lnet/minecraft/network/packet/Packet;)V", shift = At.Shift.AFTER))
private void fixVersionComparison(CallbackInfo ci) {
final ProtocolVersion version = ((IClientConnection) this.field_3774).viaFabricPlus$getTargetVersion();
private void setProtocolVersion(CallbackInfo ci) {
final VersionEnum version = ((IClientConnection) this.field_3774).viaFabricPlus$getTargetVersion();
// ViaVersion is not translating the current connection, so we don't need to do anything
if (version == null) {
return;
}
final boolean isCompatible;
if (version.isOlderThanOrEqualTo(VersionEnum.r1_6_4)) {
// Because of ViaVersion not supporting legacy minecraft versions where protocol ids are overlapping, ViaLegacy
// has its own protocol id offset, where realVersion = -(ViaLegacyVersion >> 2). Normally ViaVersion sends the client
// version to the client so its detection doesn't break when checking for serverVersion == clientVersion, but since
// ViaLegacy doesn't do that, we have to do it ourselves
isCompatible = LegacyProtocolVersion.getRealProtocolVersion(version.getVersion()) == this.field_3776.protocolVersion;
} else if (version.equals(VersionEnum.bedrockLatest)) {
// Bedrock edition doesn't have a protocol id like the Java edition, ViaBedrock also has its own protocol id offset
// Which we need to remove to get the real protocol id
isCompatible = version.getVersion() - BedrockProtocolVersion.PROTOCOL_ID_OVERLAP_PREVENTION_OFFSET == this.field_3776.protocolVersion;
} else {
return;
}
// If the server is compatible with the client, we set the protocol version to the client version
if (version != null && version.getVersion() == this.field_3776.protocolVersion) {
if (isCompatible) {
this.field_3776.protocolVersion = SharedConstants.getProtocolVersion();
}
}

View File

@ -19,33 +19,22 @@
package de.florianmichael.viafabricplus.injection.mixin.base.integration;
import com.google.common.collect.Lists;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.settings.impl.GeneralSettings;
import de.florianmichael.viafabricplus.settings.impl.VisualSettings;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
import net.minecraft.client.gui.screen.world.WorldIcon;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.text.OrderedText;
import net.minecraft.text.StringVisitable;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.*;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
@Mixin(MultiplayerServerListWidget.ServerEntry.class)
public abstract class MixinMultiplayerServerListWidget_ServerEntry {
@ -54,86 +43,19 @@ public abstract class MixinMultiplayerServerListWidget_ServerEntry {
@Final
private ServerInfo server;
@Mutable
@Shadow
@Final
private WorldIcon icon;
@Unique
private boolean viaFabricPlus$disableServerPinging = false;
@WrapWithCondition(method = "render", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/ThreadPoolExecutor;submit(Ljava/lang/Runnable;)Ljava/util/concurrent/Future;"))
private boolean disableServerPinging(ThreadPoolExecutor instance, Runnable runnable) {
ProtocolVersion version = ((IServerInfo) server).viaFabricPlus$forcedVersion();
if (version == null) version = ProtocolTranslator.getTargetVersion();
viaFabricPlus$disableServerPinging = VisualSettings.global().disableServerPinging.isEnabled(version);
if (viaFabricPlus$disableServerPinging) {
this.server.version = Text.of(version.getName()); // Show target version
}
return !viaFabricPlus$disableServerPinging;
}
@Redirect(method = "render", at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/ServerInfo$Status;INCOMPATIBLE:Lnet/minecraft/client/network/ServerInfo$Status;"))
private ServerInfo.Status disableServerPinging() {
if (viaFabricPlus$disableServerPinging) {
return this.server.getStatus(); // server version will always be shown (as we don't have a player count anyway)
} else {
return ServerInfo.Status.INCOMPATIBLE;
}
}
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/TextRenderer;wrapLines(Lnet/minecraft/text/StringVisitable;I)Ljava/util/List;"))
private List<OrderedText> disableServerPinging(TextRenderer instance, StringVisitable text, int width) {
if (viaFabricPlus$disableServerPinging) { // server label will just show the server address
return instance.wrapLines(Text.of(server.address), width);
} else {
return instance.wrapLines(text, width);
}
}
@ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawText(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;IIIZ)I"), index = 2)
private int disableServerPinging(int x) {
if (viaFabricPlus$disableServerPinging) { // Move server label to the right (as we remove the ping bar)
x += 15 /* ping bar width */ - 3 /* magical offset */;
}
return x;
}
@WrapWithCondition(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawGuiTexture(Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIII)V", ordinal = 0))
private boolean disableServerPinging(DrawContext instance, Function<Identifier, RenderLayer> renderLayers, Identifier sprite, int x, int y, int width, int height) {
return !viaFabricPlus$disableServerPinging; // Remove ping bar
}
@WrapWithCondition(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/multiplayer/MultiplayerScreen;setTooltip(Ljava/util/List;)V"))
private boolean disableServerPinging(MultiplayerScreen instance, List<Text> tooltip) {
return !viaFabricPlus$disableServerPinging; // Remove player list tooltip
}
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/world/WorldIcon;getTextureId()Lnet/minecraft/util/Identifier;"))
private Identifier disableServerPinging(WorldIcon instance) {
if (viaFabricPlus$disableServerPinging) { // Remove server icon
return WorldIcon.UNKNOWN_SERVER_ID;
} else {
return this.icon.getTextureId();
}
}
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/multiplayer/MultiplayerScreen;setTooltip(Lnet/minecraft/text/Text;)V"))
private void drawTranslatingState(MultiplayerScreen instance, Text text) {
if (viaFabricPlus$disableServerPinging) { // Remove ping bar tooltip
return;
}
final List<Text> tooltips = new ArrayList<>();
tooltips.add(text);
@WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/multiplayer/MultiplayerScreen;setMultiplayerScreenTooltip(Ljava/util/List;)V", ordinal = 0))
private void drawTranslatingState(MultiplayerScreen instance, List<Text> tooltip, Operation<Void> original) {
final List<Text> tooltipCopy = new ArrayList<>(tooltip);
if (GeneralSettings.global().showAdvertisedServerVersion.getValue()) {
final ProtocolVersion version = ((IServerInfo) server).viaFabricPlus$translatingVersion();
if (version != null) {
tooltips.add(Text.translatable("base.viafabricplus.via_translates_to", version.getName() + " (" + version.getOriginalVersion() + ")"));
tooltips.add(Text.translatable("base.viafabricplus.server_version", server.version.getString() + " (" + server.protocolVersion + ")"));
final VersionEnum versionEnum = ((IServerInfo) server).viaFabricPlus$translatingVersion();
if (versionEnum != null) {
tooltipCopy.add(Text.translatable("base.viafabricplus.via_translates_to", versionEnum.getName() + " (" + versionEnum.getOriginalVersion() + ")"));
tooltipCopy.add(Text.translatable("base.viafabricplus.server_version", server.version.getString() + " (" + server.protocolVersion + ")"));
}
}
instance.setTooltip(Lists.transform(tooltips, Text::asOrderedText));
original.call(instance, tooltipCopy);
}
}

View File

@ -19,24 +19,23 @@
package de.florianmichael.viafabricplus.injection.mixin.base.perserverversion;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.network.ServerInfo;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(MultiplayerScreen.class)
public abstract class MixinMultiplayerScreen {
@Shadow protected abstract void connect(ServerInfo entry);
@WrapOperation(method = "directConnect", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/multiplayer/MultiplayerScreen;connect(Lnet/minecraft/client/network/ServerInfo;)V"))
private void storeDirectConnectionPhase(MultiplayerScreen instance, ServerInfo entry, Operation<Void> original) {
((IServerInfo) entry).viaFabricPlus$passDirectConnectScreen(true);
original.call(instance, entry);
@Redirect(method = "directConnect", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/multiplayer/MultiplayerScreen;connect(Lnet/minecraft/client/network/ServerInfo;)V"))
private void storeDirectConnectionPhase(MultiplayerScreen instance, ServerInfo entry) {
((IServerInfo) entry).viaFabricPlus$passDirectConnectScreen();
connect(entry);
}
}

View File

@ -19,49 +19,40 @@
package de.florianmichael.viafabricplus.injection.mixin.base.perserverversion;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import de.florianmichael.viafabricplus.fixes.ClientsideFixes;
import de.florianmichael.viafabricplus.injection.access.IMultiValueDebugSampleLogImpl;
import de.florianmichael.viafabricplus.injection.access.IPerformanceLog;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import net.minecraft.client.network.MultiplayerServerListPinger;
import net.minecraft.client.network.ServerAddress;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.network.ClientConnection;
import net.minecraft.util.profiler.MultiValueDebugSampleLogImpl;
import net.minecraft.util.profiler.PerformanceLog;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.net.InetSocketAddress;
@Mixin(MultiplayerServerListPinger.class)
public abstract class MixinMultiplayerServerListPinger {
@WrapOperation(method = "add", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ServerAddress;parse(Ljava/lang/String;)Lnet/minecraft/client/network/ServerAddress;"))
private ServerAddress replaceDefaultPort(String address, Operation<ServerAddress> original, @Local(argsOnly = true) ServerInfo entry) {
// Replace port when pinging the server and the forced version is set
return original.call(ClientsideFixes.replaceDefaultPort(address, ((IServerInfo) entry).viaFabricPlus$forcedVersion()));
}
@Redirect(method = "add", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/util/profiler/PerformanceLog;)Lnet/minecraft/network/ClientConnection;"))
private ClientConnection setForcedVersion(InetSocketAddress address, boolean useEpoll, PerformanceLog packetSizeLog, @Local ServerInfo serverInfo) {
final VersionEnum forcedVersion = ((IServerInfo) serverInfo).viaFabricPlus$forcedVersion();
@WrapOperation(method = "add", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;connect(Ljava/net/InetSocketAddress;ZLnet/minecraft/util/profiler/MultiValueDebugSampleLogImpl;)Lnet/minecraft/network/ClientConnection;"))
private ClientConnection setForcedVersion(InetSocketAddress address, boolean useEpoll, MultiValueDebugSampleLogImpl packetSizeLog, Operation<ClientConnection> original, @Local(argsOnly = true) ServerInfo serverInfo) {
final IServerInfo mixinServerInfo = (IServerInfo) serverInfo;
if (mixinServerInfo.viaFabricPlus$forcedVersion() != null && !mixinServerInfo.viaFabricPlus$passedDirectConnectScreen()) {
if (forcedVersion != null && !((IServerInfo) serverInfo).viaFabricPlus$passedDirectConnectScreen()) {
// We use the PerformanceLog field to store the forced version since it's always null when pinging a server
// So we can create a dummy instance, store the forced version in it and later destroy the instance again
// To avoid any side effects, we also support cases where a mod is also creating a PerformanceLog instance
if (packetSizeLog == null) {
packetSizeLog = new MultiValueDebugSampleLogImpl(1);
packetSizeLog = new PerformanceLog();
}
// Attach the forced version to the PerformanceLog instance
((IMultiValueDebugSampleLogImpl) packetSizeLog).viaFabricPlus$setForcedVersion(mixinServerInfo.viaFabricPlus$forcedVersion());
mixinServerInfo.viaFabricPlus$passDirectConnectScreen(false);
((IPerformanceLog) packetSizeLog).viaFabricPlus$setForcedVersion(forcedVersion);
}
return original.call(address, useEpoll, packetSizeLog);
return ClientConnection.connect(address, useEpoll, packetSizeLog);
}
}

View File

@ -19,25 +19,25 @@
package de.florianmichael.viafabricplus.injection.mixin.base.perserverversion;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.injection.access.IMultiValueDebugSampleLogImpl;
import net.minecraft.util.profiler.MultiValueDebugSampleLogImpl;
import de.florianmichael.viafabricplus.injection.access.IPerformanceLog;
import net.minecraft.util.profiler.PerformanceLog;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(MultiValueDebugSampleLogImpl.class)
public abstract class MixinMultiValueDebugSampleLogImpl implements IMultiValueDebugSampleLogImpl {
@Mixin(PerformanceLog.class)
public abstract class MixinPerformanceLog implements IPerformanceLog {
@Unique
private ProtocolVersion viaFabricPlus$forcedVersion;
private VersionEnum viaFabricPlus$forcedVersion;
@Override
public ProtocolVersion viaFabricPlus$getForcedVersion() {
public VersionEnum viaFabricPlus$getForcedVersion() {
return this.viaFabricPlus$forcedVersion;
}
@Override
public void viaFabricPlus$setForcedVersion(ProtocolVersion version) {
public void viaFabricPlus$setForcedVersion(VersionEnum version) {
this.viaFabricPlus$forcedVersion = version;
}

View File

@ -19,12 +19,10 @@
package de.florianmichael.viafabricplus.injection.mixin.base.perserverversion;
import com.llamalad7.mixinextras.sugar.Local;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.injection.access.IServerInfo;
import de.florianmichael.viafabricplus.save.impl.SettingsSave;
import net.minecraft.client.network.ServerInfo;
import net.minecraft.nbt.NbtCompound;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@ -32,6 +30,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(ServerInfo.class)
public abstract class MixinServerInfo implements IServerInfo {
@ -40,26 +39,30 @@ public abstract class MixinServerInfo implements IServerInfo {
public String name;
@Unique
private ProtocolVersion viaFabricPlus$forcedVersion = null;
private VersionEnum viaFabricPlus$forcedVersion = null;
@Unique
private boolean viaFabricPlus$passedDirectConnectScreen;
@Unique
private ProtocolVersion viaFabricPlus$translatingVersion;
private VersionEnum viaFabricPlus$translatingVersion;
@Inject(method = "toNbt", at = @At("TAIL"))
private void saveForcedVersion(CallbackInfoReturnable<NbtCompound> cir, @Local NbtCompound nbtCompound) {
if (viaFabricPlus$forcedVersion != null) {
nbtCompound.putString("viafabricplus_forcedversion", viaFabricPlus$forcedVersion.getName());
@Inject(method = "toNbt", at = @At("TAIL"), locals = LocalCapture.CAPTURE_FAILHARD)
private void saveForcedVersion(CallbackInfoReturnable<NbtCompound> cir, NbtCompound nbtCompound) {
if (viaFabricPlus$forcedVersion == null) {
return;
}
nbtCompound.putInt("viafabricplus_forcedversion", viaFabricPlus$forcedVersion.getOriginalVersion());
}
@Inject(method = "fromNbt", at = @At("TAIL"))
private static void loadForcedVersion(NbtCompound root, CallbackInfoReturnable<ServerInfo> cir, @Local ServerInfo serverInfo) {
@Inject(method = "fromNbt", at = @At("TAIL"), locals = LocalCapture.CAPTURE_FAILHARD)
private static void loadForcedVersion(NbtCompound root, CallbackInfoReturnable<ServerInfo> cir, ServerInfo serverInfo) {
if (root.contains("viafabricplus_forcedversion")) {
final ProtocolVersion version = SettingsSave.protocolVersionByName(root.getString("viafabricplus_forcedversion"));
if (version != null) {
final VersionEnum version = VersionEnum.fromProtocolId(root.getInt("viafabricplus_forcedversion"));
if (VersionEnum.UNKNOWN.equals(version)) {
((IServerInfo) serverInfo).viaFabricPlus$forceVersion(null);
} else {
((IServerInfo) serverInfo).viaFabricPlus$forceVersion(version);
}
}
@ -71,32 +74,35 @@ public abstract class MixinServerInfo implements IServerInfo {
}
@Override
public ProtocolVersion viaFabricPlus$forcedVersion() {
public VersionEnum viaFabricPlus$forcedVersion() {
return viaFabricPlus$forcedVersion;
}
@Override
public void viaFabricPlus$forceVersion(ProtocolVersion version) {
public void viaFabricPlus$forceVersion(VersionEnum version) {
viaFabricPlus$forcedVersion = version;
}
@Override
public boolean viaFabricPlus$passedDirectConnectScreen() {
return viaFabricPlus$passedDirectConnectScreen;
final boolean previous = viaFabricPlus$passedDirectConnectScreen;
viaFabricPlus$passedDirectConnectScreen = false;
return previous;
}
@Override
public void viaFabricPlus$passDirectConnectScreen(boolean state) {
viaFabricPlus$passedDirectConnectScreen = state;
public void viaFabricPlus$passDirectConnectScreen() {
viaFabricPlus$passedDirectConnectScreen = true;
}
@Override
public ProtocolVersion viaFabricPlus$translatingVersion() {
public VersionEnum viaFabricPlus$translatingVersion() {
return viaFabricPlus$translatingVersion;
}
@Override
public void viaFabricPlus$setTranslatingVersion(ProtocolVersion version) {
public void viaFabricPlus$setTranslatingVersion(VersionEnum version) {
viaFabricPlus$translatingVersion = version;
}

View File

@ -20,8 +20,8 @@
package de.florianmichael.viafabricplus.injection.mixin.compat.classic4j;
import de.florianmichael.viafabricplus.injection.access.ITextFieldWidget;
import net.minecraft.SharedConstants;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.util.StringHelper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@ -37,18 +37,22 @@ public abstract class MixinTextFieldWidget implements ITextFieldWidget {
@Unique
private boolean viaFabricPlus$forbiddenCharactersUnlocked = false;
@Redirect(method = "charTyped", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/StringHelper;isValidChar(C)Z"))
@Redirect(method = "charTyped", at = @At(value = "INVOKE", target = "Lnet/minecraft/SharedConstants;isValidChar(C)Z"))
private boolean allowForbiddenCharacters(char c) {
return this.viaFabricPlus$forbiddenCharactersUnlocked || StringHelper.isValidChar(c);
if (this.viaFabricPlus$forbiddenCharactersUnlocked) {
return true;
}
return SharedConstants.isValidChar(c);
}
@Redirect(method = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/StringHelper;stripInvalidChars(Ljava/lang/String;)Ljava/lang/String;"))
@Redirect(method = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/SharedConstants;stripInvalidChars(Ljava/lang/String;)Ljava/lang/String;"))
private String allowForbiddenCharacters(String string) {
if (this.viaFabricPlus$forbiddenCharactersUnlocked) {
return string;
} else {
return StringHelper.stripInvalidChars(string);
}
return SharedConstants.stripInvalidChars(string);
}
@Override

View File

@ -1,59 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.compat.fabricapi;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.fixes.versioned.visual.FootStepParticle1_12_2;
import de.florianmichael.viafabricplus.settings.impl.DebugSettings;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.fabricmc.fabric.impl.registry.sync.RegistrySyncManager;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
@Mixin(RegistrySyncManager.class)
public abstract class MixinRegistrySyncManager {
@WrapOperation(method = "createAndPopulateRegistryMap", at = @At(value = "INVOKE", target = "Lnet/minecraft/registry/Registry;getId(Ljava/lang/Object;)Lnet/minecraft/util/Identifier;"), require = 0)
private static Identifier skipFootStepParticle(Registry instance, Object t, Operation<Identifier> original) {
final Identifier id = original.call(instance, t);
if (id == FootStepParticle1_12_2.ID) {
return null;
} else {
return id;
}
}
@Inject(method = "checkRemoteRemap", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;)V", ordinal = 0), cancellable = true, remap = false)
private static void ignoreFabricSyncErrors(Map<Identifier, Object2IntMap<Identifier>> map, CallbackInfo ci) {
if (DebugSettings.global().ignoreFabricSyncErrors.getValue()) {
ViaFabricPlus.global().getLogger().warn("Ignoring missing registries from Fabric API");
ci.cancel();
}
}
}

View File

@ -19,8 +19,8 @@
package de.florianmichael.viafabricplus.injection.mixin.compat.ipnext;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.Shadow;
@ -34,7 +34,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
*
* Fixes https://github.com/ViaVersion/ViaFabricPlus/issues/209
*/
@SuppressWarnings("UnresolvedMixinReference")
@Pseudo
@Mixin(targets = "org.anti_ad.mc.ipnext.event.AutoRefillHandler$ItemSlotMonitor", remap = false)
public abstract class MixinAutoRefillHandler_ItemSlotMonitor {
@ -44,14 +43,14 @@ public abstract class MixinAutoRefillHandler_ItemSlotMonitor {
@Inject(method = { "checkHandle", "checkShouldHandle" }, at = @At("HEAD"), cancellable = true)
public void dontHandleOffhandSlot(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
if (currentSlotId == 45) ci.cancel();
}
}
@Inject(method = "updateCurrent", at = @At(value = "FIELD", target = "Lorg/anti_ad/mc/ipnext/event/AutoRefillHandler$ItemSlotMonitor;currentSlotId:I", shift = At.Shift.AFTER), cancellable = true)
public void dontUpdateCurrentOffhandSlot(CallbackInfo ci) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_8)) {
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_8)) {
if (currentSlotId == 45) ci.cancel();
}
}

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.compat.minecraftauth;
package de.florianmichael.viafabricplus.injection.mixin.compat.jsonwebtoken;
import io.jsonwebtoken.lang.Classes;
import org.spongepowered.asm.mixin.Mixin;
@ -26,7 +26,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/*
* JsonWebToken is used by MinecraftAuth, and since it's using Java services, it's not working with the fabric loader,
* JsonWebToken is used by MinecraftAuth and since it's using Java services, it's not working with the fabric loader
* So we have to change all services usages by using the normal Java API
*/
@Mixin(value = Classes.class, remap = false)

View File

@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.compat.minecraftauth;
package de.florianmichael.viafabricplus.injection.mixin.compat.jsonwebtoken;
import io.jsonwebtoken.gson.io.GsonDeserializer;
import io.jsonwebtoken.impl.DefaultJwtParserBuilder;
@ -26,14 +26,14 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/*
* JsonWebToken is used by MinecraftAuth, and since it's using Java services, it's not working with the fabric loader,
* JsonWebToken is used by MinecraftAuth and since it's using Java services, it's not working with the fabric loader
* So we have to change all services usages by using the normal Java API
*/
@Mixin(value = DefaultJwtParserBuilder.class, remap = false)
public abstract class MixinDefaultJwtParserBuilder {
@Redirect(method = "build()Lio/jsonwebtoken/JwtParser;", at = @At(value = "INVOKE", target = "Lio/jsonwebtoken/impl/lang/Services;get(Ljava/lang/Class;)Ljava/lang/Object;"))
public Object removeServicesSupport(Class<?> spi) {
@Redirect(method = "build()Lio/jsonwebtoken/JwtParser;", at = @At(value = "INVOKE", target = "Lio/jsonwebtoken/impl/lang/Services;loadFirst(Ljava/lang/Class;)Ljava/lang/Object;"))
public Object removeServicesSupport(Class<Object> result) {
return new GsonDeserializer<>();
}

View File

@ -1,44 +0,0 @@
/*
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
* Copyright (C) 2021-2024 FlorianMichael/EnZaXD <florian.michael07@gmail.com> and RK_01/RaphiMC
* Copyright (C) 2023-2024 contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.florianmichael.viafabricplus.injection.mixin.compat.lithium;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
// Lithium is overriding the sorting with an optimized implementation
// https://github.com/CaffeineMC/lithium-fabric/blob/11892b8c0f0f14e81c3384510b0b2ac7293ca237/common/src/main/java/net/caffeinemc/mods/lithium/mixin/entity/collisions/movement/EntityMixin.java#L84
@Mixin(value = Entity.class, priority = 1001 /* Lithium has to be applied first */)
public abstract class MixinEntity {
@SuppressWarnings({"MixinAnnotationTarget", "UnresolvedMixinReference"})
@Redirect(method = "lithium$CollideMovement", at = @At(value = "INVOKE", target = "Ljava/lang/Math;abs(D)D", ordinal = 0), remap = false)
private static double alwaysSortYXZ(double a) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_13_2)) {
return Double.MAX_VALUE;
} else {
return Math.abs(a);
}
}
}

View File

@ -23,7 +23,7 @@ import com.mojang.authlib.minecraft.client.MinecraftClient;
import com.mojang.authlib.yggdrasil.YggdrasilUserApiService;
import com.mojang.authlib.yggdrasil.response.KeyPairResponse;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.fixes.versioned.KeyPairResponse1_19_0;
import de.florianmichael.viafabricplus.fixes.replacement.KeyPairResponse1_19_0;
import de.florianmichael.viafabricplus.injection.access.ILegacyKeySignatureStorage;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;

View File

@ -19,13 +19,12 @@
package de.florianmichael.viafabricplus.injection.mixin.fixes.minecraft;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.protocolhack.ProtocolHack;
import net.minecraft.client.network.Address;
import net.minecraft.client.network.AddressResolver;
import net.minecraft.client.network.AllowedAddressResolver;
import net.minecraft.client.network.ServerAddress;
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
import net.raphimc.vialoader.util.VersionEnum;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -44,7 +43,7 @@ public abstract class MixinAllowedAddressResolver {
@Inject(method = "resolve", at = @At("HEAD"), cancellable = true)
private void oldResolveBehaviour(ServerAddress address, CallbackInfoReturnable<Optional<Address>> cir) {
if (ProtocolTranslator.getTargetVersion().olderThanOrEqualTo(ProtocolVersion.v1_16_4) || ProtocolTranslator.getTargetVersion().equals(BedrockProtocolVersion.bedrockLatest)) {
if (ProtocolHack.getTargetVersion().isOlderThanOrEqualTo(VersionEnum.r1_16_4tor1_16_5) || ProtocolHack.getTargetVersion().equals(VersionEnum.bedrockLatest)) {
cir.setReturnValue(this.addressResolver.resolve(address));
}
}

Some files were not shown because too many files have changed in this diff Show More