RealmsUploadScreen.java

com.mojang.realmsclient.gui.screens.RealmsUploadScreen

信息

  • 全限定名:com.mojang.realmsclient.gui.screens.RealmsUploadScreen
  • 类型:public class
  • 包:com.mojang.realmsclient.gui.screens
  • 源码路径:src/main/java/com/mojang/realmsclient/gui/screens/RealmsUploadScreen.java
  • 起始行号:L40
  • 继承:RealmsScreen
  • 实现:RealmsWorldUploadStatusTracker
  • 职责:

    TODO

字段/常量

  • BAR_WIDTH

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

      TODO

  • BAR_TOP

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

      TODO

  • BAR_BOTTOM

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

      TODO

  • BAR_BORDER

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

      TODO

  • DOTS

    • 类型: String[]
    • 修饰符: private static final
    • 源码定位: L45
    • 说明:

      TODO

  • VERIFYING_TEXT

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

      TODO

  • lastScreen

    • 类型: RealmsResetWorldScreen
    • 修饰符: private final
    • 源码定位: L47
    • 说明:

      TODO

  • selectedLevel

    • 类型: LevelSummary
    • 修饰符: private final
    • 源码定位: L48
    • 说明:

      TODO

  • realmCreationTask

    • 类型: RealmCreationTask
    • 修饰符: private final
    • 源码定位: L49
    • 说明:

      TODO

  • realmId

    • 类型: long
    • 修饰符: private final
    • 源码定位: L50
    • 说明:

      TODO

  • slotId

    • 类型: int
    • 修饰符: private final
    • 源码定位: L51
    • 说明:

      TODO

  • currentUpload

    • 类型: AtomicReference<RealmsWorldUpload>
    • 修饰符: final
    • 源码定位: L52
    • 说明:

      TODO

  • uploadStatus

    • 类型: UploadStatus
    • 修饰符: private final
    • 源码定位: L53
    • 说明:

      TODO

  • narrationRateLimiter

    • 类型: RateLimiter
    • 修饰符: private final
    • 源码定位: L54
    • 说明:

      TODO

  • errorMessage

    • 类型: Component[]
    • 修饰符: private volatile
    • 源码定位: L55
    • 说明:

      TODO

  • status

    • 类型: Component
    • 修饰符: private volatile
    • 源码定位: L56
    • 说明:

      TODO

  • progress

    • 类型: String
    • 修饰符: private volatile
    • 源码定位: L57
    • 说明:

      TODO

  • cancelled

    • 类型: boolean
    • 修饰符: private volatile
    • 源码定位: L58
    • 说明:

      TODO

  • uploadFinished

    • 类型: boolean
    • 修饰符: private volatile
    • 源码定位: L59
    • 说明:

      TODO

  • showDots

    • 类型: boolean
    • 修饰符: private volatile
    • 源码定位: L60
    • 说明:

      TODO

  • uploadStarted

    • 类型: boolean
    • 修饰符: private volatile
    • 源码定位: L61
    • 说明:

      TODO

  • backButton

    • 类型: Button
    • 修饰符: private
    • 源码定位: L62
    • 说明:

      TODO

  • cancelButton

    • 类型: Button
    • 修饰符: private
    • 源码定位: L63
    • 说明:

      TODO

  • tickCount

    • 类型: int
    • 修饰符: private
    • 源码定位: L64
    • 说明:

      TODO

  • layout

    • 类型: HeaderAndFooterLayout
    • 修饰符: private final
    • 源码定位: L65
    • 说明:

      TODO

内部类/嵌套类型

构造器

public RealmsUploadScreen(RealmCreationTask realmCreationTask, long realmId, int slotId, RealmsResetWorldScreen lastScreen, LevelSummary selectedLevel) @ L67

  • 构造器名:RealmsUploadScreen
  • 源码定位:L67
  • 修饰符:public

参数:

  • realmCreationTask: RealmCreationTask
  • realmId: long
  • slotId: int
  • lastScreen: RealmsResetWorldScreen
  • selectedLevel: LevelSummary

说明:

TODO

方法

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

public void init() @ L80

  • 方法名:init
  • 源码定位:L80
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

protected void repositionElements() @ L112

  • 方法名:repositionElements
  • 源码定位:L112
  • 返回类型:void
  • 修饰符:protected

参数:

说明:

TODO

private void onBack() @ L117

  • 方法名:onBack
  • 源码定位:L117
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private void onCancel() @ L121

  • 方法名:onCancel
  • 源码定位:L121
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

public boolean keyPressed(KeyEvent event) @ L131

  • 方法名:keyPressed
  • 源码定位:L131
  • 返回类型:boolean
  • 修饰符:public

参数:

  • event: KeyEvent

说明:

TODO

public void extractRenderState(GuiGraphicsExtractor graphics, int xm, int ym, float a) @ L146

  • 方法名:extractRenderState
  • 源码定位:L146
  • 返回类型:void
  • 修饰符:public

参数:

  • graphics: GuiGraphicsExtractor
  • xm: int
  • ym: int
  • a: float

说明:

TODO

private void extractProgressBar(GuiGraphicsExtractor graphics) @ L172

  • 方法名:extractProgressBar
  • 源码定位:L172
  • 返回类型:void
  • 修饰符:private

参数:

  • graphics: GuiGraphicsExtractor

说明:

TODO

private void extractUploadSpeed(GuiGraphicsExtractor graphics) @ L182

  • 方法名:extractUploadSpeed
  • 源码定位:L182
  • 返回类型:void
  • 修饰符:private

参数:

  • graphics: GuiGraphicsExtractor

说明:

TODO

private void extractUploadSpeed0(GuiGraphicsExtractor graphics, long bytesPerSecond) @ L186

  • 方法名:extractUploadSpeed0
  • 源码定位:L186
  • 返回类型:void
  • 修饰符:private

参数:

  • graphics: GuiGraphicsExtractor
  • bytesPerSecond: long

说明:

TODO

public void tick() @ L195

  • 方法名:tick
  • 源码定位:L195
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

private Component createProgressNarrationMessage() @ L206

  • 方法名:createProgressNarrationMessage
  • 源码定位:L206
  • 返回类型:Component
  • 修饰符:private

参数:

说明:

TODO

private void upload() @ L221

  • 方法名:upload
  • 源码定位:L221
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private void setErrorMessage(Component... messages) @ L269

  • 方法名:setErrorMessage
  • 源码定位:L269
  • 返回类型:void
  • 修饰符:private

参数:

  • messages: Component…

说明:

TODO

public UploadStatus getUploadStatus() @ L273

  • 方法名:getUploadStatus
  • 源码定位:L273
  • 返回类型:UploadStatus
  • 修饰符:public

参数:

说明:

TODO

public void setUploading() @ L278

  • 方法名:setUploading
  • 源码定位:L278
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class RealmsUploadScreen extends RealmsScreen implements RealmsWorldUploadStatusTracker {
    private static final int BAR_WIDTH = 200;
    private static final int BAR_TOP = 80;
    private static final int BAR_BOTTOM = 95;
    private static final int BAR_BORDER = 1;
    private static final String[] DOTS = new String[]{"", ".", ". .", ". . ."};
    private static final Component VERIFYING_TEXT = Component.translatable("mco.upload.verifying");
    private final RealmsResetWorldScreen lastScreen;
    private final LevelSummary selectedLevel;
    private final @Nullable RealmCreationTask realmCreationTask;
    private final long realmId;
    private final int slotId;
    final AtomicReference<@Nullable RealmsWorldUpload> currentUpload = new AtomicReference<>();
    private final UploadStatus uploadStatus;
    private final RateLimiter narrationRateLimiter;
    private volatile Component @Nullable [] errorMessage;
    private volatile Component status = Component.translatable("mco.upload.preparing");
    private volatile @Nullable String progress;
    private volatile boolean cancelled;
    private volatile boolean uploadFinished;
    private volatile boolean showDots = true;
    private volatile boolean uploadStarted;
    private @Nullable Button backButton;
    private @Nullable Button cancelButton;
    private int tickCount;
    private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this);
 
    public RealmsUploadScreen(
        @Nullable RealmCreationTask realmCreationTask, long realmId, int slotId, RealmsResetWorldScreen lastScreen, LevelSummary selectedLevel
    ) {
        super(GameNarrator.NO_TITLE);
        this.realmCreationTask = realmCreationTask;
        this.realmId = realmId;
        this.slotId = slotId;
        this.lastScreen = lastScreen;
        this.selectedLevel = selectedLevel;
        this.uploadStatus = new UploadStatus();
        this.narrationRateLimiter = RateLimiter.create(0.1F);
    }
 
    @Override
    public void init() {
        this.backButton = this.layout.addToFooter(Button.builder(CommonComponents.GUI_BACK, button -> this.onBack()).build());
        this.backButton.visible = false;
        this.cancelButton = this.layout.addToFooter(Button.builder(CommonComponents.GUI_CANCEL, button -> this.onCancel()).build());
        if (!this.uploadStarted) {
            if (this.lastScreen.slot == -1) {
                this.uploadStarted = true;
                this.upload();
            } else {
                List<LongRunningTask> tasks = new ArrayList<>();
                if (this.realmCreationTask != null) {
                    tasks.add(this.realmCreationTask);
                }
 
                tasks.add(new SwitchSlotTask(this.realmId, this.lastScreen.slot, () -> {
                    if (!this.uploadStarted) {
                        this.uploadStarted = true;
                        this.minecraft.execute(() -> {
                            this.minecraft.setScreen(this);
                            this.upload();
                        });
                    }
                }));
                this.minecraft.setScreen(new RealmsLongRunningMcoTaskScreen(this.lastScreen, tasks.toArray(new LongRunningTask[0])));
            }
        }
 
        this.layout.visitWidgets(x$0 -> this.addRenderableWidget(x$0));
        this.repositionElements();
    }
 
    @Override
    protected void repositionElements() {
        this.layout.arrangeElements();
    }
 
    private void onBack() {
        this.minecraft.setScreen(new RealmsConfigureWorldScreen(new RealmsMainScreen(new TitleScreen()), this.realmId));
    }
 
    private void onCancel() {
        this.cancelled = true;
        RealmsWorldUpload realmsWorldUpload = this.currentUpload.get();
        if (realmsWorldUpload != null) {
            realmsWorldUpload.cancel();
        } else {
            this.minecraft.setScreen(this.lastScreen);
        }
    }
 
    @Override
    public boolean keyPressed(KeyEvent event) {
        if (event.isEscape()) {
            if (this.showDots) {
                this.onCancel();
            } else {
                this.onBack();
            }
 
            return true;
        } else {
            return super.keyPressed(event);
        }
    }
 
    @Override
    public void extractRenderState(GuiGraphicsExtractor graphics, int xm, int ym, float a) {
        super.extractRenderState(graphics, xm, ym, a);
        if (!this.uploadFinished && this.uploadStatus.uploadStarted() && this.uploadStatus.uploadCompleted() && this.cancelButton != null) {
            this.status = VERIFYING_TEXT;
            this.cancelButton.active = false;
        }
 
        graphics.centeredText(this.font, this.status, this.width / 2, 50, -1);
        if (this.showDots) {
            graphics.text(this.font, DOTS[this.tickCount / 10 % DOTS.length], this.width / 2 + this.font.width(this.status) / 2 + 5, 50, -1);
        }
 
        if (this.uploadStatus.uploadStarted() && !this.cancelled) {
            this.extractProgressBar(graphics);
            this.extractUploadSpeed(graphics);
        }
 
        Component[] errorMessages = this.errorMessage;
        if (errorMessages != null) {
            for (int i = 0; i < errorMessages.length; i++) {
                graphics.centeredText(this.font, errorMessages[i], this.width / 2, 110 + 12 * i, -65536);
            }
        }
    }
 
    private void extractProgressBar(GuiGraphicsExtractor graphics) {
        double percentage = this.uploadStatus.getPercentage();
        this.progress = String.format(Locale.ROOT, "%.1f", percentage * 100.0);
        int left = (this.width - 200) / 2;
        int right = left + (int)Math.round(200.0 * percentage);
        graphics.fill(left - 1, 79, right + 1, 96, -1);
        graphics.fill(left, 80, right, 95, -8355712);
        graphics.centeredText(this.font, Component.translatable("mco.upload.percent", this.progress), this.width / 2, 84, -1);
    }
 
    private void extractUploadSpeed(GuiGraphicsExtractor graphics) {
        this.extractUploadSpeed0(graphics, this.uploadStatus.getBytesPerSecond());
    }
 
    private void extractUploadSpeed0(GuiGraphicsExtractor graphics, long bytesPerSecond) {
        String uploadProgress = this.progress;
        if (bytesPerSecond > 0L && uploadProgress != null) {
            int progressLength = this.font.width(uploadProgress);
            String stringPresentation = "(" + Unit.humanReadable(bytesPerSecond) + "/s)";
            graphics.text(this.font, stringPresentation, this.width / 2 + progressLength / 2 + 15, 84, -1);
        }
    }
 
    @Override
    public void tick() {
        super.tick();
        this.tickCount++;
        this.uploadStatus.refreshBytesPerSecond();
        if (this.narrationRateLimiter.tryAcquire(1)) {
            Component message = this.createProgressNarrationMessage();
            this.minecraft.getNarrator().saySystemNow(message);
        }
    }
 
    private Component createProgressNarrationMessage() {
        List<Component> elements = Lists.newArrayList();
        elements.add(this.status);
        if (this.progress != null) {
            elements.add(Component.translatable("mco.upload.percent", this.progress));
        }
 
        Component[] errorMessages = this.errorMessage;
        if (errorMessages != null) {
            elements.addAll(Arrays.asList(errorMessages));
        }
 
        return CommonComponents.joinLines(elements);
    }
 
    private void upload() {
        Path worldFolder = this.minecraft.gameDirectory.toPath().resolve("saves").resolve(this.selectedLevel.getLevelId());
        RealmsWorldOptions worldOptions = RealmsWorldOptions.createFromSettings(
            this.selectedLevel.getSettings(), this.selectedLevel.levelVersion().minecraftVersionName()
        );
        RealmsSlot realmsSlot = new RealmsSlot(this.slotId, worldOptions, List.of(RealmsSetting.hardcoreSetting(this.selectedLevel.isHardcore())));
        RealmsWorldUpload newUpload = new RealmsWorldUpload(worldFolder, realmsSlot, this.minecraft.getUser(), this.realmId, this);
        if (!this.currentUpload.compareAndSet(null, newUpload)) {
            throw new IllegalStateException("Tried to start uploading but was already uploading");
        } else {
            newUpload.packAndUpload().handleAsync((result, exception) -> {
                if (exception != null) {
                    if (exception instanceof CompletionException e) {
                        exception = e.getCause();
                    }
 
                    if (exception instanceof RealmsUploadException e) {
                        if (e.getStatusMessage() != null) {
                            this.status = e.getStatusMessage();
                        }
 
                        this.setErrorMessage(e.getErrorMessages());
                    } else {
                        this.status = Component.translatable("mco.upload.failed", exception.getMessage());
                    }
                } else {
                    this.status = Component.translatable("mco.upload.done");
                    if (this.backButton != null) {
                        this.backButton.setMessage(CommonComponents.GUI_DONE);
                    }
                }
 
                this.uploadFinished = true;
                this.showDots = false;
                if (this.backButton != null) {
                    this.backButton.visible = true;
                }
 
                if (this.cancelButton != null) {
                    this.cancelButton.visible = false;
                }
 
                this.currentUpload.set(null);
                return null;
            }, this.minecraft);
        }
    }
 
    private void setErrorMessage(Component @Nullable ... messages) {
        this.errorMessage = messages;
    }
 
    @Override
    public UploadStatus getUploadStatus() {
        return this.uploadStatus;
    }
 
    @Override
    public void setUploading() {
        this.status = Component.translatable("mco.upload.uploading", this.selectedLevel.getLevelName());
    }
}

引用的其他类