2015-11-13 78 views
-2

我正在研究一個minigames插件。競技場完成後應該重新生成 - 我使用卸載和加載技巧。它有一個明顯的缺點 - 它凍結了服務器一段時間來準備出生區域。我決定將舞臺重置代碼放入可運行的異步任務runTaskAsynchronously()。但是,當服務器嘗試運行的線程裏面的代碼,它拋出一個異常:異步加載一個世界或不阻塞主線程

Caused by: java.lang.IllegalStateException: Asynchronous entity world add! 

這裏是我的代碼的一部分:

getServer().getScheduler().runTaskAsynchronously(this, new Runnable() 
{ 
    @Override 
    public void run() 
    { 
     String w_name = world.getName(); 
     getServer().unloadWorld(world.getName(), false); 
     world = getServer().createWorld(new WorldCreator(w_name)); 
    } 
}); 

任何建議如何處理這個問題?

+0

你已經發布了一個例外,但它並沒有給我們一個關於你的問題是什麼 – ControlAltDel

+0

看起來像minigames框架不希望你在另一個線程重置競技場,可能是因爲它沒有妥善處理。 –

+0

根據Bukkit調度程序編程wiki,異步任務不應該訪問Bukkit中的任何API。 –

回答

1

當您嘗試在異步任務中通過API編輯任何內容時,Bukkit不喜歡它。閱讀和處理是很好的,但是當涉及到線程安全並且因此影響世界並且多於一個線程會導致問題時,bukkit不會執行任何操作。

嘗試將您的舞臺重新設置爲更小的塊,並通過一系列同步任務將操作分散到幾個刻度上,可能有助於提高性能。

這不是我的代碼,但它確實表明了想法https://gist.github.com/aadnk/5443172

0

的一份體面的工作 - 您可以載入世界異步使用此:http://pastebin.com/K9CuVMS5 -

,你不行,如果你試過它會有很高的世界腐敗機會。但是,如果你不關心它,這是你可以做什麼:通過Bukkit.createWorld(WorldCreator)激活Server.createWorld(WorldCreator)激活 Bukkit負荷的世界:

Validate.notNull(creator, "Creator may not be null"); 
    String name = creator.name(); 
    ChunkGenerator generator = creator.generator(); 
    File folder = new File(this.getWorldContainer(), name); 
    World world = this.getWorld(name); 
    WorldType type = WorldType.getType(creator.type().getName()); 
    boolean generateStructures = creator.generateStructures(); 
    if(world != null) { 
     return world; 
    } else if(folder.exists() && !folder.isDirectory()) { 
     throw new IllegalArgumentException("File exists with the name \'" + name + "\' and isn\'t a folder"); 
    } else { 
     if(generator == null) { 
      generator = this.getGenerator(name); 
     } 

     WorldLoaderServer converter = new WorldLoaderServer(this.getWorldContainer()); 
     if(converter.isConvertable(name)) { 
      this.getLogger().info("Converting world \'" + name + "\'"); 
      converter.convert(name, new ConvertProgressUpdater(this.console)); 
     } 

     int dimension = 10 + this.console.worlds.size(); 
     boolean used = false; 

     do { 
      Iterator sdm = this.console.worlds.iterator(); 

      while(sdm.hasNext()) { 
       WorldServer hardcore = (WorldServer)sdm.next(); 
       used = hardcore.dimension == dimension; 
       if(used) { 
        ++dimension; 
        break; 
       } 
      } 
     } while(used); 

     boolean var25 = false; 
     ServerNBTManager var24 = new ServerNBTManager(this.getWorldContainer(), name, true); 
     WorldData worlddata = var24.getWorldData(); 
     if(worlddata == null) { 
      WorldSettings internal = new WorldSettings(creator.seed(), EnumGamemode.getById(this.getDefaultGameMode().getValue()), generateStructures, var25, type); 
      internal.setGeneratorSettings(creator.generatorSettings()); 
      worlddata = new WorldData(internal, name); 
     } 

     worlddata.checkName(name); 
     WorldServer var26 = (WorldServer)(new WorldServer(this.console, var24, worlddata, dimension, this.console.methodProfiler, creator.environment(), generator)).b(); 
     if(!this.worlds.containsKey(name.toLowerCase())) { 
      return null; 
     } else { 
      var26.scoreboard = this.getScoreboardManager().getMainScoreboard().getHandle(); 
      var26.tracker = new EntityTracker(var26); 
      var26.addIWorldAccess(new WorldManager(this.console, var26)); 
      var26.worldData.setDifficulty(EnumDifficulty.EASY); 
      var26.setSpawnFlags(true, true); 
      this.console.worlds.add(var26); 
      if(generator != null) { 
       var26.getWorld().getPopulators().addAll(generator.getDefaultPopulators(var26.getWorld())); 
      } 

      this.pluginManager.callEvent(new WorldInitEvent(var26.getWorld())); 
      System.out.print("Preparing start region for level " + (this.console.worlds.size() - 1) + " (Seed: " + var26.getSeed() + ")"); 
      if(var26.getWorld().getKeepSpawnInMemory()) { 
       short short1 = 196; 
       long i = System.currentTimeMillis(); 

       for(int j = -short1; j <= short1; j += 16) { 
        for(int k = -short1; k <= short1; k += 16) { 
         long l = System.currentTimeMillis(); 
         if(l < i) { 
          i = l; 
         } 

         if(l > i + 1000L) { 
          int chunkcoordinates = (short1 * 2 + 1) * (short1 * 2 + 1); 
          int j1 = (j + short1) * (short1 * 2 + 1) + k + 1; 
          System.out.println("Preparing spawn area for " + name + ", " + j1 * 100/chunkcoordinates + "%"); 
          i = l; 
         } 

         BlockPosition var27 = var26.getSpawn(); 
         var26.chunkProviderServer.getChunkAt(var27.getX() + j >> 4, var27.getZ() + k >> 4); 
        } 
       } 
      } 

      this.pluginManager.callEvent(new WorldLoadEvent(var26.getWorld())); 
      return var26.getWorld(); 
     } 
    } 

現在通過創建你自己的世界裝載器,你可以把它所以只每個勾號都會生成一個塊。