/* * IDK Game Server by Steve Winfield * https://github.com/WinfieldSteve */ package org.stevewinfield.suja.idk.game.rooms.tasks; import org.magicwerk.brownies.collections.GapList; import org.stevewinfield.suja.idk.Bootloader; import org.stevewinfield.suja.idk.communication.MessageWriter; import org.stevewinfield.suja.idk.communication.room.writers.RoomPlayerStatusListWriter; import org.stevewinfield.suja.idk.game.miscellaneous.ChatMessage; import org.stevewinfield.suja.idk.game.rooms.RoomInstance; import org.stevewinfield.suja.idk.game.rooms.RoomItem; import org.stevewinfield.suja.idk.game.rooms.RoomPlayer; import org.stevewinfield.suja.idk.game.rooms.coordination.Vector2; import org.stevewinfield.suja.idk.game.rooms.tasks.games.BattleBanzaiTask; import org.stevewinfield.suja.idk.game.rooms.wired.WiredDelayEvent; import org.stevewinfield.suja.idk.threadpools.ServerTask; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledFuture; public class RoomTask extends ServerTask { private final RoomInstance room; private int updates; private int emptyRoomCounter; private final Queue<RoomPlayer> playersToAdd; private final Queue<RoomPlayer> playersToRemove; private final Queue<MessageWriter> roomMessageWriters; private final Queue<ChatMessage> chatMessages; private final Queue<RoomItem> itemCycleRequests; private final Queue<WiredDelayEvent> wiredItemDelay; private ScheduledFuture<?> scheduledFuture; private final GameTask banzaiTask; private boolean canceled; public RoomTask(final RoomInstance room) { this.room = room; this.playersToAdd = new ArrayBlockingQueue<>(1024); this.playersToRemove = new ArrayBlockingQueue<>(1024); this.roomMessageWriters = new ArrayBlockingQueue<>(1024); this.chatMessages = new ArrayBlockingQueue<>(1024); this.itemCycleRequests = new ArrayBlockingQueue<>(1024); this.wiredItemDelay = new ArrayBlockingQueue<>(1024); this.updates = 0; this.emptyRoomCounter = 0; this.canceled = false; this.banzaiTask = new BattleBanzaiTask(room); } public void offerRoomPlayerAdd(final RoomPlayer player) { this.playersToAdd.offer(player); } public void offerWiredItemDelay(final WiredDelayEvent item) { this.wiredItemDelay.offer(item); } public GameTask getBanzaiTask() { return banzaiTask; } public boolean isCanceled() { return canceled; } public void setCanceled(final boolean c) { this.canceled = c; } public void offerChatMessageAdd(final ChatMessage message) { this.chatMessages.offer(message); } public void offerRoomPlayerRemove(final RoomPlayer player) { this.playersToRemove.offer(player); } public void offerRoomMessageWriter(final MessageWriter writer) { this.roomMessageWriters.offer(writer); } public void offerItemCycle(final RoomItem item) { this.itemCycleRequests.offer(item); } public void setScheduledFuture(final ScheduledFuture<?> scheduledFuture) { this.scheduledFuture = scheduledFuture; } @Override public void run() { if (this.canceled) { if (this.scheduledFuture == null) { return; } for (final RoomPlayer player : this.room.getRoomPlayers().values()) { if (player.getSession() != null) { room.removePlayerFromRoom(player.getSession(), true, false); } } this.scheduledFuture.cancel(true); room.getInformation().totalPlayers = 0; Bootloader.getGame().getNavigatorListManager().setRoom(room.getInformation(), 0, true); Bootloader.getGame().getRoomManager().removeLoadedRoomInstance(room.getInformation().getId()); return; } if (this.emptyRoomCounter >= 60) { this.room.save(); this.canceled = true; this.emptyRoomCounter = 0; return; } if (this.room.getInformation().getTotalPlayers() == 0) { this.emptyRoomCounter++; } final GapList<MessageWriter> messages = new GapList<>(); final List<RoomPlayer> updatedPlayers = new GapList<>(); final ConcurrentHashMap<Vector2, Integer> setTileStates = new ConcurrentHashMap<>(); for (final RoomPlayer player : room.getRoomPlayers().values()) { player.onCycle(setTileStates); if (player.needsUpdate()) { updatedPlayers.add(player); player.setUpdateNeeded(false); } } for (final Map.Entry<Vector2, Integer> tileState : setTileStates.entrySet()) { this.room.getGamemap().updateTile(tileState.getKey(), tileState.getValue()); } while (!this.chatMessages.isEmpty()) { this.room.onPlayerChat(this.chatMessages.poll()); } final List<RoomItem> toCycle = new GapList<>(); while (!itemCycleRequests.isEmpty()) { toCycle.add(itemCycleRequests.poll()); } for (final RoomItem item : toCycle) { item.onCycle(); } while (!this.roomMessageWriters.isEmpty()) { messages.add(this.roomMessageWriters.poll()); } if (updatedPlayers.size() > 0) { messages.add(new RoomPlayerStatusListWriter(updatedPlayers)); } while (!this.playersToRemove.isEmpty()) { final RoomPlayer player = this.playersToRemove.poll(); this.room.getRoomPlayers().remove(player.getVirtualId()); this.room.onPlayerLeaves(player); } if (messages.size() > 0) { for (final RoomPlayer player : this.room.getRoomPlayers().values()) { if (player.isBot()) { continue; } for (final MessageWriter message : messages) { if (message.getSenderId() < 1 || player.getSession().getId() != message.getSenderId()) { player.getSession().writeMessage(message); } } } } while (!this.playersToAdd.isEmpty()) { final RoomPlayer player = this.playersToAdd.poll(); this.room.getRoomPlayers().put(player.getVirtualId(), player); this.room.onPlayerEnters(player); } room.getWiredHandler().onTriggerPeriodically(); final GapList<WiredDelayEvent> reAdd = new GapList<>(); while (!this.wiredItemDelay.isEmpty()) { final WiredDelayEvent delayEvent = this.wiredItemDelay.poll(); delayEvent.getAction().onHandle(delayEvent.getPlayer(), delayEvent); if (!delayEvent.isFinished()) { reAdd.add(delayEvent); } } for (final WiredDelayEvent delay : reAdd) { this.wiredItemDelay.offer(delay); } if (this.updates == 0 || this.updates == 3) { Bootloader.getGame().getNavigatorListManager().setRoom(room.getInformation(), room.getInformation().getTotalPlayers()); this.updates = 0; } this.updates++; } }