Search in sources :

Example 1 with CPacketUpdateSign

use of net.minecraft.network.play.client.CPacketUpdateSign in project SpongeCommon by SpongePowered.

the class MixinNetHandlerPlayServer method callSignChangeEvent.

/**
 * @author Zidane
 *
 * Invoke before {@code System.arraycopy(packetIn.getLines(), 0, tileentitysign.signText, 0, 4);} (line 1156 in source) to call SignChangeEvent.
 * @param packetIn Injected packet param
 * @param ci Info to provide mixin on how to handle the callback
 * @param worldserver Injected world param
 * @param blockpos Injected blockpos param
 * @param tileentity Injected tilentity param
 * @param tileentitysign Injected tileentitysign param
 */
@Inject(method = "processUpdateSign", at = @At(value = "INVOKE", target = UPDATE_SIGN), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
public void callSignChangeEvent(CPacketUpdateSign packetIn, CallbackInfo ci, WorldServer worldserver, BlockPos blockpos, IBlockState iblockstate, TileEntity tileentity, TileEntitySign tileentitysign) {
    ci.cancel();
    final Optional<SignData> existingSignData = ((Sign) tileentitysign).get(SignData.class);
    if (!existingSignData.isPresent()) {
        // TODO Unsure if this is the best to do here...
        throw new RuntimeException("Critical error! Sign data not present on sign!");
    }
    final SignData changedSignData = existingSignData.get().copy();
    final ListValue<Text> lines = changedSignData.lines();
    for (int i = 0; i < packetIn.getLines().length; i++) {
        lines.set(i, SpongeTexts.toText(new TextComponentString(packetIn.getLines()[i])));
    }
    changedSignData.set(lines);
    // I pass changedSignData in here twice to emulate the fact that even-though the current sign data doesn't have the lines from the packet
    // applied, this is what it "is" right now. If the data shown in the world is desired, it can be fetched from Sign.getData
    Sponge.getCauseStackManager().pushCause(this.player);
    final ChangeSignEvent event = SpongeEventFactory.createChangeSignEvent(Sponge.getCauseStackManager().getCurrentCause(), changedSignData.asImmutable(), changedSignData, (Sign) tileentitysign);
    if (!SpongeImpl.postEvent(event)) {
        ((Sign) tileentitysign).offer(event.getText());
    } else {
        // If cancelled, I set the data back that was fetched from the sign. This means that if its a new sign, the sign will be empty else
        // it will be the text of the sign that was showing in the world
        ((Sign) tileentitysign).offer(existingSignData.get());
    }
    Sponge.getCauseStackManager().popCause();
    tileentitysign.markDirty();
    worldserver.getPlayerChunkMap().markBlockForUpdate(blockpos);
}
Also used : SignData(org.spongepowered.api.data.manipulator.mutable.tileentity.SignData) ChangeSignEvent(org.spongepowered.api.event.block.tileentity.ChangeSignEvent) TileEntitySign(net.minecraft.tileentity.TileEntitySign) Sign(org.spongepowered.api.block.tileentity.Sign) CPacketUpdateSign(net.minecraft.network.play.client.CPacketUpdateSign) Text(org.spongepowered.api.text.Text) TextComponentString(net.minecraft.util.text.TextComponentString) Inject(org.spongepowered.asm.mixin.injection.Inject)

Aggregations

CPacketUpdateSign (net.minecraft.network.play.client.CPacketUpdateSign)1 TileEntitySign (net.minecraft.tileentity.TileEntitySign)1 TextComponentString (net.minecraft.util.text.TextComponentString)1 Sign (org.spongepowered.api.block.tileentity.Sign)1 SignData (org.spongepowered.api.data.manipulator.mutable.tileentity.SignData)1 ChangeSignEvent (org.spongepowered.api.event.block.tileentity.ChangeSignEvent)1 Text (org.spongepowered.api.text.Text)1 Inject (org.spongepowered.asm.mixin.injection.Inject)1