From 5315b7bf875b96de525d839a91ee0c9c4da5035e Mon Sep 17 00:00:00 2001 From: Chris Kearney <chris@kearneymail.com> Date: Mon, 8 Aug 2016 21:09:12 -0700 Subject: [PATCH] fixes --- .../com/comandante/creeper/CreeperEvent.java | 5 ++ .../SingleThreadedCreeperEventProcessor.java | 47 +++++++++++++++++++ .../creeper/managers/GameManager.java | 8 ++++ .../java/com/comandante/creeper/npc/Npc.java | 2 +- .../com/comandante/creeper/player/Player.java | 12 +++-- .../creeper/spawner/NpcSpawner.java | 44 +++++++++-------- 6 files changed, 93 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/comandante/creeper/CreeperEvent.java create mode 100644 src/main/java/com/comandante/creeper/SingleThreadedCreeperEventProcessor.java diff --git a/src/main/java/com/comandante/creeper/CreeperEvent.java b/src/main/java/com/comandante/creeper/CreeperEvent.java new file mode 100644 index 00000000..a50a8fdc --- /dev/null +++ b/src/main/java/com/comandante/creeper/CreeperEvent.java @@ -0,0 +1,5 @@ +package com.comandante.creeper; + +public interface CreeperEvent { + void run(); +} diff --git a/src/main/java/com/comandante/creeper/SingleThreadedCreeperEventProcessor.java b/src/main/java/com/comandante/creeper/SingleThreadedCreeperEventProcessor.java new file mode 100644 index 00000000..7aaca477 --- /dev/null +++ b/src/main/java/com/comandante/creeper/SingleThreadedCreeperEventProcessor.java @@ -0,0 +1,47 @@ +package com.comandante.creeper; + +import com.google.api.client.util.Lists; +import com.google.common.util.concurrent.AbstractScheduledService; +import org.apache.log4j.Logger; + +import java.util.ArrayList; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; + +public class SingleThreadedCreeperEventProcessor extends AbstractScheduledService { + + private final ArrayBlockingQueue<CreeperEvent> creeperEventQueue; + private static final Logger log = Logger.getLogger(SingleThreadedCreeperEventProcessor.class); + + public SingleThreadedCreeperEventProcessor(ArrayBlockingQueue<CreeperEvent> creeperEventQueue) { + this.creeperEventQueue = creeperEventQueue; + } + + @Override + protected void runOneIteration() throws Exception { + ArrayList<CreeperEvent> events = Lists.newArrayList(); + creeperEventQueue.drainTo(events); + events.forEach(this::safeRun); + } + + public void addEvent(CreeperEvent event) { + try { + creeperEventQueue.put(event); + } catch (InterruptedException ex) { + log.error("Problem adding event.", ex); + } + } + + private void safeRun(final CreeperEvent e) { + try { + e.run(); + } catch (Exception ex) { + log.error("Problem executing event.", ex); + } + } + + @Override + protected Scheduler scheduler() { + return Scheduler.newFixedDelaySchedule(0, 50, TimeUnit.MILLISECONDS); + } +} diff --git a/src/main/java/com/comandante/creeper/managers/GameManager.java b/src/main/java/com/comandante/creeper/managers/GameManager.java index 743f940f..5a263378 100755 --- a/src/main/java/com/comandante/creeper/managers/GameManager.java +++ b/src/main/java/com/comandante/creeper/managers/GameManager.java @@ -5,6 +5,7 @@ import com.comandante.creeper.CreeperConfiguration; import com.comandante.creeper.IrcBotService; import com.comandante.creeper.Items.*; import com.comandante.creeper.Main; +import com.comandante.creeper.SingleThreadedCreeperEventProcessor; import com.comandante.creeper.bot.BotCommandFactory; import com.comandante.creeper.bot.BotCommandManager; import com.comandante.creeper.entity.CreeperEntity; @@ -37,6 +38,7 @@ import org.nocrala.tools.texttablefmt.Table; import java.text.NumberFormat; import java.util.*; +import java.util.concurrent.ArrayBlockingQueue; import static com.comandante.creeper.server.Color.*; @@ -67,6 +69,7 @@ public class GameManager { private final TimeTracker timeTracker; private final ItemUseHandler itemUseHandler; private final NpcMover npcMover; + private final SingleThreadedCreeperEventProcessor eventProcessor = new SingleThreadedCreeperEventProcessor(new ArrayBlockingQueue<>(100000)); public GameManager(CreeperConfiguration creeperConfiguration, RoomManager roomManager, PlayerManager playerManager, EntityManager entityManager, MapsManager mapsManager, ChannelCommunicationUtils channelUtils) { this.roomManager = roomManager; @@ -92,6 +95,7 @@ public class GameManager { this.entityManager.addEntity(itemDecayManager); this.itemUseHandler = new ItemUseHandler(this); this.npcMover = new NpcMover(this); + this.eventProcessor.startAsync(); } public NpcMover getNpcMover() { @@ -166,6 +170,10 @@ public class GameManager { return timeTracker; } + public SingleThreadedCreeperEventProcessor getEventProcessor() { + return eventProcessor; + } + public void placePlayerInLobby(Player player) { Room room = roomManager.getRoom(LOBBY_ID); room.addPresentPlayer(player.getPlayerId()); diff --git a/src/main/java/com/comandante/creeper/npc/Npc.java b/src/main/java/com/comandante/creeper/npc/Npc.java index c79b4912..76a630d4 100644 --- a/src/main/java/com/comandante/creeper/npc/Npc.java +++ b/src/main/java/com/comandante/creeper/npc/Npc.java @@ -244,8 +244,8 @@ public class Npc extends CreeperEntity { long xpEarned = (long) (experienceManager.calculateNpcXp(playerLevel, npcLevel) * playerDamagePercentValue); p.addExperience(xpEarned); - p.addNpcKillLog(getName()); gameManager.getChannelUtils().write(p.getPlayerId(), getBattleReport(xpEarned) + "\r\n", true); + p.addNpcKillLog(getName()); } } diff --git a/src/main/java/com/comandante/creeper/player/Player.java b/src/main/java/com/comandante/creeper/player/Player.java index 5a017253..24a16bac 100755 --- a/src/main/java/com/comandante/creeper/player/Player.java +++ b/src/main/java/com/comandante/creeper/player/Player.java @@ -362,11 +362,13 @@ public class Player extends CreeperEntity { } public void addNpcKillLog(String npcName) { - synchronized (interner.intern(playerId)) { - PlayerMetadata playerMetadata = getPlayerMetadata(); - playerMetadata.addNpcKill(npcName); - savePlayerMetadata(playerMetadata); - } + gameManager.getEventProcessor().addEvent(() -> { + synchronized (interner.intern(playerId)) { + PlayerMetadata playerMetadata = getPlayerMetadata(); + playerMetadata.addNpcKill(npcName); + savePlayerMetadata(playerMetadata); + } + }); } public void transferItemFromLocker(String entityId) { diff --git a/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java b/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java index 07b99089..b479ec54 100755 --- a/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java +++ b/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java @@ -9,13 +9,12 @@ import com.comandante.creeper.npc.Npc; import com.comandante.creeper.npc.NpcBuilder; import com.comandante.creeper.world.Area; import com.comandante.creeper.world.Room; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterators; -import com.google.common.collect.Lists; -import java.util.ArrayList; +import java.util.List; import java.util.Random; import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; public class NpcSpawner extends CreeperEntity { @@ -69,7 +68,7 @@ public class NpcSpawner extends CreeperEntity { } private void createAndAddItem(Area spawnArea) { - ArrayList<Room> rooms = Lists.newArrayList(Iterators.filter(gameManager.getRoomManager().getRoomsByArea(spawnArea).iterator(), getRoomsWithRoom())); + List<Room> rooms = gameManager.getRoomManager().getRoomsByArea(spawnArea).stream().filter(getRoomsWithRoom()).collect(Collectors.toList()); Room room = rooms.get(random.nextInt(rooms.size())); NpcBuilder npcBuilder = new NpcBuilder(npc); Npc newNpc = npcBuilder.createNpc(); @@ -80,23 +79,30 @@ public class NpcSpawner extends CreeperEntity { Main.metrics.counter(MetricRegistry.name(NpcSpawner.class, npc.getName() + "-spawn")).inc(); } + private Predicate<Room> getRoomsWithRoomNew() { + return room -> { + int count = room.getNpcIds().stream().filter(npcId -> { + Npc npcEntity = gameManager.getEntityManager().getNpcEntity(npcId); + return npcEntity.getName().equals(npc.getName()); + }).collect(Collectors.toList()).size(); + return count < spawnRule.getMaxPerRoom(); + }; + } + private Predicate<Room> getRoomsWithRoom() { - return new Predicate<Room>() { - @Override - public boolean apply(Room room) { - int count = 0; - Set<String> npcIds = room.getNpcIds(); - for (String npcId : npcIds) { - Npc npcEntity = gameManager.getEntityManager().getNpcEntity(npcId); - if (npcEntity.getName().equals(npc.getName())) { - count++; - } - } - if (count < spawnRule.getMaxPerRoom()) { - return true; + return room -> { + int count = 0; + Set<String> npcIds = room.getNpcIds(); + for (String npcId : npcIds) { + Npc npcEntity = gameManager.getEntityManager().getNpcEntity(npcId); + if (npcEntity.getName().equals(npc.getName())) { + count++; } - return false; } + if (count < spawnRule.getMaxPerRoom()) { + return true; + } + return false; }; } } \ No newline at end of file -- GitLab