ServerPackManager.java

net.minecraft.client.resources.server.ServerPackManager

信息

  • 全限定名:net.minecraft.client.resources.server.ServerPackManager
  • 类型:public class
  • 包:net.minecraft.client.resources.server
  • 源码路径:src/main/java/net/minecraft/client/resources/server/ServerPackManager.java
  • 起始行号:L20
  • 职责:

    TODO

字段/常量

  • downloader

    • 类型: PackDownloader
    • 修饰符: private final
    • 源码定位: L21
    • 说明:

      TODO

  • packLoadFeedback

    • 类型: PackLoadFeedback
    • 修饰符: private final
    • 源码定位: L22
    • 说明:

      TODO

  • reloadConfig

    • 类型: PackReloadConfig
    • 修饰符: private final
    • 源码定位: L23
    • 说明:

      TODO

  • updateRequest

    • 类型: Runnable
    • 修饰符: private final
    • 源码定位: L24
    • 说明:

      TODO

  • packPromptStatus

    • 类型: ServerPackManager.PackPromptStatus
    • 修饰符: private
    • 源码定位: L25
    • 说明:

      TODO

  • packs

    • 类型: List<ServerPackManager.ServerPackData>
    • 修饰符: private final
    • 源码定位: L26
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.client.resources.server.ServerPackManager.ActivationStatus

    • 类型: enum
    • 修饰符: private static
    • 源码定位: L328
    • 说明:

      TODO

  • net.minecraft.client.resources.server.ServerPackManager.PackDownloadStatus

    • 类型: enum
    • 修饰符: private static
    • 源码定位: L335
    • 说明:

      TODO

  • net.minecraft.client.resources.server.ServerPackManager.PackPromptStatus

    • 类型: enum
    • 修饰符: public static
    • 源码定位: L342
    • 说明:

      TODO

  • net.minecraft.client.resources.server.ServerPackManager.RemovalReason

    • 类型: enum
    • 修饰符: private static
    • 源码定位: L349
    • 说明:

      TODO

  • net.minecraft.client.resources.server.ServerPackManager.ServerPackData

    • 类型: class
    • 修饰符: private static
    • 源码定位: L365
    • 说明:

      TODO

构造器

public ServerPackManager(PackDownloader downloader, PackLoadFeedback packLoadFeedback, PackReloadConfig reloadConfig, Runnable updateRequest, ServerPackManager.PackPromptStatus packPromptStatus) @ L28

  • 构造器名:ServerPackManager
  • 源码定位:L28
  • 修饰符:public

参数:

  • downloader: PackDownloader
  • packLoadFeedback: PackLoadFeedback
  • reloadConfig: PackReloadConfig
  • updateRequest: Runnable
  • packPromptStatus: ServerPackManager.PackPromptStatus

说明:

TODO

方法

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

private void registerForUpdate() @ L42

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

参数:

说明:

TODO

private void markExistingPacksAsRemoved(UUID id) @ L46

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

参数:

  • id: UUID

说明:

TODO

public void pushPack(UUID id, URL url, HashCode hash) @ L54

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

参数:

  • id: UUID
  • url: URL
  • hash: HashCode

说明:

TODO

public void pushLocalPack(UUID id, Path path) @ L62

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

参数:

  • id: UUID
  • path: Path

说明:

TODO

private void pushNewPack(UUID id, ServerPackManager.ServerPackData pack) @ L80

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

参数:

  • id: UUID
  • pack: ServerPackManager.ServerPackData

说明:

TODO

private void acceptPack(ServerPackManager.ServerPackData pack) @ L90

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

参数:

  • pack: ServerPackManager.ServerPackData

说明:

TODO

private ServerPackManager.ServerPackData findPackInfo(UUID id) @ L95

  • 方法名:findPackInfo
  • 源码定位:L95
  • 返回类型:ServerPackManager.ServerPackData
  • 修饰符:private

参数:

  • id: UUID

说明:

TODO

public void popPack(UUID id) @ L105

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

参数:

  • id: UUID

说明:

TODO

public void popAll() @ L113

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

参数:

说明:

TODO

public void allowServerPacks() @ L121

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

参数:

说明:

TODO

public void rejectServerPacks() @ L133

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

参数:

说明:

TODO

public void resetPromptStatus() @ L145

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

参数:

说明:

TODO

public void tick() @ L149

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

参数:

说明:

TODO

private void cleanupRemovedPacks() @ L158

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

参数:

说明:

TODO

private void onDownload(Collection<ServerPackManager.ServerPackData> data, DownloadQueue.BatchResult result) @ L175

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

参数:

  • data: Collection<ServerPackManager.ServerPackData>
  • result: DownloadQueue.BatchResult

说明:

TODO

private boolean updateDownloads() @ L202

  • 方法名:updateDownloads
  • 源码定位:L202
  • 返回类型:boolean
  • 修饰符:private

参数:

说明:

TODO

private void triggerReloadIfNeeded() @ L232

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

参数:

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class ServerPackManager {
    private final PackDownloader downloader;
    private final PackLoadFeedback packLoadFeedback;
    private final PackReloadConfig reloadConfig;
    private final Runnable updateRequest;
    private ServerPackManager.PackPromptStatus packPromptStatus;
    private final List<ServerPackManager.ServerPackData> packs = new ArrayList<>();
 
    public ServerPackManager(
        PackDownloader downloader,
        PackLoadFeedback packLoadFeedback,
        PackReloadConfig reloadConfig,
        Runnable updateRequest,
        ServerPackManager.PackPromptStatus packPromptStatus
    ) {
        this.downloader = downloader;
        this.packLoadFeedback = packLoadFeedback;
        this.reloadConfig = reloadConfig;
        this.updateRequest = updateRequest;
        this.packPromptStatus = packPromptStatus;
    }
 
    private void registerForUpdate() {
        this.updateRequest.run();
    }
 
    private void markExistingPacksAsRemoved(UUID id) {
        for (ServerPackManager.ServerPackData pack : this.packs) {
            if (pack.id.equals(id)) {
                pack.setRemovalReasonIfNotSet(ServerPackManager.RemovalReason.SERVER_REPLACED);
            }
        }
    }
 
    public void pushPack(UUID id, URL url, @Nullable HashCode hash) {
        if (this.packPromptStatus == ServerPackManager.PackPromptStatus.DECLINED) {
            this.packLoadFeedback.reportFinalResult(id, PackLoadFeedback.FinalResult.DECLINED);
        } else {
            this.pushNewPack(id, new ServerPackManager.ServerPackData(id, url, hash));
        }
    }
 
    public void pushLocalPack(UUID id, Path path) {
        if (this.packPromptStatus == ServerPackManager.PackPromptStatus.DECLINED) {
            this.packLoadFeedback.reportFinalResult(id, PackLoadFeedback.FinalResult.DECLINED);
        } else {
            URL url;
            try {
                url = path.toUri().toURL();
            } catch (MalformedURLException var5) {
                throw new IllegalStateException("Can't convert path to URL " + path, var5);
            }
 
            ServerPackManager.ServerPackData pack = new ServerPackManager.ServerPackData(id, url, null);
            pack.downloadStatus = ServerPackManager.PackDownloadStatus.DONE;
            pack.path = path;
            this.pushNewPack(id, pack);
        }
    }
 
    private void pushNewPack(UUID id, ServerPackManager.ServerPackData pack) {
        this.markExistingPacksAsRemoved(id);
        this.packs.add(pack);
        if (this.packPromptStatus == ServerPackManager.PackPromptStatus.ALLOWED) {
            this.acceptPack(pack);
        }
 
        this.registerForUpdate();
    }
 
    private void acceptPack(ServerPackManager.ServerPackData pack) {
        this.packLoadFeedback.reportUpdate(pack.id, PackLoadFeedback.Update.ACCEPTED);
        pack.promptAccepted = true;
    }
 
    private ServerPackManager.@Nullable ServerPackData findPackInfo(UUID id) {
        for (ServerPackManager.ServerPackData pack : this.packs) {
            if (!pack.isRemoved() && pack.id.equals(id)) {
                return pack;
            }
        }
 
        return null;
    }
 
    public void popPack(UUID id) {
        ServerPackManager.ServerPackData packInfo = this.findPackInfo(id);
        if (packInfo != null) {
            packInfo.setRemovalReasonIfNotSet(ServerPackManager.RemovalReason.SERVER_REMOVED);
            this.registerForUpdate();
        }
    }
 
    public void popAll() {
        for (ServerPackManager.ServerPackData pack : this.packs) {
            pack.setRemovalReasonIfNotSet(ServerPackManager.RemovalReason.SERVER_REMOVED);
        }
 
        this.registerForUpdate();
    }
 
    public void allowServerPacks() {
        this.packPromptStatus = ServerPackManager.PackPromptStatus.ALLOWED;
 
        for (ServerPackManager.ServerPackData pack : this.packs) {
            if (!pack.promptAccepted && !pack.isRemoved()) {
                this.acceptPack(pack);
            }
        }
 
        this.registerForUpdate();
    }
 
    public void rejectServerPacks() {
        this.packPromptStatus = ServerPackManager.PackPromptStatus.DECLINED;
 
        for (ServerPackManager.ServerPackData pack : this.packs) {
            if (!pack.promptAccepted) {
                pack.setRemovalReasonIfNotSet(ServerPackManager.RemovalReason.DECLINED);
            }
        }
 
        this.registerForUpdate();
    }
 
    public void resetPromptStatus() {
        this.packPromptStatus = ServerPackManager.PackPromptStatus.PENDING;
    }
 
    public void tick() {
        boolean downloadsPending = this.updateDownloads();
        if (!downloadsPending) {
            this.triggerReloadIfNeeded();
        }
 
        this.cleanupRemovedPacks();
    }
 
    private void cleanupRemovedPacks() {
        this.packs.removeIf(data -> {
            if (data.activationStatus != ServerPackManager.ActivationStatus.INACTIVE) {
                return false;
            } else if (data.removalReason != null) {
                PackLoadFeedback.FinalResult response = data.removalReason.serverResponse;
                if (response != null) {
                    this.packLoadFeedback.reportFinalResult(data.id, response);
                }
 
                return true;
            } else {
                return false;
            }
        });
    }
 
    private void onDownload(Collection<ServerPackManager.ServerPackData> data, DownloadQueue.BatchResult result) {
        if (!result.failed().isEmpty()) {
            for (ServerPackManager.ServerPackData pack : this.packs) {
                if (pack.activationStatus != ServerPackManager.ActivationStatus.ACTIVE) {
                    if (result.failed().contains(pack.id)) {
                        pack.setRemovalReasonIfNotSet(ServerPackManager.RemovalReason.DOWNLOAD_FAILED);
                    } else {
                        pack.setRemovalReasonIfNotSet(ServerPackManager.RemovalReason.DISCARDED);
                    }
                }
            }
        }
 
        for (ServerPackManager.ServerPackData packx : data) {
            Path packFile = result.downloaded().get(packx.id);
            if (packFile != null) {
                packx.downloadStatus = ServerPackManager.PackDownloadStatus.DONE;
                packx.path = packFile;
                if (!packx.isRemoved()) {
                    this.packLoadFeedback.reportUpdate(packx.id, PackLoadFeedback.Update.DOWNLOADED);
                }
            }
        }
 
        this.registerForUpdate();
    }
 
    private boolean updateDownloads() {
        List<ServerPackManager.ServerPackData> downloadPacks = new ArrayList<>();
        boolean downloadsInProgress = false;
 
        for (ServerPackManager.ServerPackData pack : this.packs) {
            if (!pack.isRemoved() && pack.promptAccepted) {
                if (pack.downloadStatus != ServerPackManager.PackDownloadStatus.DONE) {
                    downloadsInProgress = true;
                }
 
                if (pack.downloadStatus == ServerPackManager.PackDownloadStatus.REQUESTED) {
                    pack.downloadStatus = ServerPackManager.PackDownloadStatus.PENDING;
                    downloadPacks.add(pack);
                }
            }
        }
 
        if (!downloadPacks.isEmpty()) {
            Map<UUID, DownloadQueue.DownloadRequest> downloadRequests = new HashMap<>();
 
            for (ServerPackManager.ServerPackData packx : downloadPacks) {
                downloadRequests.put(packx.id, new DownloadQueue.DownloadRequest(packx.url, packx.hash));
            }
 
            this.downloader.download(downloadRequests, result -> this.onDownload(downloadPacks, result));
        }
 
        return downloadsInProgress;
    }
 
    private void triggerReloadIfNeeded() {
        boolean needsReload = false;
        final List<ServerPackManager.ServerPackData> packsToLoad = new ArrayList<>();
        final List<ServerPackManager.ServerPackData> packsToUnload = new ArrayList<>();
 
        for (ServerPackManager.ServerPackData pack : this.packs) {
            if (pack.activationStatus == ServerPackManager.ActivationStatus.PENDING) {
                return;
            }
 
            boolean shouldBeActive = pack.promptAccepted && pack.downloadStatus == ServerPackManager.PackDownloadStatus.DONE && !pack.isRemoved();
            if (shouldBeActive && pack.activationStatus == ServerPackManager.ActivationStatus.INACTIVE) {
                packsToLoad.add(pack);
                needsReload = true;
            }
 
            if (pack.activationStatus == ServerPackManager.ActivationStatus.ACTIVE) {
                if (!shouldBeActive) {
                    needsReload = true;
                    packsToUnload.add(pack);
                } else {
                    packsToLoad.add(pack);
                }
            }
        }
 
        if (needsReload) {
            for (ServerPackManager.ServerPackData pack : packsToLoad) {
                if (pack.activationStatus != ServerPackManager.ActivationStatus.ACTIVE) {
                    pack.activationStatus = ServerPackManager.ActivationStatus.PENDING;
                }
            }
 
            for (ServerPackManager.ServerPackData packx : packsToUnload) {
                packx.activationStatus = ServerPackManager.ActivationStatus.PENDING;
            }
 
            this.reloadConfig.scheduleReload(new PackReloadConfig.Callbacks() {
                {
                    Objects.requireNonNull(ServerPackManager.this);
                }
 
                @Override
                public void onSuccess() {
                    for (ServerPackManager.ServerPackData packx : packsToLoad) {
                        packx.activationStatus = ServerPackManager.ActivationStatus.ACTIVE;
                        if (packx.removalReason == null) {
                            ServerPackManager.this.packLoadFeedback.reportFinalResult(packx.id, PackLoadFeedback.FinalResult.APPLIED);
                        }
                    }
 
                    for (ServerPackManager.ServerPackData packx : packsToUnload) {
                        packx.activationStatus = ServerPackManager.ActivationStatus.INACTIVE;
                    }
 
                    ServerPackManager.this.registerForUpdate();
                }
 
                @Override
                public void onFailure(boolean isRecovery) {
                    if (!isRecovery) {
                        packsToLoad.clear();
 
                        for (ServerPackManager.ServerPackData packx : ServerPackManager.this.packs) {
                            switch (packx.activationStatus) {
                                case INACTIVE:
                                    packx.setRemovalReasonIfNotSet(ServerPackManager.RemovalReason.DISCARDED);
                                    break;
                                case PENDING:
                                    packx.activationStatus = ServerPackManager.ActivationStatus.INACTIVE;
                                    packx.setRemovalReasonIfNotSet(ServerPackManager.RemovalReason.ACTIVATION_FAILED);
                                    break;
                                case ACTIVE:
                                    packsToLoad.add(packx);
                            }
                        }
 
                        ServerPackManager.this.registerForUpdate();
                    } else {
                        for (ServerPackManager.ServerPackData packx : ServerPackManager.this.packs) {
                            if (packx.activationStatus == ServerPackManager.ActivationStatus.PENDING) {
                                packx.activationStatus = ServerPackManager.ActivationStatus.INACTIVE;
                            }
                        }
                    }
                }
 
                @Override
                public List<PackReloadConfig.IdAndPath> packsToLoad() {
                    return packsToLoad.stream().map(packx -> new PackReloadConfig.IdAndPath(packx.id, packx.path)).toList();
                }
            });
        }
    }
 
    @OnlyIn(Dist.CLIENT)
    private static enum ActivationStatus {
        INACTIVE,
        PENDING,
        ACTIVE;
    }
 
    @OnlyIn(Dist.CLIENT)
    private static enum PackDownloadStatus {
        REQUESTED,
        PENDING,
        DONE;
    }
 
    @OnlyIn(Dist.CLIENT)
    public static enum PackPromptStatus {
        PENDING,
        ALLOWED,
        DECLINED;
    }
 
    @OnlyIn(Dist.CLIENT)
    private static enum RemovalReason {
        DOWNLOAD_FAILED(PackLoadFeedback.FinalResult.DOWNLOAD_FAILED),
        ACTIVATION_FAILED(PackLoadFeedback.FinalResult.ACTIVATION_FAILED),
        DECLINED(PackLoadFeedback.FinalResult.DECLINED),
        DISCARDED(PackLoadFeedback.FinalResult.DISCARDED),
        SERVER_REMOVED(null),
        SERVER_REPLACED(null);
 
        private final PackLoadFeedback.@Nullable FinalResult serverResponse;
 
        private RemovalReason(PackLoadFeedback.@Nullable FinalResult serverResponse) {
            this.serverResponse = serverResponse;
        }
    }
 
    @OnlyIn(Dist.CLIENT)
    private static class ServerPackData {
        private final UUID id;
        private final URL url;
        private final @Nullable HashCode hash;
        private @Nullable Path path;
        private ServerPackManager.@Nullable RemovalReason removalReason;
        private ServerPackManager.PackDownloadStatus downloadStatus = ServerPackManager.PackDownloadStatus.REQUESTED;
        private ServerPackManager.ActivationStatus activationStatus = ServerPackManager.ActivationStatus.INACTIVE;
        private boolean promptAccepted;
 
        private ServerPackData(UUID id, URL url, @Nullable HashCode hash) {
            this.id = id;
            this.url = url;
            this.hash = hash;
        }
 
        public void setRemovalReasonIfNotSet(ServerPackManager.RemovalReason removalReason) {
            if (this.removalReason == null) {
                this.removalReason = removalReason;
            }
        }
 
        public boolean isRemoved() {
            return this.removalReason != null;
        }
    }
}

引用的其他类

  • PackDownloader

    • 引用位置: 参数/字段
  • PackLoadFeedback

    • 引用位置: 参数/字段
  • PackReloadConfig

    • 引用位置: 参数/字段/方法调用/构造调用
    • 关联成员: Callbacks(), IdAndPath(), PackReloadConfig.Callbacks(), PackReloadConfig.IdAndPath()
  • DownloadQueue

    • 引用位置: 参数/方法调用/构造调用
    • 关联成员: DownloadQueue.DownloadRequest(), DownloadRequest()