SignedMessageChain.java

net.minecraft.network.chat.SignedMessageChain

信息

  • 全限定名:net.minecraft.network.chat.SignedMessageChain
  • 类型:public class
  • 包:net.minecraft.network.chat
  • 源码路径:src/main/java/net/minecraft/network/chat/SignedMessageChain.java
  • 起始行号:L14
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L15
    • 说明:

      TODO

  • nextLink

    • 类型: SignedMessageLink
    • 修饰符: private
    • 源码定位: L16
    • 说明:

      TODO

  • lastTimeStamp

    • 类型: Instant
    • 修饰符: private
    • 源码定位: L17
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.network.chat.SignedMessageChain.DecodeException

    • 类型: class
    • 修饰符: public static
    • 源码定位: L80
    • 说明:

      TODO

  • net.minecraft.network.chat.SignedMessageChain.Decoder

    • 类型: interface
    • 修饰符: public
    • 源码定位: L93
    • 说明:

      TODO

  • net.minecraft.network.chat.SignedMessageChain.Encoder

    • 类型: interface
    • 修饰符: public
    • 源码定位: L111
    • 说明:

      TODO

构造器

public SignedMessageChain(UUID profileId, UUID sessionId) @ L19

  • 构造器名:SignedMessageChain
  • 源码定位:L19
  • 修饰符:public

参数:

  • profileId: UUID
  • sessionId: UUID

说明:

TODO

方法

下面的方法块按源码顺序生成。

public SignedMessageChain.Encoder encoder(Signer signer) @ L23

  • 方法名:encoder
  • 源码定位:L23
  • 返回类型:SignedMessageChain.Encoder
  • 修饰符:public

参数:

  • signer: Signer

说明:

TODO

public SignedMessageChain.Decoder decoder(ProfilePublicKey profilePublicKey) @ L35

  • 方法名:decoder
  • 源码定位:L35
  • 返回类型:SignedMessageChain.Decoder
  • 修饰符:public

参数:

  • profilePublicKey: ProfilePublicKey

说明:

TODO

代码

public class SignedMessageChain {
    private static final Logger LOGGER = LogUtils.getLogger();
    private @Nullable SignedMessageLink nextLink;
    private Instant lastTimeStamp = Instant.EPOCH;
 
    public SignedMessageChain(UUID profileId, UUID sessionId) {
        this.nextLink = SignedMessageLink.root(profileId, sessionId);
    }
 
    public SignedMessageChain.Encoder encoder(Signer signer) {
        return body -> {
            SignedMessageLink link = this.nextLink;
            if (link == null) {
                return null;
            } else {
                this.nextLink = link.advance();
                return new MessageSignature(signer.sign(output -> PlayerChatMessage.updateSignature(output, link, body)));
            }
        };
    }
 
    public SignedMessageChain.Decoder decoder(ProfilePublicKey profilePublicKey) {
        final SignatureValidator signatureValidator = profilePublicKey.createSignatureValidator();
        return new SignedMessageChain.Decoder() {
            {
                Objects.requireNonNull(SignedMessageChain.this);
            }
 
            @Override
            public PlayerChatMessage unpack(@Nullable MessageSignature signature, SignedMessageBody body) throws SignedMessageChain.DecodeException {
                if (signature == null) {
                    throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.MISSING_PROFILE_KEY);
                } else if (profilePublicKey.data().hasExpired()) {
                    throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.EXPIRED_PROFILE_KEY);
                } else {
                    SignedMessageLink link = SignedMessageChain.this.nextLink;
                    if (link == null) {
                        throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.CHAIN_BROKEN);
                    } else if (body.timeStamp().isBefore(SignedMessageChain.this.lastTimeStamp)) {
                        this.setChainBroken();
                        throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.OUT_OF_ORDER_CHAT);
                    } else {
                        SignedMessageChain.this.lastTimeStamp = body.timeStamp();
                        PlayerChatMessage unpacked = new PlayerChatMessage(link, signature, body, null, FilterMask.PASS_THROUGH);
                        if (!unpacked.verify(signatureValidator)) {
                            this.setChainBroken();
                            throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.INVALID_SIGNATURE);
                        } else {
                            if (unpacked.hasExpiredServer(Instant.now())) {
                                SignedMessageChain.LOGGER.warn("Received expired chat: '{}'. Is the client/server system time unsynchronized?", body.content());
                            }
 
                            SignedMessageChain.this.nextLink = link.advance();
                            return unpacked;
                        }
                    }
                }
            }
 
            @Override
            public void setChainBroken() {
                SignedMessageChain.this.nextLink = null;
            }
        };
    }
 
    public static class DecodeException extends ThrowingComponent {
        private static final Component MISSING_PROFILE_KEY = Component.translatable("chat.disabled.missingProfileKey");
        private static final Component CHAIN_BROKEN = Component.translatable("chat.disabled.chain_broken");
        private static final Component EXPIRED_PROFILE_KEY = Component.translatable("chat.disabled.expiredProfileKey");
        private static final Component INVALID_SIGNATURE = Component.translatable("chat.disabled.invalid_signature");
        private static final Component OUT_OF_ORDER_CHAT = Component.translatable("chat.disabled.out_of_order_chat");
 
        public DecodeException(Component component) {
            super(component);
        }
    }
 
    @FunctionalInterface
    public interface Decoder {
        static SignedMessageChain.Decoder unsigned(UUID profileId, BooleanSupplier enforcesSecureChat) {
            return (signature, body) -> {
                if (enforcesSecureChat.getAsBoolean()) {
                    throw new SignedMessageChain.DecodeException(SignedMessageChain.DecodeException.MISSING_PROFILE_KEY);
                } else {
                    return PlayerChatMessage.unsigned(profileId, body.content());
                }
            };
        }
 
        PlayerChatMessage unpack(@Nullable MessageSignature signature, SignedMessageBody body) throws SignedMessageChain.DecodeException;
 
        default void setChainBroken() {
        }
    }
 
    @FunctionalInterface
    public interface Encoder {
        SignedMessageChain.Encoder UNSIGNED = body -> null;
 
        @Nullable MessageSignature pack(SignedMessageBody body);
    }
}

引用的其他类

  • Component

    • 引用位置: 方法调用
    • 关联成员: Component.translatable()
  • MessageSignature

    • 引用位置: 构造调用
    • 关联成员: MessageSignature()
  • PlayerChatMessage

    • 引用位置: 方法调用/构造调用
    • 关联成员: PlayerChatMessage(), PlayerChatMessage.unsigned(), PlayerChatMessage.updateSignature()
  • SignedMessageLink

    • 引用位置: 字段/方法调用
    • 关联成员: SignedMessageLink.root()
  • Signer

    • 引用位置: 参数
  • ProfilePublicKey

    • 引用位置: 参数