• 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);
        }
    }
    

      

  • 相关阅读:
    [LintCode 614.] 二叉树的最长连续子序列 II
    [LintCode 90.] k数和 II
    [LintCode 1674.] 倒可乐
    [LintCode 797.] 到达一个数字
    [LintCode 1691.] 买卖股票的最佳时机V
    [LintCode 69. 242.] 二叉树的层次遍历
    [LintCode 229.] 栈排序
    [LeetCode 1671.] 玩游戏
    [LintCode 1668.] 区间最小覆盖
    (十)线程同步
  • 原文地址:https://www.cnblogs.com/mature1021/p/13354242.html
Copyright © 2020-2023  润新知