Java游戏服(简单事件通知实现)
Posted Mature
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java游戏服(简单事件通知实现)相关的知识,希望对你有一定的参考价值。
本次主要用Java实现简单的游戏服务器事件通知,在游戏服中,事件通知是必不可少的一种游戏业务处理逻辑,可以基于观察者模式去编写,或则其他更好的方式。也可以用guava框架的事件通知框架,以下代码只是大概的实现思想,总体设计思路都大同小异; 1.Event注解 package ge; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ ElementType.FIELD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Event { public GameEventType value(); } 处理器接口 IGameEventHandler.Java package ge; public interface IGameEventHandler extends Runnable{ } GameEventHadler.java(父类事件处理器实现类) package ge; public abstract class GameEventHadler implements IGameEventHandler { /** * 事件类型 */ private GameEventType gameEventType; /** * 传递的参数 */ private GameEventMsg gameEventMsg; @Override public void run() { notice(gameEventType, gameEventMsg); } public abstract void notice(GameEventType gameEventType, GameEventMsg gameEventMsg); /** * 设置参数 * * @param gameEventType * @param gameEventMsg * @return */ public GameEventHadler transmit(GameEventType gameEventType, GameEventMsg gameEventMsg) { this.gameEventType = gameEventType; this.gameEventMsg = gameEventMsg; return this; } public GameEventType getGameEventType() { return gameEventType; } public void setGameEventType(GameEventType gameEventType) { this.gameEventType = gameEventType; } public GameEventMsg getGameEventMsg() { return gameEventMsg; } public void setGameEventMsg(GameEventMsg gameEventMsg) { this.gameEventMsg = gameEventMsg; } } 事件管理器 GameEventMgr。Java package ge; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import ge.util.EventRegister; public class GameEventMgr { public static GameEventMgr observerMgr = new GameEventMgr(); public static final String EVENT_PACKGE = "ge.imp"; public static GameEventMgr getIns() { return observerMgr; } private static final int MAX_THREAD_NUM = Runtime.getRuntime().availableProcessors() * 2; /** * 事件执行线程池 */ private static ExecutorService executorService = Executors.newFixedThreadPool(MAX_THREAD_NUM); /** * 事件处理器容器 */ public static Map<GameEventType, GameEventHadler> gameEventHadlerMaps = new HashMap<>(); static { // 注解注册 EventRegister.registeredByAnnotation(); // 代码对象注册 EventRegister.registeredByClassCode(); } /** * 事件通知 * @param gameEventType * @param gameEventMsg */ public static void poolEvent(GameEventType gameEventType, GameEventMsg gameEventMsg) { if (gameEventHadlerMaps.containsKey(gameEventType)) { GameEventHadler gameEventHadler = gameEventHadlerMaps.get(gameEventType); executorService.execute(gameEventHadler.transmit(gameEventType, gameEventMsg)); } } /** * 优雅的关闭线程池子 */ public static void shutDownExecutorService() { if (executorService != null) { executorService.shutdown(); try { if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { executorService.shutdown(); } if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { } } catch (Exception e) { executorService.shutdown(); Thread.currentThread().interrupt(); } } System.err.println("Thread pool shutdown:OK"); } } 事件消息基类 GameEventMsg。Java package ge; /** * 事件消息基类 * @author admin * */ public abstract class GameEventMsg { } 事件类型枚举类 package ge; public enum GameEventType { UP_LEVEL(1, "升级事件"), VIP_UP_LEVEL(2, "VIP升级事件"), RECHARGE(3, "充值事件"), MONSTER_DIE(4,"怪物死亡"), ; private int value; private String des; GameEventType(int value, String des) { this.value = value; this.des = des; } public String getDes() { return des; } public int getValue() { return value; } } 消息实体 package ge.event; import ge.GameEventMsg; public class MonsterDeath_GE extends GameEventMsg { // 击杀者 private long killPlayerId; // 怪物id private int monsterId; public long getKillPlayerId() { return killPlayerId; } public void setKillPlayerId(long killPlayerId) { this.killPlayerId = killPlayerId; } public int getMonsterId() { return monsterId; } public void setMonsterId(int monsterId) { this.monsterId = monsterId; } } package ge.event; import ge.GameEventMsg; public class RechargeEvent_GE extends GameEventMsg{ /** * 充值数量 */ private int rechargeNum; public int getRechargeNum() { return rechargeNum; } public void setRechargeNum(int rechargeNum) { this.rechargeNum = rechargeNum; } } package ge.event; import ge.GameEventMsg; public class UpLevelEvent_GE extends GameEventMsg{ /** * 等级 */ private int level; public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } } package ge.event; import ge.GameEventMsg; public class VipLevelEvent_GE extends GameEventMsg{ /** * VIP等级 */ private int vipLevel; public int getVipLevel() { return vipLevel; } public void setVipLevel(int vipLevel) { this.vipLevel = vipLevel; } } 通知处理器 package ge.imp; import ge.GameEventHadler; import ge.GameEventMsg; import ge.GameEventType; import ge.event.MonsterDeath_GE; import ge.mgr.MonsterMgr; public class MonsterDeathHandler extends GameEventHadler { @Override public void notice(GameEventType gameEventType, GameEventMsg gameEventMsg) { MonsterDeath_GE MonsterDeath_GE = (MonsterDeath_GE) gameEventMsg; MonsterMgr.getIns().monsterKillEvent(MonsterDeath_GE.getKillPlayerId(), MonsterDeath_GE.getMonsterId()); } } package ge.imp; import ge.Event; import ge.GameEventHadler; import ge.GameEventMsg; import ge.GameEventType; import ge.mgr.RechargeMgr; import observer.event.RechargeEvent_GE; /** * 接收事件触发后的业务处理 * * @author admin * */ @Event(GameEventType.RECHARGE) public class RechargeEventHandler extends GameEventHadler { @Override public void notice(GameEventType gameEventType, GameEventMsg gameEventMsg) { RechargeEvent_GE e = (RechargeEvent_GE) gameEventMsg; RechargeMgr.getIns().rechargeEvent(e.getRechargeNum()); /** * 通常相关业务处理:充值奖励,VIP充值经验增加等 */ } } package ge.imp; import ge.Event; import ge.GameEventHadler; import ge.GameEventMsg; import ge.GameEventType; import ge.mgr.LevelMgr; import observer.event.UpLevelEvent_GE; /** * 接收事件触发后的业务处理 * * @author admin * */ @Event(GameEventType.UP_LEVEL) public class UpLevelEventHandler extends GameEventHadler { @Override public void notice(GameEventType gameEventType, GameEventMsg gameEventMsg) { UpLevelEvent_GE e = (UpLevelEvent_GE) gameEventMsg; LevelMgr.getIns().uplevelEvent(e.getLevel()); /** * 通常相关业务处理:玩家战力,系统开放,等级礼包,等级排行等相关 */ } } package ge.imp; import ge.Event; import ge.GameEventHadler; import ge.GameEventMsg; import ge.GameEventType; import ge.mgr.VipMgr; import observer.event.VipLevelEvent_GE; /** * 接收事件触发后的业务处理 * * @author admin * */ @Event(GameEventType.VIP_UP_LEVEL) public class VipUpLevelEventHandler extends GameEventHadler { @Override public void notice(GameEventType gameEventType, GameEventMsg gameEventMsg) { VipLevelEvent_GE e = (VipLevelEvent_GE) gameEventMsg; VipMgr.getIns().vipLevelEvent(e.getVipLevel()); /** * 通常相关业务处理:VIP特权,奖励,系统开放相关等 */ } } 模拟业务管理器调用 package ge.mgr; /** * 业务类 * @author admin * */ public class LevelMgr { private static LevelMgr levelMgr=new LevelMgr(); public static LevelMgr getIns() { return levelMgr; } public void uplevelEvent(int level) { System.err.println("升级到:" + level); } } package ge.mgr; /** * 业务类 * * @author admin * */ public class MonsterMgr { private static MonsterMgr monsterMgr = new MonsterMgr(); public static MonsterMgr getIns() { return monsterMgr; } public void monsterKillEvent(long killPlayer, int monsterId) { System.err.println("击杀者ID:" + killPlayer + ":怪物id:" + monsterId); } } package ge.mgr; /** * 业务类 * * @author admin * */ public class RechargeMgr { private static RechargeMgr rechargeMgr = new RechargeMgr(); public static RechargeMgr getIns() { return rechargeMgr; } public void rechargeEvent(int rechargeNum) { System.err.println("充值了" + rechargeNum); } } package ge.mgr; public class VipMgr { /** * 业务类 */ private static VipMgr vipMgr=new VipMgr(); public static VipMgr getIns() { return vipMgr; } public void vipLevelEvent(int vipLevel) { System.err.println("VIP升级到:" + vipLevel); } } 工具类 package ge.util; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.URL; import java.net.URLDecoder; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.Set; public class ClazzUtils { /** * 从包package中获取所有的Class * * @param pack * @return */ public static Set<Class<?>> getClasses(String pack) { Set<Class<?>> classes = new LinkedHashSet<Class<?>>(); boolean recursive = true; String packageName = pack; String packageDirName = packageName.replace(‘.‘, ‘/‘); Enumeration<URL> dirs; try { dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); while (dirs.hasMoreElements()) { URL url = dirs.nextElement(); String protocol = url.getProtocol(); if ("file".equals(protocol)) { System.err.println("file类型的扫描"); String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes); } } } catch (IOException e) { e.printStackTrace(); } return classes; } /** * 以文件的形式来获取包下的所有Class * * @param packageName * @param packagePath * @param recursive * @param classes */ public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, Set<Class<?>> classes) { File dir = new File(packagePath); if (!dir.exists() || !dir.isDirectory()) { return; } File[] dirfiles = dir.listFiles(new FileFilter() { public boolean accept(File file) { return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")); } }); for (File file : dirfiles) { if (file.isDirectory()) { findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes); } else { String className = file.getName().substring(0, file.getName().length() - 6); try { classes.add( Thread.currentThread().getContextClassLoader().loadClass(packageName + ‘.‘ + className)); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } public static void main(String[] args) { Set<Class<?>> clazz = getClasses("observer.imp"); clazz.forEach(s -> { System.err.println(s); }); } } 事件处理器注册类 package ge.util; import java.util.Set; import ge.Event; import ge.GameEventHadler; import ge.GameEventMgr; import ge.GameEventType; import ge.imp.MonsterDeathHandler; import observer.imp.RechargeEventHandler; import observer.imp.UpLevelEventHandler; import observer.imp.VipUpLevelEventHandler; public class EventRegister { /** * 代码:注册事件处理器[注册方式1] */ public static void registeredByClassCode() { registered(GameEventType.UP_LEVEL, new UpLevelEventHandler()); registered(GameEventType.RECHARGE, new RechargeEventHandler()); registered(GameEventType.VIP_UP_LEVEL, new VipUpLevelEventHandler()); registered(GameEventType.MONSTER_DIE, new MonsterDeathHandler()); } /** * 注册:如果存在就不再进行重复注册 * * @param gameEventType * @param gameEventHadler */ public static void registered(GameEventType gameEventType, GameEventHadler gameEventHadler) { GameEventMgr.gameEventHadlerMaps.computeIfAbsent(gameEventType, s -> { return gameEventHadler; }); } /** * 通过扫描指定包名进行注册[注册方式2] */ public static void registeredByAnnotation() { Set<Class<?>> clazzs = ClazzUtils.getClasses(GameEventMgr.EVENT_PACKGE); if (clazzs == null||clazzs.isEmpty()) { System.err.println("无可注册的事件处理器类"); return; } for (Class<?> clazz : clazzs) { if (!clazz.isAnnotationPresent(Event.class)) { continue; } Event event = clazz.getAnnotation(Event.class); if (event == null) { continue; } GameEventType gameEventType = event.value(); try { GameEventMgr.gameEventHadlerMaps.put(gameEventType, (GameEventHadler) clazz.newInstance()); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } } } 测试类 package ge; import java.util.Scanner; import ge.event.MonsterDeath_GE; import observer.event.RechargeEvent_GE; import observer.event.UpLevelEvent_GE; import observer.event.VipLevelEvent_GE; public class GameEventTest { @SuppressWarnings("static-access") /** * 测试 * * @param args */ public static void main(String[] args) throws InterruptedException { /** * 添加守护线程:在jvm关闭前关闭线程池:一般用在服务器关闭前的操作{数据持久,线程池关闭等等...} */ Runtime.getRuntime().addShutdownHook(new Thread(() -> GameEventMgr.shutDownExecutorService())); /** * 模拟关闭程序命令操作 */ new Thread(() -> closeSystemThread()).start(); /** * 模拟玩家升级 */ UpLevelEvent_GE upLevelEvent_GE = new UpLevelEvent_GE(); upLevelEvent_GE.setLevel(1000); GameEventMgr.getIns().poolEvent(GameEventType.UP_LEVEL, upLevelEvent_GE); /** * 模拟vip升级 */ VipLevelEvent_GE vipLevelEvent_GE = new VipLevelEvent_GE(); vipLevelEvent_GE.setVipLevel(12); GameEventMgr.getIns().poolEvent(GameEventType.VIP_UP_LEVEL, vipLevelEvent_GE); /** * 模拟充值 */ RechargeEvent_GE rechargeEvent_GE = new RechargeEvent_GE(); rechargeEvent_GE.setRechargeNum(500); GameEventMgr.getIns().poolEvent(GameEventType.RECHARGE, rechargeEvent_GE); /** * 模拟怪物击杀 */ MonsterDeath_GE monsterDeath_GE = new MonsterDeath_GE(); monsterDeath_GE.setKillPlayerId(1000200088); monsterDeath_GE.setMonsterId(100008); GameEventMgr.getIns().poolEvent(GameEventType.MONSTER_DIE, monsterDeath_GE); } /** * 关闭程序 */ @SuppressWarnings("resource") public static void closeSystemThread() { Scanner scanner = new Scanner(System.in); if (scanner.next().equals("close")) System.exit(0); } }
以上是关于Java游戏服(简单事件通知实现)的主要内容,如果未能解决你的问题,请参考以下文章