Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix banner crashing client when copying blank vanilia banner and desync in multiplayer #10500

Merged
merged 12 commits into from
Dec 8, 2024
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 @@ -1921,6 +1921,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
Loading