<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 世界數據存儲? ? 若問題歡迎討論,感謝閱讀! * * * 官方教程([教程:global\_data \[面料百科\] (fabricmc.net)](https://fabricmc.net/wiki/tutorial:global_data))并沒講具體如何存儲數據數據,不過看了原版后也容易寫出,在此將教你保存世界數據(**注意,這些操作幾乎是在服務端完成的**)。 ## PersistentState 游戲每個世界中的數據是通過`PersistentState`保存的,該世界存檔中保存的數據(\*.dat)可以在游戲目錄下`saves\[world]\data`文件夾看到,其中的文件都對應了一個`PersistentState`對象(如計分板的`ScoreboardState`類),這些類會實現“fromTag”和“toTag”方法來完成數據的解析與生成。接下來讓我們編寫自己的`PersistentState`類吧! 樣例: ``` public class ExampleState extends PersistentState { ? ?? ???private static final Logger LOGGER = LogManager.getLogger(); ? ?? ???private ExampleObject object; ? ?? ???public ExampleState() { ? ?? ?? ?? ?? ? super("example"); ? ?? ???} ? ?? ???public void setObject(ExampleObject object) { ? ?? ?? ?? ?? ? this.object = object; ? ?? ???} ? ?? ???public ExampleObject getObject() { ? ?? ?? ?? ?? ? return object; ? ?? ???} ? ?? ???public void fromTag(CompoundTag tag) { ? ?? ?? ?? ?? ? object.fromTag(tag.getCompound("ExampleData")); ? ?? ???} ? ?? ???public CompoundTag toTag(CompoundTag tag) { ? ?? ?? ?? ?? ? if(this.handler == null) { ? ?? ?? ?? ?? ?? ?? ?? ?LOGGER.warn("無法保存未創建的存儲對象。"); ? ?? ?? ?? ?? ? } else { ? ?? ?? ?? ?? ?? ?? ?? ?tag.put("ExampleData", object.toTag()); ? ?? ?? ?? ?? ? } ? ?? ?? ?? ?? ? return tag; ? ?? ???} } ``` * 在對應功能的包下創建一個類并繼承 net.minecraft.world.PersistentState 類,類名為 記錄對象+“State”(如“ScoreboardState”); * 添加構造器,調用父構造器傳入字符串 key,以小寫駝峰式命名(如“scoreboard”),該參數將用作數據文件的文件名; * 添加被存儲對象成員,并實現“get”與“set”方法;(其實原版 ScoreboardState 里并無“get”方法,是通過服務器的成員方法獲取計分板的,這里只是為了獲取方便) * 實現“public void fromTag(CompoundTag tag)”和“public CompoundTag toTag(CompoundTag tag)”方法,這是該類的核心方法,分別對應數據的讀入和寫出,一般會間接調用存儲對象的“fromTag”和“toTag”方法; * 如果需要,可以創建一個 Logger 記錄錯誤。 完成后,存儲對象還需要注意下,為減少不必要的負擔,防止該對象未更新數據而再次保存,需要實現`void addUpdateListener(Runnable listener)`并加入一個`Synchronizer`監聽數據更改,稍等你將會用到它們,此外實現`void runUpdateListeners()`并在更新數據后調用。 樣例: ``` //存儲對象類 private Runnable[] updateListeners = new Runnable[0]; public void addUpdateListener(Runnable listener) { ? ?? ???this.updateListeners = Arrays.copyOf(this.updateListeners, this.updateListeners.length + ); ? ?? ???this.updateListeners[this.updateListeners.length - 1] = listener; } protected void runUpdateListeners() { ? ?? ???Runnable[] var1 = this.updateListeners; ? ?? ???for(Runnable runnable : var1) { ? ?? ?? ?? ?? ? runnable.run(); ? ?? ???} } ``` ``` public class ExampleSynchronizer implements Runnable { ? ?? ???private final PersistentState compound; ? ?? ???public ExampleSynchronizer(PersistentState compound) { ? ?? ?? ?? ?? ? this.compound = compound; ? ?? ???} ? ?? ???public void run() { ? ?? ?? ?? ?? ? this.compound.markDirty(); ? ?? ???} } ``` * `addUpdateListener()`:向存儲對象添加數據更新監聽器; * `runUpdateListeners()`:數據更新后調用,將執行已添加的監聽器動作; * `Synchronizer`:以 存儲對象+“Synchronizer” 命名,用來標記已更改的數據(原理:每個 PersistentState 都有`dirty`成員標記數據是否更改,在保存時會判斷該`dirty`是否為`ture`)。 接下來將教你將該 PersistentState 類加入到服務器中。 ## PersistentStateManager 官方教程中講到數據是按維度(代碼中是`World`,使用`DimensionType`辨別維度)保存的,即每個維度都有自己的數據管理器——`PersistentStateManager`,我們可以使用`serverWorld.getPersistentStateManager()`獲得 ,其中使用一個 map 存儲著各個`PersistentState`,會在創建與保存時分別調用`PersistentState`的“fromTag”和“toTag”方法,我們可以在創建維度時使用`persistentStateManager.getOrCreate(Supplier factory, String id)`創建自己的`PersistentState`。接下來我們將使用 Mixin 向`MinecraftServer`中注入我們的代碼。 樣例: ``` @Mixin(MinecraftServer.class) public abstract class MinecraftServerMixin { ? ?? ???private ExampleObject object; ? ?? ???@Inject(method = "(Ljava/io/File;Ljava/net/Proxy;Lcom/mojang/datafixers/DataFixer;Lnet/minecraft/server/command/CommandManager;Lcom/mojang/authlib/yggdrasil/YggdrasilAuthenticationService;Lcom/mojang/authlib/minecraft/MinecraftSessionService;Lcom/mojang/authlib/GameProfileRepository;Lnet/minecraft/util/UserCache;Lnet/minecraft/server/WorldGenerationProgressListenerFactory;Ljava/lang/String;)V", at = @At(value = "RETURN")) ? ?? ???private void initExampleObject(File gameDir, Proxy proxy, DataFixer dataFixer, CommandManager commandManager, YggdrasilAuthenticationService authService, MinecraftSessionService sessionService, GameProfileRepository gameProfileRepository, UserCache userCache, WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, String levelName, CallbackInfo ci) { ? ?? ?? ?? ?? ? this.object = new ExampleObject(); ? ?? ???} ? ?? ???private void initExampleObject(PersistentStateManager persistentStateManager) { ? ?? ?? ?? ?? ? ExampleState exampleState = persistentStateManager.getOrCreate(ExampleState::new, "example"); ? ?? ?? ?? ?? ? exampleState.setObject(object); ? ?? ?? ?? ?? ? object.addUpdateListener(new ExampleSynchronizer(exampleState)); ? ?? ???} ? ?? ???@Inject(method = "createWorlds(Lnet/minecraft/world/WorldSaveHandler;Lnet/minecraft/world/level/LevelProperties;Lnet/minecraft/world/level/LevelInfo;Lnet/minecraft/server/WorldGenerationProgressListener;)V", at = @At(value = "TAIL"), locals = LocalCapture.CAPTURE\_FAILHARD) ? ?? ???private void createTemperatureState(WorldSaveHandler worldSaveHandler, LevelProperties properties, LevelInfo levelInfo, WorldGenerationProgressListener worldGenerationProgressListener, CallbackInfo ci, ServerWorld serverWorld, ersistentStateManager persistentStateManager) { ? ?? ?? ?? ?? ? this.initExampleObject(persistentStateManager); ? ?? ???} } ``` * 在服務器被創建時,初始化存儲對象; * 在創建世界時,向某維度中的 persistentStateManager 創建你的 PersistentState,設置存儲對象并對存儲對象添加數據更新監聽器(Synchronizer),注意,這里注入時捕獲其中的局部變量 persistentStateManager 是主世界的,若要在其他維度創建,請使用 this.getWorld(dimensionType).getPersistentStateManager() 獲取對應維度的 persistentStateManager。 完成后,我們將學習如何在其它地方獲取存儲對象對其修改。 ## 獲取存儲對象 向 persistentStateManager 添加 PersistentState 后,我們應如何獲取我們的存儲對象?前面說到為了方便獲取存儲對象,在我們的 PersistentState 類中加入的“get”方法來獲取存儲對象,而已創建的 PersistentState 對象可以通過 persistentStateManager 的 get(Supplier factory, String id) 方法獲取,因此可以寫出以下代碼: ``` MinecraftClient.getInstance().getServer().getWorld(DimensionType.OVERWORLD).getPersistentStateManager().get(ExampleState::new, "example").getObject() ``` * 通過 MinecraftClient 類的靜態方法 getInstance() 獲取客戶端的游戲實例; * 使用 getServer() 方法獲取服務端對象; * 使用 getWorld(DimensionType) 獲取對應維度,若已有 ServerWorld 對象此前步驟可以跳過; * 使用 getPersistentStateManager() 獲取該維度的 persistentStateManager 并獲取我們創建的 PersistentState 對象; * 通過 PersistentState 中的“get”方法獲取被存儲對象,即可對之修改。 * * * 完成后,趕快進入游戲測試吧!若成功你將在游戲目錄(或開發環境的“run”目錄)下`saves\[world]\data`文件夾看到你的數據文件,如果在 IDEA 安裝的 MinecraftDev 插件,你可以方便地查看或編寫這些數據文件。編寫不易,你的支持是我最大的動力!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看