/** * @Author Zidane * * <p>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 = "Lnet/minecraft/network/play/client/C12PacketUpdateSign;getLines()[Lnet/minecraft/util/IChatComponent;"), cancellable = true, locals = LocalCapture.CAPTURE_FAILSOFT) public void callSignChangeEvent( C12PacketUpdateSign packetIn, CallbackInfo ci, WorldServer worldserver, BlockPos blockpos, TileEntity tileentity, TileEntitySign tileentitysign) { ci.cancel(); final Optional<SignData> existingSignData = ((Sign) tileentitysign).getData(); 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(); for (int i = 0; i < packetIn.getLines().length; i++) { changedSignData.setLine(i, SpongeTexts.toText(packetIn.getLines()[i])); } // 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 final SignChangeEvent event = SpongeEventFactory.createSignChange( Sponge.getGame(), new Cause(null, this.playerEntity, null), (Sign) tileentitysign, changedSignData, changedSignData); if (!Sponge.getGame().getEventManager().post(event)) { ((Sign) tileentitysign).offer(event.getNewData()); } 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()); } tileentitysign.markDirty(); worldserver.markBlockForUpdate(blockpos); }
public static String getTextRaw(Sign sign, int line) { return getTextRaw(sign.get(SignData.class).get(), line); }