/**
   * @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);
  }
Example #2
0
 public static String getTextRaw(Sign sign, int line) {
   return getTextRaw(sign.get(SignData.class).get(), line);
 }