2015-11-13 42 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(); 
     } 
    } 

现在通过创建你自己的世界装载器,你可以把它所以只每个勾号都会生成一个块。