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);
}
Aggregations