2015-03-01 4 views
0

Я получаю StackOverflowError при использовании рекурсивного метода. Я строю поверх API Spigot.StackOverflowError по рекурсивному методу

Это мой метод:

private Location spawnPlayer(Player p) { 
    int r = new Random().nextInt(ServerManager.getInstance().getServer(p).getSpawns().size()); 
    final Spawn s = ServerManager.getInstance().getServer(p).getSpawns().get(r); 

    if (s.hasPlayer()) { 
     spawnPlayer(p); 
    } else { 
     s.setPlayer(p); 

     Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(Arsenal.p, new Runnable() { 
      public void run() { 
       spawnClear--; 

       if (spawnClear == 0) { 
        s.setPlayer(null); 
       } 
      } 
     }, 0L, 20L); 
    } 
    return s.getLocation(); 
} 

Я получаю ошибку при spawnPlayer(p), которая называет себя, если порождение уже есть игрок.

+2

Мы понятия не имеем, что такое «ServerManager»? Что это метод 'getInstance()' дает. Что такое 'Spawn', что такое' Bukket'? Ну, в этом коде есть так много неизвестных. –

+0

@RohitJain Я считаю, что это modecraft server mod (mod framework?). – childofsoong

+0

Я бы посоветовал создать новый экземпляр «Случайный» в каждом вызове метода, хотя я не думаю, что это причина бесконечной рекурсии. Попробуйте создать один экземпляр «Случайный» вне метода и сохранить его в члене вашего класса. – Eran

ответ

1

Похоже s.hasPlayer() всегда верно, что делает это так:

if(s.hasPlayer()){ 
    spawnPlayer(p); 
} 

запускается на выполнение внутри spawnPlayer(Player) метода, который для них вызывает метод бежать бесконечно, в результате чего StackOverflowError.

Чтобы исправить это, вы могли бы подождать до вызова spawnPlayer(p):

if(s.hasPlayer()){ 
    long timeToWait = 20L;//set the time to wait to 20 ticks (1 second) 
    Bukkit.getServer().getScheduler().runTaskLater(Arsenal.p, new Runnable(){ 
     public void run(){ 
      spawnPlayer(p); 
     } 
    },timeToWait); 
} 

Итак, вот что ваш код может выглядеть следующим образом:

private Location spawnPlayer(Player p) { 
    int r = new Random().nextInt(ServerManager.getInstance().getServer(p).getSpawns().size()); 
    final Spawn s = ServerManager.getInstance().getServer(p).getSpawns().get(r); 

    if(s.hasPlayer()){ 
     long timeToWait = 20L;//set the time to wait to 20 ticks (1 second) 
     Bukkit.getServer().getScheduler().runTaskLater(Arsenal.p, new Runnable(){ 
      public void run(){ 
       spawnPlayer(p); 
      } 
     },timeToWait); 
    } 
    else{ 
     s.setPlayer(p); 

     Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(Arsenal.p, new Runnable() { 
      public void run() { 
       spawnClear--; 

       if (spawnClear == 0) { 
        s.setPlayer(null); 
       } 
      } 
     }, 0L, 20L); 
    } 
    return s.getLocation(); 
} 

Другое затруднительное бы сделать это так s.hasPlayer() не всегда например, используя ArrayList, чтобы убедиться, что игрок еще не был порожден:

List<String> spawned = new ArrayList<String>(); 

private Location spawnPlayer(Player p){ 
    int r = new Random().nextInt(ServerManager.getInstance().getServer(p).getSpawns().size()); 
    final Spawn s = ServerManager.getInstance().getServer(p).getSpawns().get(r); 

    if(s.hasPlayer() && !spawned.contains(p.getName()){ 
     spawned.add(p.getName()); 
     spawnPlayer(p); 
    } 
    else{ 
    //the rest of your code... 
    } 
} 
+0

Благодарим вас за помощь. Когда игра начинается, игрок назначается на икру и сразу же удаляется, что означает, что hasPlayer возвращает значение null. Я просто хочу избежать появления игроков на той же самой точке появления на карте. – Indy

+0

В этом случае вы можете просто составить список всех уже используемых икр, а затем только порождать их в икру, если это место отсутствует в списке. – Jojodmo

+0

Большое спасибо! Я собираюсь создать ArrayList из неиспользуемых нерестит и выбрать случайную икру из этого. Затем я снова добавлю спавну через три секунды и поставлю игрока на нуль. – Indy

0

Я не уверен, но логически я думаю, что вы хотите:

if (!s.hasPlayer()) { 
    spawnPlayer(p); 

Примечание к!.

В целом, обратите внимание на рекурсивные функции в minecraft :) После того, как я написал один, который превратил бы дерево в журналы, но в итоге он перевернул листья - взрыв был довольно впечатляющим - уничтожил весь форрест и убил моего клиента из-за всей активности.

+0

Благодарим вас за ответ. Однако я хочу повторно выполнить метод, если у икры нет игрока, поэтому генерируется новый случай. – Indy

Смежные вопросы