Skip to content
This repository has been archived by the owner on Apr 20, 2023. It is now read-only.

Commit

Permalink
Make the width of the version dropdown dynamic and fix doesServerKnow (
Browse files Browse the repository at this point in the history
…#518)

* Make the width of the version dropdown dynamic

* Fix doesServerKnow

* Fix items not getting added back to the creative inventory

Also applies to items not getting removed if you joined a newer server
first.

* Handle blocks older than 1.12.2 properly as well

* Suppress conversion warnings

---------

Co-authored-by: Joseph Burton <[email protected]>
  • Loading branch information
Gaming32 and Earthcomputer authored Feb 23, 2023
1 parent be7871c commit d6cfe94
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 56 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
package net.earthcomputer.multiconnect.impl;

import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import com.mojang.blaze3d.vertex.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.AbstractButton;
Expand All @@ -19,6 +11,11 @@
import net.minecraft.network.chat.Component;
import net.minecraft.util.Mth;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

public class DropDownWidget<T> extends AbstractButton {

private static final int DROP_DOWN_ELEMENT_HEIGHT = 20;
Expand Down Expand Up @@ -47,6 +44,14 @@ public DropDownWidget(int x, int y, int width, int height, T initialValue, Funct
this.value = initialValue;
}

public Function<T, Component> getLabelExtractor() {
return labelExtractor;
}

public Function<T, Component> getCategoryLabelExtractor() {
return categoryLabelExtractor;
}

public DropDownWidget<T> setCategoryLabelExtractor(Function<T, Component> categoryLabelExtractor) {
this.categoryLabelExtractor = categoryLabelExtractor;
return this;
Expand Down
19 changes: 17 additions & 2 deletions src/main/java/net/earthcomputer/multiconnect/impl/Utils.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
package net.earthcomputer.multiconnect.impl;

import com.google.common.cache.Cache;
import net.earthcomputer.multiconnect.api.ThreadSafe;
import net.earthcomputer.multiconnect.api.IProtocol;
import net.earthcomputer.multiconnect.api.ThreadSafe;
import net.earthcomputer.multiconnect.connect.ConnectionMode;
import net.earthcomputer.multiconnect.protocols.ProtocolRegistry;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;

import java.lang.ref.Cleaner;
import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.util.*;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
Expand Down Expand Up @@ -65,6 +70,7 @@ public static DropDownWidget<IProtocol> createVersionDropdown(Screen screen, IPr
for (IProtocol protocol : ProtocolRegistry.getProtocols()) {
populateDropdown(versionDropDown, protocol);
}
versionDropDown.setX(screen.width - 5 - versionDropDown.getWidth());

return versionDropDown;
}
Expand All @@ -80,15 +86,24 @@ private static MutableComponent getMajorReleaseNameText(IProtocolExt protocol) {
private static void populateDropdown(DropDownWidget<IProtocol> versionDropDown, IProtocol protocol) {
if (protocol.isMajorRelease()) {
var category = versionDropDown.add(protocol);
var maxWidth = getWidth(versionDropDown, protocol);
List<IProtocol> children = protocol.getMinorReleases();
if (children.size() > 1) {
for (IProtocol child : children) {
category.add(child);
maxWidth = Math.max(maxWidth, getWidth(versionDropDown, child));
}
}
if (maxWidth + 30 > versionDropDown.getWidth()) {
versionDropDown.setWidth(maxWidth + 30);
}
}
}

private static int getWidth(DropDownWidget<IProtocol> versionDropDown, IProtocol protocol) {
return Minecraft.getInstance().font.width(versionDropDown.getCategoryLabelExtractor().apply(protocol));
}

@ThreadSafe
public static void leftShift(BitSet bitSet, int n) {
if (n < 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package net.earthcomputer.multiconnect.mixin.bridge;

import net.earthcomputer.multiconnect.impl.ConnectionInfo;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.item.CreativeModeTabs;
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.CallbackInfoReturnable;

@Mixin(CreativeModeTabs.class)
public class CreativeModeTabsMixin {
private static int protocolValue = Integer.MIN_VALUE;

@Inject(method = "wouldRebuildSameContents", at = @At("HEAD"), cancellable = true)
private static void alsoCheckProtocolVersion(FeatureFlagSet featureFlagSet, boolean bl, CallbackInfoReturnable<Boolean> cir) {
if (protocolValue != ConnectionInfo.protocolVersion) {
protocolValue = ConnectionInfo.protocolVersion;
cir.setReturnValue(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import com.mojang.blaze3d.vertex.PoseStack;
import net.earthcomputer.multiconnect.api.IProtocol;
import net.earthcomputer.multiconnect.connect.ConnectionMode;
import net.earthcomputer.multiconnect.impl.DropDownWidget;
import net.earthcomputer.multiconnect.connect.ServersExt;
import net.earthcomputer.multiconnect.impl.DropDownWidget;
import net.earthcomputer.multiconnect.impl.IProtocolExt;
import net.earthcomputer.multiconnect.impl.Utils;
import net.minecraft.client.gui.components.EditBox;
Expand Down Expand Up @@ -52,7 +52,7 @@ private void onTick(CallbackInfo ci) {

@Inject(method = "render", at = @At("RETURN"))
private void drawScreen(PoseStack matrixStack, int mouseX, int mouseY, float delta, CallbackInfo ci) {
font.drawShadow(matrixStack, multiconnect_forceProtocolLabel, width - 85 - font.width(multiconnect_forceProtocolLabel), 11, 0xFFFFFF);
font.drawShadow(matrixStack, multiconnect_forceProtocolLabel, width - multiconnect_protocolSelector.getWidth() - 10 - font.width(multiconnect_forceProtocolLabel), 11, 0xFFFFFF);
multiconnect_protocolSelector.render(matrixStack, mouseX, mouseY, delta);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import com.google.common.collect.ImmutableSet;
import com.mojang.blaze3d.vertex.PoseStack;
import net.earthcomputer.multiconnect.api.IProtocol;
import net.earthcomputer.multiconnect.impl.DropDownWidget;
import net.earthcomputer.multiconnect.connect.ServersExt;
import net.earthcomputer.multiconnect.impl.DropDownWidget;
import net.earthcomputer.multiconnect.impl.Utils;
import net.earthcomputer.multiconnect.protocols.ProtocolRegistry;
import net.minecraft.client.Minecraft;
Expand Down Expand Up @@ -69,7 +69,7 @@ private void addButtons(CallbackInfo ci) {
@Inject(method = "render", at = @At("RETURN"))
private void onRender(PoseStack matrixStack, int mouseX, int mouseY, float delta, CallbackInfo ci) {
if (multiconnect_isProtocolReason) {
font.drawShadow(matrixStack, multiconnect_forceProtocolLabel, width - 85 - font.width(multiconnect_forceProtocolLabel), 11, 0xFFFFFF);
font.drawShadow(matrixStack, multiconnect_forceProtocolLabel, width - multiconnect_protocolSelector.getWidth() - 10 - font.width(multiconnect_forceProtocolLabel), 11, 0xFFFFFF);
multiconnect_protocolSelector.render(matrixStack, mouseX, mouseY, delta);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import com.mojang.blaze3d.vertex.PoseStack;
import net.earthcomputer.multiconnect.api.IProtocol;
import net.earthcomputer.multiconnect.impl.DropDownWidget;
import net.earthcomputer.multiconnect.connect.ServersExt;
import net.earthcomputer.multiconnect.impl.DropDownWidget;
import net.earthcomputer.multiconnect.impl.Utils;
import net.minecraft.client.gui.screens.EditServerScreen;
import net.minecraft.client.gui.screens.Screen;
Expand Down Expand Up @@ -39,7 +39,7 @@ private void createButtons(CallbackInfo ci) {

@Inject(method = "render", at = @At("RETURN"))
private void drawScreen(PoseStack stack, int mouseX, int mouseY, float delta, CallbackInfo ci) {
font.drawShadow(stack, multiconnect_forceProtocolLabel, width - 85 - font.width(multiconnect_forceProtocolLabel), 11, 0xFFFFFF);
font.drawShadow(stack, multiconnect_forceProtocolLabel, width - multiconnect_protocolSelector.getWidth() - 10 - font.width(multiconnect_forceProtocolLabel), 11, 0xFFFFFF);
multiconnect_protocolSelector.render(stack, mouseX, mouseY, delta);
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/assets/multiconnect/via_config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# this is a comment

serverside-blockconnections: true
serverside-blockconnections: true
suppress-conversion-warnings: true
1 change: 1 addition & 0 deletions src/main/resources/multiconnect.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"bridge.Connection1Mixin",
"bridge.ConnectionMixin",
"bridge.CreativeModeTabItemDisplayBuilderMixin",
"bridge.CreativeModeTabsMixin",
"bridge.MinecraftAccessor",
"bridge.MinecraftMixin",
"bridge.ParticleEngineMixin",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.Mappings;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.connection.UserConnectionImpl;
Expand All @@ -18,6 +20,8 @@
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import net.earthcomputer.multiconnect.api.IMulticonnectTranslator;
import net.earthcomputer.multiconnect.api.IMulticonnectTranslatorApi;
import net.minecraft.client.Minecraft;
Expand All @@ -28,8 +32,6 @@
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;

import java.util.BitSet;

public class ViaMulticonnectTranslator implements IMulticonnectTranslator {
private static final Logger LOGGER = LogUtils.getLogger();
private static final AttributeKey<UserConnection> VIA_USER_CONNECTION_KEY = AttributeKey.valueOf("multiconnect.via_user_connection");
Expand Down Expand Up @@ -92,42 +94,43 @@ public void postPipelineModifiers(Channel channel) {
}
}

private static BitSet invertMappings(Mappings mappings) {
BitSet result = new BitSet(mappings.mappedSize());
private static Int2IntMap invertMappings(Mappings mappings) {
Int2IntMap result = new Int2IntOpenHashMap(mappings.mappedSize());
for (int oldId = 0; oldId < mappings.size(); oldId++) {
int newId = mappings.getNewId(oldId);
if (newId != -1) {
result.set(newId);
result.put(newId, oldId);
}
}
return result;
}

private static BitSet getInverseMappings(Channel channel, AttributeKey<BitSet> key, Mappings mappings) {
private static Int2IntMap getInverseMappings(Channel channel, AttributeKey<Int2IntMap> key, Mappings mappings) {
if (mappings == null) {
return null;
}

BitSet result = channel.attr(key).get();
Int2IntMap result = channel.attr(key).get();
if (result == null) {
channel.attr(key).set(result = invertMappings(mappings));
}
return result;
}

private static final AttributeKey<BitSet> INV_BLOCK_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invBlockMappings");
private static final AttributeKey<BitSet> INV_ENTITY_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invEntityMappings");
private static final AttributeKey<BitSet> INV_ENCHANTMENT_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invEnchantmentMappings");
private static final AttributeKey<BitSet> INV_ARGUMENT_TYPE_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invArgumentTypeMappings");
private static final AttributeKey<BitSet> INV_BLOCK_ENTITY_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invBlockEntityMappings");
private static final AttributeKey<BitSet> INV_PAINTING_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invPaintingMappings");
private static final AttributeKey<BitSet> INV_PARTICLE_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invParticleMappings");
private static final AttributeKey<BitSet> INV_SOUND_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invSoundMappings");
private static final AttributeKey<BitSet> INV_STATISTICS_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invStatisticsMappings");
private static final AttributeKey<Int2IntMap> INV_BLOCK_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invBlockMappings");
private static final AttributeKey<Int2IntMap> INV_ENTITY_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invEntityMappings");
private static final AttributeKey<Int2IntMap> INV_ENCHANTMENT_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invEnchantmentMappings");
private static final AttributeKey<Int2IntMap> INV_ARGUMENT_TYPE_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invArgumentTypeMappings");
private static final AttributeKey<Int2IntMap> INV_BLOCK_ENTITY_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invBlockEntityMappings");
private static final AttributeKey<Int2IntMap> INV_PAINTING_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invPaintingMappings");
private static final AttributeKey<Int2IntMap> INV_PARTICLE_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invParticleMappings");
private static final AttributeKey<Int2IntMap> INV_SOUND_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invSoundMappings");
private static final AttributeKey<Int2IntMap> INV_STATISTICS_MAPPINGS_KEY = AttributeKey.valueOf("multiconnect.invStatisticsMappings");

@Override
public boolean doesServerKnow(String registry, String entry) {
int id = getRegistryId(registry, entry);
if (registry.equals("minecraft:item") && id == 1) return true; // Stone *always* exists

Channel channel = api.getCurrentChannel();
if (channel == null) {
Expand All @@ -137,36 +140,50 @@ public boolean doesServerKnow(String registry, String entry) {
if (connection == null) {
return true;
}
MappingData mappingData = connection.getProtocolInfo().getPipeline().getMappingData();
if (mappingData == null) {
return true;
}
for (final var protocol : connection.getProtocolInfo().getPipeline().pipes()) {
if (registry.equals("minecraft:item")) {
final var itemRewriter = protocol.getItemRewriter();
if (itemRewriter != null) {
final Item newItem = itemRewriter.handleItemToServer(new DataItem(id, (byte)1, (short)0, null));
if (newItem != null) {
id = newItem.identifier();
if (id == 1) return false;
continue;
}
}
}

return switch (registry) {
case "minecraft:block" -> doesServerKnow(channel, INV_BLOCK_MAPPINGS_KEY, mappingData.getBlockMappings(), id);
case "minecraft:item" -> mappingData.getOldItemId(id) != -1;
case "minecraft:entity_type" -> doesServerKnow(channel, INV_ENTITY_MAPPINGS_KEY, mappingData.getEntityMappings(), id);
case "minecraft:enchantment" -> doesServerKnow(channel, INV_ENCHANTMENT_MAPPINGS_KEY, mappingData.getEnchantmentMappings(), id);
case "minecraft:command_argument_type" -> doesServerKnow(channel, INV_ARGUMENT_TYPE_MAPPINGS_KEY, mappingData.getArgumentTypeMappings(), id);
case "minecraft:block_entity_type" -> doesServerKnow(channel, INV_BLOCK_ENTITY_MAPPINGS_KEY, mappingData.getBlockEntityMappings(), id);
case "minecraft:painting_variant" -> doesServerKnow(channel, INV_PAINTING_MAPPINGS_KEY, mappingData.getPaintingMappings(), id);
case "minecraft:particle_type" -> doesServerKnow(channel, INV_PARTICLE_MAPPINGS_KEY, mappingData.getParticleMappings(), id);
case "minecraft:sound_event" -> doesServerKnow(channel, INV_SOUND_MAPPINGS_KEY, mappingData.getSoundMappings(), id);
case "minecraft:custom_stat" -> doesServerKnow(channel, INV_STATISTICS_MAPPINGS_KEY, mappingData.getStatisticsMappings(), id);
default -> true;
};
MappingData mappingData = protocol.getMappingData();
if (mappingData == null) continue;

id = switch (registry) {
case "minecraft:block" -> getOldId(channel, INV_BLOCK_MAPPINGS_KEY, mappingData.getBlockMappings(), id);
case "minecraft:item" -> mappingData.getOldItemId(id);
case "minecraft:entity_type" -> getOldId(channel, INV_ENTITY_MAPPINGS_KEY, mappingData.getEntityMappings(), id);
case "minecraft:enchantment" -> getOldId(channel, INV_ENCHANTMENT_MAPPINGS_KEY, mappingData.getEnchantmentMappings(), id);
case "minecraft:command_argument_type" -> getOldId(channel, INV_ARGUMENT_TYPE_MAPPINGS_KEY, mappingData.getArgumentTypeMappings(), id);
case "minecraft:block_entity_type" -> getOldId(channel, INV_BLOCK_ENTITY_MAPPINGS_KEY, mappingData.getBlockEntityMappings(), id);
case "minecraft:painting_variant" -> getOldId(channel, INV_PAINTING_MAPPINGS_KEY, mappingData.getPaintingMappings(), id);
case "minecraft:particle_type" -> getOldId(channel, INV_PARTICLE_MAPPINGS_KEY, mappingData.getParticleMappings(), id);
case "minecraft:sound_event" -> getOldId(channel, INV_SOUND_MAPPINGS_KEY, mappingData.getSoundMappings(), id);
case "minecraft:custom_stat" -> getOldId(channel, INV_STATISTICS_MAPPINGS_KEY, mappingData.getStatisticsMappings(), id);
default -> id;
};
if (id == -1 || (registry.equals("minecraft:item") && id == 1)) return false;
}
return true;
}

private static boolean doesServerKnow(Channel channel, AttributeKey<BitSet> key, @Nullable FullMappings mappings, int id) {
private static int getOldId(Channel channel, AttributeKey<Int2IntMap> key, @Nullable FullMappings mappings, int id) {
if (mappings == null) {
return true;
return id;
}
return doesServerKnow(channel, key, mappings.mappings(), id);
return getOldId(channel, key, mappings.mappings(), id);
}

private static boolean doesServerKnow(Channel channel, AttributeKey<BitSet> key, @Nullable Mappings mappings, int id) {
private static int getOldId(Channel channel, AttributeKey<Int2IntMap> key, @Nullable Mappings mappings, int id) {
if (mappings == null) {
return true;
return id;
}
return getInverseMappings(channel, key, mappings).get(id);
}
Expand Down

0 comments on commit d6cfe94

Please sign in to comment.