mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-23 15:00:37 +01: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 {
|
||||
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 Int2ByteMap BED_COLORS = new FixedInt2ByteMap();
|
||||
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
|
||||
*/
|
||||
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");
|
||||
if (bannerColor != null) {
|
||||
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.
|
||||
* 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.util.SignUtils;
|
||||
|
||||
@BlockEntity(type = {BlockEntityType.SIGN, BlockEntityType.HANGING_SIGN})
|
||||
@BlockEntity(type = BlockEntityType.SIGN)
|
||||
public class SignBlockEntityTranslator extends BlockEntityTranslator {
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
public int signWidthMax() {
|
||||
return SignUtils.SIGN_WIDTH_MAX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
|
||||
builder.putCompound("FrontText", translateSide(tag.get("front_text")));
|
||||
|
@ -105,8 +109,7 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator {
|
|||
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 <= SignUtils.BEDROCK_CHARACTER_WIDTH_MAX) {
|
||||
if (signWidth <= signWidthMax()) {
|
||||
finalSignLine.append(c);
|
||||
} else {
|
||||
// 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();
|
||||
String id = tag.getString("id");
|
||||
if (id.equals("Sign")) {
|
||||
// Hanging signs are narrower
|
||||
int widthMax = SignUtils.getSignWidthMax(session.getGeyser().getWorldManager().getBlockAt(session, packet.getBlockPosition()));
|
||||
|
||||
String text = MessageTranslator.convertToPlainText(
|
||||
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.
|
||||
|
@ -60,13 +63,10 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator<BlockEnti
|
|||
for (char character : text.toCharArray()) {
|
||||
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 (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
|
||||
boolean wentOverMax = widthCount > SignUtils.JAVA_CHARACTER_WIDTH_MAX && character != '\n';
|
||||
boolean wentOverMax = widthCount > widthMax && character != '\n';
|
||||
widthCount = 0;
|
||||
// Saves if we're moving a word to the next line
|
||||
String word = null;
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
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.
|
||||
* 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?
|
||||
/**
|
||||
* 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
|
||||
|
@ -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