Skip to content

Commit

Permalink
Fix banner crashing client when copying blank vanilia banner and desy…
Browse files Browse the repository at this point in the history
…nc in multiplayer (#10500)

Fix banner crashing client on banner that didn't have tags (aka blank patterns)
Fix server not copying but client did, causing a desync
add a explanation on how to copy banner's patterns
  • Loading branch information
cylian914 authored Dec 8, 2024
1 parent bca16ad commit 9700ea5
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public TileEntityColonyFlagRenderer(final BlockEntityRendererProvider.Context co
@Override
public void render(TileEntityColonyFlag flagIn, float partialTicks, PoseStack transform, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn)
{
List<Pair<Holder<BannerPattern>, DyeColor>> list = flagIn.getPatternList();
List<Pair<Holder<BannerPattern>, DyeColor>> list = flagIn.getPatterns();

boolean noWorld = flagIn.getLevel() == null;
transform.pushPose();
Expand Down
54 changes: 25 additions & 29 deletions src/main/java/com/minecolonies/core/items/ItemColonyFlagBanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

import com.minecolonies.api.blocks.ModBlocks;
import com.minecolonies.core.tileentities.TileEntityColonyFlag;
import net.minecraft.world.level.block.AbstractBannerBlock;
import com.mojang.datafixers.util.Pair;

import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BannerPatterns;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.BannerItem;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.core.Holder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.world.level.block.entity.BannerBlockEntity;
import net.minecraft.world.level.block.entity.BannerPattern;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.InteractionResult;
import net.minecraft.network.chat.Component;
Expand Down Expand Up @@ -46,38 +48,27 @@ public InteractionResult useOn(UseOnContext context)
{
// Duplicate the patterns of the banner that was clicked on
BlockEntity te = context.getLevel().getBlockEntity(context.getClickedPos());
BlockState state = context.getLevel().getBlockState(context.getClickedPos());
ItemStack stack = context.getPlayer().getMainHandItem();
ItemStack stack = context.getItemInHand();

if (te instanceof BannerBlockEntity || te instanceof TileEntityColonyFlag)
{
CompoundTag source;
BannerPattern.Builder patternsBuilder = new BannerPattern.Builder();
List<Pair<Holder<BannerPattern>, DyeColor>> source;

if (te instanceof BannerBlockEntity)
{
source = ((BannerBlockEntity) te).getItem()
.getTag().getCompound("BlockEntityTag");
source = ((BannerBlockEntity) te).getPatterns();
}
else
{
source = (context.getLevel().isClientSide ? ((TileEntityColonyFlag) te).getItemClient() : ((TileEntityColonyFlag) te).getItemServer())
.getTag().getCompound("BlockEntityTag");
}

ListTag patternList = source.getList(TAG_BANNER_PATTERNS, 10);

// Set the base pattern, if there wasn't one set.
// This saves us attempting to alter the item itself to change the base color.
if (!patternList.getCompound(0).getString(TAG_SINGLE_PATTERN).equals(BannerPatterns.BASE.location().toString()))
{
CompoundTag nbt = new CompoundTag();
nbt.putString(TAG_SINGLE_PATTERN, BannerPatterns.BASE.location().toString());
nbt.putInt(TAG_PATTERN_COLOR, ((AbstractBannerBlock) state.getBlock()).getColor().getId());
patternList.add(0, nbt);
source = ((TileEntityColonyFlag) te).getPatterns();
}

CompoundTag tag = stack.getOrCreateTagElement("BlockEntityTag");
tag.put(TAG_BANNER_PATTERNS, patternList);
CompoundTag bannerPattern = new CompoundTag();
source.forEach((pattern) -> patternsBuilder.addPattern(pattern.getFirst(), pattern.getSecond()));
bannerPattern.put(TAG_BANNER_PATTERNS, patternsBuilder.toListTag());

stack.addTagElement("BlockEntityTag", bannerPattern);
return InteractionResult.SUCCESS;
}
return super.useOn(context);
Expand All @@ -86,9 +77,14 @@ public InteractionResult useOn(UseOnContext context)
@Override
public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List<Component> tooltip, TooltipFlag flagIn)
{
super.appendHoverText(stack, worldIn, tooltip, flagIn);

// Remove the base, as they have no translations (Mojang were lazy. Or maybe saving space?)
if (tooltip.size() > 1) tooltip.remove(1);
CompoundTag tag = BlockItem.getBlockEntityData(stack);
if (tag != null && tag.contains(TAG_BANNER_PATTERNS))
{
super.appendHoverText(stack, worldIn, tooltip, flagIn);
}
else
{
tooltip.add(Component.translatable("com.minecolonies.coremod.item.colony_banner.tooltipempty"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@

public class TileEntityColonyFlag extends BlockEntity
{
/** The last known flag. Required for when the colony is not available. */
private ListTag flag = new ListTag();

/** A list of the default banner patterns, for colonies that have not chosen a flag */
private ListTag patterns = new ListTag();

Expand All @@ -44,7 +41,6 @@ public void saveAdditional(CompoundTag compound)
{
super.saveAdditional(compound);

compound.put(TAG_FLAG_PATTERNS, this.flag);
compound.put(TAG_BANNER_PATTERNS, this.patterns);

compound.putInt(TAG_COLONY_ID, colonyId);
Expand All @@ -55,7 +51,6 @@ public void load(CompoundTag compound)
{
super.load(compound);

this.flag = compound.getList(TAG_FLAG_PATTERNS, 10);
this.patterns = compound.getList(TAG_BANNER_PATTERNS, 10);
this.colonyId = compound.getInt(TAG_COLONY_ID);

Expand Down Expand Up @@ -87,27 +82,29 @@ public void onDataPacket(final Connection net, final ClientboundBlockEntityDataP
}

/**
* Retrieves the patterns for the renderer
* Retrieves the patterns, similar to {@link BannerBlockEntity#getPatterns()}
* @return the list of pattern-color pairs
*/
@OnlyIn(Dist.CLIENT)
public List<Pair<Holder<BannerPattern>, DyeColor>> getPatternList()
public List<Pair<Holder<BannerPattern>, DyeColor>> getPatterns()
{
// Structurize will cause the second condition to be false
if (level != null && level.dimension() != null)
{
IColonyView colony = IColonyManager.getInstance().getColonyView(this.colonyId, level.dimension());
if (colony != null && this.flag != colony.getColonyFlag())
if (colony != null && this.patterns != colony.getColonyFlag())
{
this.flag = colony.getColonyFlag();
this.patterns = colony.getColonyFlag();
setChanged();
}
}

return BannerBlockEntity.createPatterns(
List<Pair<Holder<BannerPattern>, DyeColor>> pattern = BannerBlockEntity.createPatterns(
DyeColor.WHITE,
this.flag.size() > 1 ? this.flag : this.patterns
this.patterns
);
//remove the first base layer
pattern.remove(0);
return pattern;
}

/**
Expand All @@ -118,7 +115,7 @@ public List<Pair<Holder<BannerPattern>, DyeColor>> getPatternList()
public ItemStack getItemClient()
{
ItemStack itemstack = new ItemStack(ModBlocks.blockColonyBanner);
List<Pair<Holder<BannerPattern>, DyeColor>> list = getPatternList();
List<Pair<Holder<BannerPattern>, DyeColor>> list = getPatterns();
ListTag nbt = new ListTag();

for (Pair<Holder<BannerPattern>, DyeColor> pair : list)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1945,6 +1945,7 @@
"com.minecolonies.coremod.gui.flag.base_layer": "Base",
"com.minecolonies.coremod.gui.townhall.edit_flag": "Edit Colony Flag",
"block.minecolonies.colony_banner": "Colony Flag Banner",
"com.minecolonies.coremod.item.colony_banner.tooltipempty": "Right click to copy pattern on the item",
"com.minecolonies.coremod.gui.locate": "Locate",
"com.minecolonies.coremod.locating": "Successfully located rack with respective item(s).",

Expand Down

0 comments on commit 9700ea5

Please sign in to comment.