Restructure item fix loading

Also fixes the loading behaviour of PostViaVersionLoadCallback to actually getting fired after Via is fully loaded. Adding VB back since VAF requires it (for now).
This commit is contained in:
FlorianMichael 2024-04-27 18:42:08 +02:00
parent 7fc46c4854
commit 712d8bbba7
9 changed files with 96 additions and 150 deletions

View File

@ -65,6 +65,7 @@ dependencies {
// 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}") {

View File

@ -15,6 +15,7 @@ archives_base_name=ViaFabricPlus
# ViaVersion Libraries
viaversion_version=4.10.0
viabackwards_version=4.10.0
vialegacy_version=2.2.22
viaaprilfools_version=2.0.11
vialoader_version=2.2.13

View File

@ -20,6 +20,7 @@
package de.florianmichael.viafabricplus;
import de.florianmichael.viafabricplus.event.PostGameLoadCallback;
import de.florianmichael.viafabricplus.event.PostViaVersionLoadCallback;
import de.florianmichael.viafabricplus.fixes.ClientsideFixes;
import de.florianmichael.viafabricplus.protocoltranslator.ProtocolTranslator;
import de.florianmichael.viafabricplus.save.SaveManager;
@ -78,6 +79,7 @@ public class ViaFabricPlus {
PostGameLoadCallback.EVENT.register(() -> {
loadingFuture.join();
saveManager.init();
PostViaVersionLoadCallback.EVENT.invoker().onPostViaVersionLoad();
});
}

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 IBlockItemPacketRewriter1_20_5 {
void onMappingDataLoaded();
}

View File

@ -40,20 +40,20 @@ import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.Protocol1_20_5
import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.rewriter.BlockItemPacketRewriter1_20_5;
import com.viaversion.viaversion.rewriter.ItemRewriter;
import de.florianmichael.viafabricplus.ViaFabricPlus;
import de.florianmichael.viafabricplus.injection.access.IBlockItemPacketRewriter1_20_5;
import de.florianmichael.viafabricplus.event.PostViaVersionLoadCallback;
import de.florianmichael.viafabricplus.protocoltranslator.impl.ViaFabricPlusMappingDataLoader;
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
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 java.util.*;
@Mixin(value = BlockItemPacketRewriter1_20_5.class, remap = false)
public abstract class MixinBlockItemPacketRewriter1_20_5 extends ItemRewriter<ClientboundPacket1_20_3, ServerboundPacket1_20_5, Protocol1_20_5To1_20_3> implements IBlockItemPacketRewriter1_20_5 {
public abstract class MixinBlockItemPacketRewriter1_20_5 extends ItemRewriter<ClientboundPacket1_20_3, ServerboundPacket1_20_5, Protocol1_20_5To1_20_3> {
@Unique
private final Set<String> foodItems_b1_7_3 = new HashSet<>();
@ -71,107 +71,95 @@ public abstract class MixinBlockItemPacketRewriter1_20_5 extends ItemRewriter<Cl
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType);
}
@Override
public void onMappingDataLoaded() {
this.foodItems_b1_7_3.add("minecraft:apple");
this.foodItems_b1_7_3.add("minecraft:mushroom_stew");
this.foodItems_b1_7_3.add("minecraft:bread");
this.foodItems_b1_7_3.add("minecraft:porkchop");
this.foodItems_b1_7_3.add("minecraft:cooked_porkchop");
this.foodItems_b1_7_3.add("minecraft:golden_apple");
this.foodItems_b1_7_3.add("minecraft:cod");
this.foodItems_b1_7_3.add("minecraft:cooked_cod");
this.foodItems_b1_7_3.add("minecraft:cookie");
@Inject(method = "<init>", at = @At("RETURN"))
public void loadItemMappings(Protocol1_20_5To1_20_3 protocol, CallbackInfo ci) {
// Technically it would be cleaner to split mapping loading into there respective protocols, but that will be impossible
// in a clean way, so let's just wait for Via* to load all protocols and then load everything in here.
PostViaVersionLoadCallback.EVENT.register(() -> {
this.foodItems_b1_7_3.add("minecraft:apple");
this.foodItems_b1_7_3.add("minecraft:mushroom_stew");
this.foodItems_b1_7_3.add("minecraft:bread");
this.foodItems_b1_7_3.add("minecraft:porkchop");
this.foodItems_b1_7_3.add("minecraft:cooked_porkchop");
this.foodItems_b1_7_3.add("minecraft:golden_apple");
this.foodItems_b1_7_3.add("minecraft:cod");
this.foodItems_b1_7_3.add("minecraft:cooked_cod");
this.foodItems_b1_7_3.add("minecraft:cookie");
this.armorMaxDamage_b1_8_1.put("minecraft:leather_helmet", 33);
this.armorMaxDamage_b1_8_1.put("minecraft:leather_chestplate", 48);
this.armorMaxDamage_b1_8_1.put("minecraft:leather_leggings", 45);
this.armorMaxDamage_b1_8_1.put("minecraft:leather_boots", 39);
this.armorMaxDamage_b1_8_1.put("minecraft:chainmail_helmet", 66);
this.armorMaxDamage_b1_8_1.put("minecraft:chainmail_chestplate", 96);
this.armorMaxDamage_b1_8_1.put("minecraft:chainmail_leggings", 90);
this.armorMaxDamage_b1_8_1.put("minecraft:chainmail_boots", 78);
this.armorMaxDamage_b1_8_1.put("minecraft:iron_helmet", 132);
this.armorMaxDamage_b1_8_1.put("minecraft:iron_chestplate", 192);
this.armorMaxDamage_b1_8_1.put("minecraft:iron_leggings", 180);
this.armorMaxDamage_b1_8_1.put("minecraft:iron_boots", 156);
this.armorMaxDamage_b1_8_1.put("minecraft:diamond_helmet", 264);
this.armorMaxDamage_b1_8_1.put("minecraft:diamond_chestplate", 384);
this.armorMaxDamage_b1_8_1.put("minecraft:diamond_leggings", 360);
this.armorMaxDamage_b1_8_1.put("minecraft:diamond_boots", 312);
this.armorMaxDamage_b1_8_1.put("minecraft:golden_helmet", 66);
this.armorMaxDamage_b1_8_1.put("minecraft:golden_chestplate", 96);
this.armorMaxDamage_b1_8_1.put("minecraft:golden_leggings", 90);
this.armorMaxDamage_b1_8_1.put("minecraft:golden_boots", 78);
final JsonObject armorMaxDamages = ViaFabricPlusMappingDataLoader.INSTANCE.loadData("armor-damages-b1.8.1.json");
for (Map.Entry<String, JsonElement> entry : armorMaxDamages.entrySet()) {
final String item = entry.getKey();
final int maxDamage = entry.getValue().getAsInt();
this.armorMaxDamage_b1_8_1.put(item, maxDamage);
}
this.swordItems1_8.add("minecraft:wooden_sword");
this.swordItems1_8.add("minecraft:stone_sword");
this.swordItems1_8.add("minecraft:iron_sword");
this.swordItems1_8.add("minecraft:golden_sword");
this.swordItems1_8.add("minecraft:diamond_sword");
this.swordItems1_8.add("minecraft:wooden_sword");
this.swordItems1_8.add("minecraft:stone_sword");
this.swordItems1_8.add("minecraft:iron_sword");
this.swordItems1_8.add("minecraft:golden_sword");
this.swordItems1_8.add("minecraft:diamond_sword");
final JsonObject itemToolComponents = ViaFabricPlusMappingDataLoader.INSTANCE.loadData("item-tool-components.json");
for (Map.Entry<String, JsonElement> entry : itemToolComponents.entrySet()) {
int attempts = 0;
while (ProtocolVersion.getClosest(entry.getKey()) == null) {
try {
Thread.sleep(100);
if (attempts++ > 100) { // 10 seconds
ViaFabricPlus.global().getLogger().warn("Failed to load item-tool-components.json after 10 seconds. Skipping entry.");
break;
final JsonObject itemToolComponents = ViaFabricPlusMappingDataLoader.INSTANCE.loadData("item-tool-components.json");
for (Map.Entry<String, JsonElement> entry : itemToolComponents.entrySet()) {
final ProtocolVersion version = ProtocolVersion.getClosest(entry.getKey());
if (version == null) {
throw new IllegalStateException("Unknown protocol version: " + entry.getKey());
}
final Map<String, ToolProperties> toolProperties = new HashMap<>();
final JsonArray toolComponents = entry.getValue().getAsJsonArray();
for (JsonElement toolComponent : toolComponents) {
final JsonObject toolComponentObject = toolComponent.getAsJsonObject();
final String item = toolComponentObject.get("item").getAsString();
final float defaultMiningSpeed = toolComponentObject.get("default_mining_speed").getAsFloat();
final int damagePerBlock = toolComponentObject.get("damage_per_block").getAsInt();
final int[] suitableFor = this.viaFabricPlus$blockJsonArrayToIds(version, toolComponentObject.getAsJsonArray("suitable_for"));
final List<ToolRule> toolRules = new ArrayList<>();
final JsonArray miningSpeeds = toolComponentObject.getAsJsonArray("mining_speeds");
for (JsonElement miningSpeed : miningSpeeds) {
final JsonObject miningSpeedObject = miningSpeed.getAsJsonObject();
final int[] blocks = this.viaFabricPlus$blockJsonArrayToIds(version, miningSpeedObject.getAsJsonArray("blocks"));
final float speed = miningSpeedObject.get("speed").getAsFloat();
toolRules.add(new ToolRule(HolderSet.of(blocks), speed, null));
}
} catch (InterruptedException e) {
break;
if (suitableFor.length > 0) {
toolRules.add(new ToolRule(HolderSet.of(suitableFor), null, true));
}
toolProperties.put(item, new ToolProperties(toolRules.toArray(new ToolRule[0]), defaultMiningSpeed, damagePerBlock));
}
this.toolDataChanges.put(version, toolProperties);
}
final ProtocolVersion version = ProtocolVersion.getClosest(entry.getKey());
if (version == null) { // Only happens if the timeout above is reached or the thread is interrupted
continue;
}
final Map<String, ToolProperties> toolProperties = new HashMap<>();
final JsonArray toolComponents = entry.getValue().getAsJsonArray();
for (JsonElement toolComponent : toolComponents) {
final JsonObject toolComponentObject = toolComponent.getAsJsonObject();
final String item = toolComponentObject.get("item").getAsString();
final float defaultMiningSpeed = toolComponentObject.get("default_mining_speed").getAsFloat();
final int damagePerBlock = toolComponentObject.get("damage_per_block").getAsInt();
final int[] suitableFor = this.blockJsonArrayToIds(version, toolComponentObject.getAsJsonArray("suitable_for"));
final List<ToolRule> toolRules = new ArrayList<>();
final JsonArray miningSpeeds = toolComponentObject.getAsJsonArray("mining_speeds");
for (JsonElement miningSpeed : miningSpeeds) {
final JsonObject miningSpeedObject = miningSpeed.getAsJsonObject();
final int[] blocks = this.blockJsonArrayToIds(version, miningSpeedObject.getAsJsonArray("blocks"));
final float speed = miningSpeedObject.get("speed").getAsFloat();
toolRules.add(new ToolRule(HolderSet.of(blocks), speed, null));
}
if (suitableFor.length > 0) {
toolRules.add(new ToolRule(HolderSet.of(suitableFor), null, true));
}
toolProperties.put(item, new ToolProperties(toolRules.toArray(new ToolRule[0]), defaultMiningSpeed, damagePerBlock));
}
this.toolDataChanges.put(version, toolProperties);
}
});
}
// Older servers don't have these components, so we can use them to emulate old item behaviour without the need
// of modifying tons of code in the game.
@Inject(method = "toStructuredItem", at = @At("RETURN"))
private void appendItemDataFixComponents(UserConnection connection, Item old, CallbackInfoReturnable<Item> cir) {
final StructuredDataContainer data = cir.getReturnValue().structuredData();
final String identifier = this.protocol.getMappingData().getFullItemMappings().identifier(cir.getReturnValue().identifier());
// Fix damage bar being displayed wrong
if (connection.getProtocolInfo().serverProtocolVersion().olderThanOrEqualTo(ProtocolVersion.v1_17_1)) {
if (identifier.equals("minecraft:crossbow")) {
data.set(StructuredDataKey.MAX_DAMAGE, 326);
}
}
// Add item blocking by make the sword eatable, counterpart in MixinSwordItem
if (connection.getProtocolInfo().serverProtocolVersion().betweenInclusive(LegacyProtocolVersion.b1_8tob1_8_1, ProtocolVersion.v1_8)) {
if (this.swordItems1_8.contains(identifier)) {
data.set(StructuredDataKey.FOOD, new FoodProperties(0, 0F, true, 3600, new FoodEffect[0]));
}
}
// Fix durability tooltip displaying wrong
if (connection.getProtocolInfo().serverProtocolVersion().olderThanOrEqualTo(LegacyProtocolVersion.b1_8tob1_8_1)) {
if (this.armorMaxDamage_b1_8_1.containsKey(identifier)) {
data.set(StructuredDataKey.MAX_DAMAGE, this.armorMaxDamage_b1_8_1.get(identifier));
}
}
// Fix item desyncs
if (connection.getProtocolInfo().serverProtocolVersion().olderThanOrEqualTo(LegacyProtocolVersion.b1_7tob1_7_3)) {
if (this.foodItems_b1_7_3.contains(identifier)) {
data.set(StructuredDataKey.MAX_STACK_SIZE, 1);
@ -179,6 +167,7 @@ public abstract class MixinBlockItemPacketRewriter1_20_5 extends ItemRewriter<Cl
}
}
// Tool data changes include mining speeds as well as suitable blocks and damage values
for (Map.Entry<ProtocolVersion, Map<String, ToolProperties>> entry : this.toolDataChanges.entrySet()) {
if (connection.getProtocolInfo().serverProtocolVersion().olderThanOrEqualTo(entry.getKey())) {
final ToolProperties toolProperties = entry.getValue().get(identifier);
@ -191,7 +180,8 @@ public abstract class MixinBlockItemPacketRewriter1_20_5 extends ItemRewriter<Cl
}
@Unique
private int[] blockJsonArrayToIds(final ProtocolVersion protocolVersion, final JsonArray jsonArray) {
// Converts block identifiers as well as materials (prefixed with #) to block ids
private int[] viaFabricPlus$blockJsonArrayToIds(final ProtocolVersion protocolVersion, final JsonArray jsonArray) {
final IntSet ids = new IntOpenHashSet();
for (final JsonElement element : jsonArray) {
final String name = element.getAsString();

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.fixes.viaversion;
import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.Protocol1_20_5To1_20_3;
import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.rewriter.BlockItemPacketRewriter1_20_5;
import de.florianmichael.viafabricplus.injection.access.IBlockItemPacketRewriter1_20_5;
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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(value = Protocol1_20_5To1_20_3.class, remap = false)
public abstract class MixinProtocol1_20_5To1_20_3 {
@Shadow
@Final
private BlockItemPacketRewriter1_20_5 itemRewriter;
@Inject(method = "onMappingDataLoaded", at = @At("RETURN"))
private void callOnMappingDataLoaded(CallbackInfo ci) {
((IBlockItemPacketRewriter1_20_5) (Object) this.itemRewriter).onMappingDataLoaded();
}
}

View File

@ -55,6 +55,7 @@ import net.raphimc.viabedrock.api.BedrockProtocolVersion;
import net.raphimc.viabedrock.protocol.data.ProtocolConstants;
import net.raphimc.vialoader.ViaLoader;
import net.raphimc.vialoader.impl.platform.ViaAprilFoolsPlatformImpl;
import net.raphimc.vialoader.impl.platform.ViaBackwardsPlatformImpl;
import net.raphimc.vialoader.impl.platform.ViaBedrockPlatformImpl;
import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption;
@ -315,13 +316,13 @@ public class ProtocolTranslator {
new ViaFabricPlusVLInjector(),
new ViaFabricPlusVLCommandHandler(),
ViaBackwardsPlatformImpl::new,
ViaFabricPlusViaLegacyPlatformImpl::new,
ViaAprilFoolsPlatformImpl::new,
ViaBedrockPlatformImpl::new
);
Protocol1_20_5To1_20_3.strictErrorHandling = false;
ProtocolVersion.register(AUTO_DETECT_PROTOCOL);
PostViaVersionLoadCallback.EVENT.invoker().onPostViaVersionLoad();
});
}

View File

@ -0,0 +1,22 @@
{
"minecraft:leather_helmet": 33,
"minecraft:leather_chestplate": 48,
"minecraft:leather_leggings": 45,
"minecraft:leather_boots": 39,
"minecraft:chainmail_helmet": 66,
"minecraft:chainmail_chestplate": 96,
"minecraft:chainmail_leggings": 90,
"minecraft:chainmail_boots": 78,
"minecraft:iron_helmet": 132,
"minecraft:iron_chestplate": 192,
"minecraft:iron_leggings": 180,
"minecraft:iron_boots": 156,
"minecraft:diamond_helmet": 264,
"minecraft:diamond_chestplate": 384,
"minecraft:diamond_leggings": 360,
"minecraft:diamond_boots": 312,
"minecraft:golden_helmet": 66,
"minecraft:golden_chestplate": 96,
"minecraft:golden_leggings": 90,
"minecraft:golden_boots": 78
}

View File

@ -184,7 +184,6 @@
"fixes.viaversion.MixinProtocol1_11To1_10",
"fixes.viaversion.MixinProtocol1_12To1_11_1",
"fixes.viaversion.MixinProtocol1_20_2To1_20",
"fixes.viaversion.MixinProtocol1_20_5To1_20_3",
"fixes.viaversion.MixinTagType",
"fixes.viaversion.MixinUserConnectionImpl",
"fixes.viaversion.MixinWorldPackets1_16_2",