mirror of https://github.com/GeyserMC/Geyser.git
210 lines
9.2 KiB
Java
210 lines
9.2 KiB
Java
/*
|
|
* 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.item.type;
|
|
|
|
import it.unimi.dsi.fastutil.Pair;
|
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
import org.cloudburstmc.nbt.NbtList;
|
|
import org.cloudburstmc.nbt.NbtMap;
|
|
import org.cloudburstmc.nbt.NbtType;
|
|
import org.geysermc.geyser.inventory.item.BannerPattern;
|
|
import org.geysermc.geyser.inventory.item.DyeColor;
|
|
import org.geysermc.geyser.registry.type.ItemMapping;
|
|
import org.geysermc.geyser.session.GeyserSession;
|
|
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
|
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
|
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
|
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
public class BannerItem extends BlockItem {
|
|
/**
|
|
* Holds what a Java ominous banner pattern looks like.
|
|
* <p>
|
|
* Translating the patterns over to Bedrock does not work effectively, but Bedrock has a dedicated type for
|
|
* ominous banners that we set instead. This variable is used to detect Java ominous banner patterns, and apply
|
|
* the correct ominous banner pattern if Bedrock pulls the item from creative.
|
|
*/
|
|
private static final List<Pair<BannerPattern, DyeColor>> OMINOUS_BANNER_PATTERN;
|
|
private static final List<NbtMap> OMINOUS_BANNER_PATTERN_BLOCK;
|
|
|
|
static {
|
|
// Construct what an ominous banner is supposed to look like
|
|
OMINOUS_BANNER_PATTERN = List.of(
|
|
Pair.of(BannerPattern.RHOMBUS, DyeColor.CYAN),
|
|
Pair.of(BannerPattern.STRIPE_BOTTOM, DyeColor.LIGHT_GRAY),
|
|
Pair.of(BannerPattern.STRIPE_CENTER, DyeColor.GRAY),
|
|
Pair.of(BannerPattern.BORDER, DyeColor.LIGHT_GRAY),
|
|
Pair.of(BannerPattern.STRIPE_MIDDLE, DyeColor.BLACK),
|
|
Pair.of(BannerPattern.HALF_HORIZONTAL, DyeColor.LIGHT_GRAY),
|
|
Pair.of(BannerPattern.CIRCLE, DyeColor.LIGHT_GRAY),
|
|
Pair.of(BannerPattern.BORDER, DyeColor.BLACK)
|
|
);
|
|
|
|
OMINOUS_BANNER_PATTERN_BLOCK = new ArrayList<>();
|
|
for (Pair<BannerPattern, DyeColor> pair : OMINOUS_BANNER_PATTERN) {
|
|
OMINOUS_BANNER_PATTERN_BLOCK.add(getJavaBannerPatternTag(pair.left(), pair.right()));
|
|
}
|
|
}
|
|
|
|
public static boolean isOminous(GeyserSession session, List<BannerPatternLayer> patternLayers) {
|
|
if (OMINOUS_BANNER_PATTERN.size() != patternLayers.size()) {
|
|
return false;
|
|
}
|
|
for (int i = 0; i < OMINOUS_BANNER_PATTERN.size(); i++) {
|
|
BannerPatternLayer patternLayer = patternLayers.get(i);
|
|
Pair<BannerPattern, DyeColor> pair = OMINOUS_BANNER_PATTERN.get(i);
|
|
if (patternLayer.getColorId() != pair.right().ordinal() ||
|
|
!patternLayer.getPattern().isId()) {
|
|
return false;
|
|
}
|
|
BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().get(patternLayer.getPattern().id());
|
|
if (bannerPattern != pair.left()) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static boolean isOminous(List<NbtMap> blockEntityPatterns) {
|
|
return OMINOUS_BANNER_PATTERN_BLOCK.equals(blockEntityPatterns);
|
|
}
|
|
|
|
/**
|
|
* Convert a list of patterns from Java nbt to Bedrock nbt
|
|
*
|
|
* @param patterns The patterns to convert
|
|
* @return The new converted patterns
|
|
*/
|
|
public static NbtList<NbtMap> convertBannerPattern(List<NbtMap> patterns) {
|
|
List<NbtMap> tagsList = new ArrayList<>();
|
|
for (NbtMap patternTag : patterns) {
|
|
NbtMap bedrockBannerPattern = getBedrockBannerPattern(patternTag);
|
|
if (bedrockBannerPattern != null) {
|
|
tagsList.add(bedrockBannerPattern);
|
|
}
|
|
}
|
|
|
|
return new NbtList<>(NbtType.COMPOUND, tagsList);
|
|
}
|
|
|
|
/**
|
|
* Converts a Java item component for banners into Bedrock item NBT.
|
|
*/
|
|
static void convertBannerPattern(GeyserSession session, List<BannerPatternLayer> patterns, BedrockItemBuilder builder) {
|
|
if (isOminous(session, patterns)) {
|
|
// Remove the current patterns and set the ominous banner type
|
|
builder.putInt("Type", 1);
|
|
} else {
|
|
List<NbtMap> patternList = new ArrayList<>(patterns.size());
|
|
for (BannerPatternLayer patternLayer : patterns) {
|
|
patternLayer.getPattern().ifId(holder -> {
|
|
BannerPattern bannerPattern = session.getRegistryCache().bannerPatterns().get(holder.id());
|
|
if (bannerPattern != null) {
|
|
NbtMap tag = NbtMap.builder()
|
|
.putString("Pattern", bannerPattern.getBedrockIdentifier())
|
|
.putInt("Color", 15 - patternLayer.getColorId())
|
|
.build();
|
|
patternList.add(tag);
|
|
}
|
|
});
|
|
}
|
|
builder.putList("Patterns", NbtType.COMPOUND, patternList);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert the Java edition banner pattern nbt to Bedrock edition, null if the pattern doesn't exist
|
|
*
|
|
* @param pattern Java edition pattern nbt
|
|
* @return The Bedrock edition format pattern nbt
|
|
*/
|
|
private static NbtMap getBedrockBannerPattern(NbtMap pattern) {
|
|
BannerPattern bannerPattern = BannerPattern.getByJavaIdentifier(pattern.getString("pattern"));
|
|
DyeColor dyeColor = DyeColor.getByJavaIdentifier(pattern.getString("color"));
|
|
if (bannerPattern == null || dyeColor == null) {
|
|
return null;
|
|
}
|
|
|
|
return NbtMap.builder()
|
|
.putString("Pattern", bannerPattern.getBedrockIdentifier())
|
|
.putInt("Color", 15 - dyeColor.ordinal())
|
|
.build();
|
|
}
|
|
|
|
public static NbtMap getJavaBannerPatternTag(BannerPattern bannerPattern, DyeColor dyeColor) {
|
|
return NbtMap.builder()
|
|
.putString("pattern", bannerPattern.getJavaIdentifier())
|
|
.putString("color", dyeColor.getJavaIdentifier())
|
|
.build();
|
|
}
|
|
|
|
/**
|
|
* Convert the Bedrock edition banner pattern nbt to Java edition
|
|
*
|
|
* @param pattern Bedrock edition pattern nbt
|
|
* @return The Java edition format pattern layer
|
|
*/
|
|
public static BannerPatternLayer getJavaBannerPattern(GeyserSession session, NbtMap pattern) {
|
|
return null; // TODO
|
|
/*Int2ObjectBiMap<BannerPattern> registry = session.getRegistryCache().bannerPatterns();
|
|
BannerPattern bannerPattern = BannerPattern.getByBedrockIdentifier(pattern.getString("Pattern"));
|
|
DyeColor dyeColor = DyeColor.getById(15 - pattern.getInt("Color"));
|
|
if (bannerPattern != null && dyeColor != null && registry.containsValue(bannerPattern)) {
|
|
return new BannerPatternLayer(Holder.ofId(registry.get(bannerPattern)), dyeColor.ordinal());
|
|
}
|
|
return null;*/
|
|
}
|
|
|
|
public BannerItem(String javaIdentifier, Builder builder) {
|
|
super(javaIdentifier, builder);
|
|
}
|
|
|
|
@Override
|
|
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
|
|
super.translateComponentsToBedrock(session, components, builder);
|
|
|
|
List<BannerPatternLayer> patterns = components.get(DataComponentType.BANNER_PATTERNS);
|
|
if (patterns != null) {
|
|
convertBannerPattern(session, patterns, builder);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void translateNbtToJava(@NonNull NbtMap bedrockTag, @NonNull DataComponents components, @NonNull ItemMapping mapping) { // TODO
|
|
super.translateNbtToJava(bedrockTag, components, mapping);
|
|
|
|
if (bedrockTag.getInt("Type") == 1) {
|
|
// Ominous banner pattern
|
|
// TODO more registry stuff
|
|
//components.put(DataComponentType.BANNER_PATTERNS);
|
|
}
|
|
// Bedrock's creative inventory does not support other patterns as of 1.20.5
|
|
}
|
|
}
|