Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] World 이벤트 관리에 Observer 패턴 적용 #13

Merged
merged 19 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions src/engine/src/rabbitescape/engine/World.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import rabbitescape.engine.Rabbit.Type;
import rabbitescape.engine.WaterRegion;
import rabbitescape.engine.err.RabbitEscapeException;
import rabbitescape.engine.events.*;
import rabbitescape.engine.textworld.Comment;
import rabbitescape.engine.util.Dimension;
import rabbitescape.engine.util.LookupTable2D;
Expand Down Expand Up @@ -132,6 +133,9 @@ public enum CompletionState
public final String music;
public final VoidMarkerStyle.Style voidStyle;

private final GameEventManager eventManager;
private LevelWinListener levelWinListener;

public World(
Dimension size,
List<Block> blocks,
Expand Down Expand Up @@ -194,7 +198,9 @@ public World(
waterAmounts );
}

this.changes = new WorldChanges( this, statsListener );
this.eventManager = new GameEventManager();
this.changes = new WorldChanges( this, new WorldStatsListenerAdapter(statsListener, eventManager) );
this.levelWinListener = null;

init();
}
Expand All @@ -205,7 +211,7 @@ public World(
List<Rabbit> rabbits,
List<Thing> things,
LookupTable2D<WaterRegion> waterTable,
Map<rabbitescape.engine.Token.Type, Integer> abilities,
Map<Token.Type, Integer> abilities,
String name,
String description,
String author_name,
Expand All @@ -222,8 +228,9 @@ public World(
int rabbit_index_count,
boolean paused,
Comment[] comments,
IgnoreWorldStatsListener statsListener,
VoidMarkerStyle.Style voidStyle )
WorldStatsListener statsListener,
VoidMarkerStyle.Style voidStyle
)
{
this.size = size;
this.blockTable = blockTable;
Expand All @@ -249,7 +256,9 @@ public World(
this.comments = comments;
this.voidStyle = voidStyle;

this.changes = new WorldChanges( this, statsListener );
this.eventManager = new GameEventManager();
this.changes = new WorldChanges(this, new WorldStatsListenerAdapter(statsListener, eventManager));
this.levelWinListener = null;

init();
}
Expand Down Expand Up @@ -498,4 +507,36 @@ public Map<Position, Integer> getWaterContents()
}
return waterAmounts;
}

public void addEventListener(EventType type, GameEventListener listener) {
eventManager.addEventListener(type, listener);
}

public void removeEventListener(EventType type, GameEventListener listener) {
eventManager.removeEventListener(type, listener);
}

public GameEventManager getEventManager() {
return eventManager;
}

public void setLevelWinListener(LevelWinListener listener) {
if (listener != null) {
this.levelWinListener = new LevelWinListenerAdapter(listener, eventManager);
} else {
this.levelWinListener = null;
}
}

public void won() {
if (levelWinListener != null) {
levelWinListener.won();
}
}

public void lost() {
if (levelWinListener != null) {
levelWinListener.lost();
}
}
}
14 changes: 14 additions & 0 deletions src/engine/src/rabbitescape/engine/events/EventType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package rabbitescape.engine.events;

public enum EventType {
RABBIT_MOVED,
RABBIT_SAVED,
RABBIT_KILLED,
TOKEN_ADDED,
TOKEN_USED,
BLOCK_CHANGED,
WATER_CHANGED,
LEVEL_WON,
LEVEL_LOST,
STATS_CHANGED
}
8 changes: 8 additions & 0 deletions src/engine/src/rabbitescape/engine/events/GameEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package rabbitescape.engine.events;

import java.util.Map;

public interface GameEvent {
EventType getType();
Map<String, Object> getEventData();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package rabbitescape.engine.events;

public interface GameEventListener {
void onGameEvent(GameEvent event);
}
33 changes: 33 additions & 0 deletions src/engine/src/rabbitescape/engine/events/GameEventManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package rabbitescape.engine.events;

import java.util.*;

public class GameEventManager {
private final Map<EventType, List<GameEventListener>> listeners;

public GameEventManager() {
this.listeners = new HashMap<>();
for (EventType type : EventType.values()) {
listeners.put(type, new ArrayList<GameEventListener>());
}
}

public void addEventListener(EventType type, GameEventListener listener) {
List<GameEventListener> typeListeners = listeners.get(type);
if (!typeListeners.contains(listener)) {
typeListeners.add(listener);
}
}

public void removeEventListener(EventType type, GameEventListener listener) {
List<GameEventListener> typeListeners = listeners.get(type);
typeListeners.remove(listener);
}

public void fireEvent(GameEvent event) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분이 옵저버 패턴에서 옵저버들을 업데이트 하는 부분이군요! 옵저버들의 세부 구현체가 아닌 인터페이스를 참조해서 잘 구현된 것 같습니다.

List<GameEventListener> typeListeners = listeners.get(event.getType());
for (GameEventListener listener : typeListeners) {
listener.onGameEvent(event);
}
}
}
26 changes: 26 additions & 0 deletions src/engine/src/rabbitescape/engine/events/LevelWinEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package rabbitescape.engine.events;

import java.util.HashMap;
import java.util.Map;

public class LevelWinEvent implements GameEvent {
private final EventType type;
private final boolean won;

public LevelWinEvent(boolean won) {
this.type = won ? EventType.LEVEL_WON : EventType.LEVEL_LOST;
this.won = won;
}

@Override
public EventType getType() {
return type;
}

@Override
public Map<String, Object> getEventData() {
Map<String, Object> data = new HashMap<>();
data.put("won", won);
return data;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package rabbitescape.engine.events;

import rabbitescape.engine.LevelWinListener;

public class LevelWinListenerAdapter implements LevelWinListener {
private final LevelWinListener originalListener;
private final GameEventManager eventManager;

public LevelWinListenerAdapter(LevelWinListener originalListener, GameEventManager eventManager) {
this.originalListener = originalListener;
this.eventManager = eventManager;
}

@Override
public void won() {
// 기존 리스너 호출
if (originalListener != null) {
originalListener.won();
}

// 새로운 이벤트 발생
eventManager.fireEvent(new LevelWinEvent(true));
}

@Override
public void lost() {
// 기존 리스너 호출
if (originalListener != null) {
originalListener.lost();
}

// 새로운 이벤트 발생
eventManager.fireEvent(new LevelWinEvent(false));
}
}
32 changes: 32 additions & 0 deletions src/engine/src/rabbitescape/engine/events/RabbitEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package rabbitescape.engine.events;

import rabbitescape.engine.Rabbit;
import rabbitescape.engine.util.Position;

import java.util.HashMap;
import java.util.Map;

public class RabbitEvent implements GameEvent {
private final EventType type;
private final Rabbit rabbit;
private final Position position;

public RabbitEvent(EventType type, Rabbit rabbit, Position position) {
this.type = type;
this.rabbit = rabbit;
this.position = position;
}

@Override
public EventType getType() {
return type;
}

@Override
public Map<String, Object> getEventData() {
Map<String, Object> data = new HashMap<>();
data.put("rabbit", rabbit);
data.put("position", position);
return data;
}
}
27 changes: 27 additions & 0 deletions src/engine/src/rabbitescape/engine/events/StatsChangedEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package rabbitescape.engine.events;

import java.util.HashMap;
import java.util.Map;

public class StatsChangedEvent implements GameEvent {
private final int numSaved;
private final int numToSave;

public StatsChangedEvent(int numSaved, int numToSave) {
this.numSaved = numSaved;
this.numToSave = numToSave;
}

@Override
public EventType getType() {
return EventType.STATS_CHANGED;
}

@Override
public Map<String, Object> getEventData() {
Map<String, Object> data = new HashMap<>();
data.put("numSaved", numSaved);
data.put("numToSave", numToSave);
return data;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package rabbitescape.engine.events;

import rabbitescape.engine.WorldStatsListener;

public class WorldStatsListenerAdapter implements WorldStatsListener {
private final WorldStatsListener originalListener;
private final GameEventManager eventManager;

public WorldStatsListenerAdapter(WorldStatsListener originalListener, GameEventManager eventManager) {
this.originalListener = originalListener;
this.eventManager = eventManager;
}

@Override
public void worldStats(int numSaved, int numToSave) {
// 기존 리스너 호출
if (originalListener != null) {
originalListener.worldStats(numSaved, numToSave);
}

// 새로운 이벤트 발생
eventManager.fireEvent(new StatsChangedEvent(numSaved, numToSave));
}
}
Loading