mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Take width of hanging signs into account
This commit is contained in:
parent
b9c568733a
commit
df5092d32f
5 changed files with 80 additions and 12 deletions
|
@ -45,6 +45,7 @@ import java.util.Locale;
|
||||||
*/
|
*/
|
||||||
public final class BlockStateValues {
|
public final class BlockStateValues {
|
||||||
private static final IntSet ALL_CAULDRONS = new IntOpenHashSet();
|
private static final IntSet ALL_CAULDRONS = new IntOpenHashSet();
|
||||||
|
private static final IntSet HANGING_SIGNS = new IntOpenHashSet();
|
||||||
private static final Int2IntMap BANNER_COLORS = new FixedInt2IntMap();
|
private static final Int2IntMap BANNER_COLORS = new FixedInt2IntMap();
|
||||||
private static final Int2ByteMap BED_COLORS = new FixedInt2ByteMap();
|
private static final Int2ByteMap BED_COLORS = new FixedInt2ByteMap();
|
||||||
private static final Int2ByteMap COMMAND_BLOCK_VALUES = new Int2ByteOpenHashMap();
|
private static final Int2ByteMap COMMAND_BLOCK_VALUES = new Int2ByteOpenHashMap();
|
||||||
|
@ -86,6 +87,12 @@ public final class BlockStateValues {
|
||||||
* @param blockData JsonNode of info about the block from blocks.json
|
* @param blockData JsonNode of info about the block from blocks.json
|
||||||
*/
|
*/
|
||||||
public static void storeBlockStateValues(String javaId, int javaBlockState, JsonNode blockData) {
|
public static void storeBlockStateValues(String javaId, int javaBlockState, JsonNode blockData) {
|
||||||
|
if (javaId.contains("_hanging_sign")) {
|
||||||
|
// covers hanging_sign and wall_hanging_sign
|
||||||
|
HANGING_SIGNS.add(javaBlockState);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
JsonNode bannerColor = blockData.get("banner_color");
|
JsonNode bannerColor = blockData.get("banner_color");
|
||||||
if (bannerColor != null) {
|
if (bannerColor != null) {
|
||||||
BANNER_COLORS.put(javaBlockState, (byte) bannerColor.intValue());
|
BANNER_COLORS.put(javaBlockState, (byte) bannerColor.intValue());
|
||||||
|
@ -203,6 +210,17 @@ public final class BlockStateValues {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hanging signs have a different maximum text width than "normal" signs. As a result, when the client
|
||||||
|
* updates the text of a sign without indication of the sign type, we must determine it.
|
||||||
|
*
|
||||||
|
* @param state BlockState of the block
|
||||||
|
* @return true if the sign is any hanging variant
|
||||||
|
*/
|
||||||
|
public static boolean isHangingSign(int state) {
|
||||||
|
return HANGING_SIGNS.contains(state);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Banner colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
|
* Banner colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock.
|
||||||
* This gives an integer color that Bedrock can use.
|
* This gives an integer color that Bedrock can use.
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.geyser.translator.level.block.entity;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
|
||||||
|
import org.geysermc.geyser.util.SignUtils;
|
||||||
|
|
||||||
|
@BlockEntity(type = BlockEntityType.HANGING_SIGN)
|
||||||
|
public class HangingSignBlockEntityTranslator extends SignBlockEntityTranslator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int signWidthMax() {
|
||||||
|
return SignUtils.HANGING_SIGN_WIDTH_MAX; // Smaller than that for BlockEntityType.SIGN
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,7 +35,7 @@ import org.geysermc.geyser.text.ChatColor;
|
||||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||||
import org.geysermc.geyser.util.SignUtils;
|
import org.geysermc.geyser.util.SignUtils;
|
||||||
|
|
||||||
@BlockEntity(type = {BlockEntityType.SIGN, BlockEntityType.HANGING_SIGN})
|
@BlockEntity(type = BlockEntityType.SIGN)
|
||||||
public class SignBlockEntityTranslator extends BlockEntityTranslator {
|
public class SignBlockEntityTranslator extends BlockEntityTranslator {
|
||||||
/**
|
/**
|
||||||
* Maps a color stored in a sign's Color tag to its ARGB value.
|
* Maps a color stored in a sign's Color tag to its ARGB value.
|
||||||
|
@ -67,6 +67,10 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator {
|
||||||
return dyeColor | (255 << 24);
|
return dyeColor | (255 << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int signWidthMax() {
|
||||||
|
return SignUtils.SIGN_WIDTH_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
|
public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
|
||||||
builder.putCompound("FrontText", translateSide(tag.get("front_text")));
|
builder.putCompound("FrontText", translateSide(tag.get("front_text")));
|
||||||
|
@ -105,8 +109,7 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator {
|
||||||
signWidth += SignUtils.getCharacterWidth(c);
|
signWidth += SignUtils.getCharacterWidth(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo 1.20: update for hanging signs (smaller width). Currently OK because bedrock sees hanging signs as normal signs
|
if (signWidth <= signWidthMax()) {
|
||||||
if (signWidth <= SignUtils.BEDROCK_CHARACTER_WIDTH_MAX) {
|
|
||||||
finalSignLine.append(c);
|
finalSignLine.append(c);
|
||||||
} else {
|
} else {
|
||||||
// Adding the character would make Bedrock move to the next line - Java doesn't do that, so we do not want to
|
// Adding the character would make Bedrock move to the next line - Java doesn't do that, so we do not want to
|
||||||
|
|
|
@ -44,6 +44,9 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator<BlockEnti
|
||||||
NbtMap tag = packet.getData();
|
NbtMap tag = packet.getData();
|
||||||
String id = tag.getString("id");
|
String id = tag.getString("id");
|
||||||
if (id.equals("Sign")) {
|
if (id.equals("Sign")) {
|
||||||
|
// Hanging signs are narrower
|
||||||
|
int widthMax = SignUtils.getSignWidthMax(session.getGeyser().getWorldManager().getBlockAt(session, packet.getBlockPosition()));
|
||||||
|
|
||||||
String text = MessageTranslator.convertToPlainText(
|
String text = MessageTranslator.convertToPlainText(
|
||||||
tag.getCompound(session.getWorldCache().isEditingSignOnFront() ? "FrontText" : "BackText").getString("Text"));
|
tag.getCompound(session.getWorldCache().isEditingSignOnFront() ? "FrontText" : "BackText").getString("Text"));
|
||||||
// Note: as of 1.18.30, only one packet is sent from Bedrock when the sign is finished.
|
// Note: as of 1.18.30, only one packet is sent from Bedrock when the sign is finished.
|
||||||
|
@ -60,13 +63,10 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator<BlockEnti
|
||||||
for (char character : text.toCharArray()) {
|
for (char character : text.toCharArray()) {
|
||||||
widthCount += SignUtils.getCharacterWidth(character);
|
widthCount += SignUtils.getCharacterWidth(character);
|
||||||
|
|
||||||
// todo 1.20: update for hanging signs (smaller width). Currently bedrock thinks hanging signs are normal,
|
|
||||||
// so it thinks hanging signs have more width than they actually do. Seems like JE just truncates it.
|
|
||||||
|
|
||||||
// If we get a return in Bedrock, or go over the character width max, that signals to use the next line.
|
// If we get a return in Bedrock, or go over the character width max, that signals to use the next line.
|
||||||
if (character == '\n' || widthCount > SignUtils.JAVA_CHARACTER_WIDTH_MAX) {
|
if (character == '\n' || widthCount > widthMax) {
|
||||||
// We need to apply some more logic if we went over the character width max
|
// We need to apply some more logic if we went over the character width max
|
||||||
boolean wentOverMax = widthCount > SignUtils.JAVA_CHARACTER_WIDTH_MAX && character != '\n';
|
boolean wentOverMax = widthCount > widthMax && character != '\n';
|
||||||
widthCount = 0;
|
widthCount = 0;
|
||||||
// Saves if we're moving a word to the next line
|
// Saves if we're moving a word to the next line
|
||||||
String word = null;
|
String word = null;
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
package org.geysermc.geyser.util;
|
package org.geysermc.geyser.util;
|
||||||
|
|
||||||
|
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides utilities for interacting with signs. Mainly, it deals with the widths of each character.
|
* Provides utilities for interacting with signs. Mainly, it deals with the widths of each character.
|
||||||
* Since Bedrock auto-wraps signs and Java does not, we have to take this into account when translating signs.
|
* Since Bedrock auto-wraps signs and Java does not, we have to take this into account when translating signs.
|
||||||
|
@ -33,14 +35,15 @@ public class SignUtils {
|
||||||
|
|
||||||
// TODO: If we send the Java font via resource pack, does width change?
|
// TODO: If we send the Java font via resource pack, does width change?
|
||||||
/**
|
/**
|
||||||
* The maximum character width that a sign can hold in Bedrock
|
* The maximum character width that a non-hanging sign can hold in both Java and Bedrock
|
||||||
*/
|
*/
|
||||||
public static final int BEDROCK_CHARACTER_WIDTH_MAX = 88;
|
public static final int SIGN_WIDTH_MAX = 90;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum character width that a sign can hold in Java
|
* The maximum character width that a hanging sign can hold in both Java and Bedrock. Hanging signs are narrower.
|
||||||
*/
|
*/
|
||||||
public static final int JAVA_CHARACTER_WIDTH_MAX = 90;
|
public static final int HANGING_SIGN_WIDTH_MAX = 60;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Minecraft width of a character
|
* Gets the Minecraft width of a character
|
||||||
|
@ -58,4 +61,10 @@ public class SignUtils {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getSignWidthMax(int javaBlockState) {
|
||||||
|
if (BlockStateValues.isHangingSign(javaBlockState)) {
|
||||||
|
return HANGING_SIGN_WIDTH_MAX;
|
||||||
|
}
|
||||||
|
return SIGN_WIDTH_MAX;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue