1、清理仓库

This commit is contained in:
贝密游戏
2017-12-21 22:59:24 +08:00
parent 63c4a7927e
commit eeb1c9e07b
1265 changed files with 91622 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
package com.beimi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableAsync;
import com.beimi.core.BMDataContext;
@EnableAutoConfiguration
@SpringBootApplication
@EnableAsync
@EnableJpaRepositories("com.beimi.web.service.repository.jpa")
@EnableElasticsearchRepositories("com.beimi.web.service.repository.es")
public class Application {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(Application.class) ;
BMDataContext.setApplicationContext(springApplication.run(args));
}
}
@@ -0,0 +1,66 @@
package com.beimi.config.web;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.web.util.matcher.RequestMatcher;
import com.beimi.core.BMDataContext;
import com.beimi.util.cache.CacheHelper;
public class ApiRequestMatchingFilter implements Filter {
private RequestMatcher[] ignoredRequests;
private RequestMatcher[] exRequests;
public ApiRequestMatchingFilter(RequestMatcher[] exRequests , RequestMatcher... matcher) {
this.exRequests = exRequests ;
this.ignoredRequests = matcher;
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
boolean matchAnyRoles = false ;
for(RequestMatcher anyRequest : ignoredRequests ){
if(anyRequest.matches(request)){
matchAnyRoles = true ;
}
}
if(exRequests!=null){
for(RequestMatcher anyRequest : exRequests ){
if(anyRequest.matches(request)){
matchAnyRoles = false ;
}
}
}
String authorization = request.getHeader("authorization") ;
if(matchAnyRoles){
if(!StringUtils.isBlank(authorization) && CacheHelper.getApiUserCacheBean().getCacheObject(authorization, BMDataContext.SYSTEM_ORGI) != null){
chain.doFilter(req,resp);
}else{
HttpServletResponse response = (HttpServletResponse) resp ;
response.sendRedirect("/tokens");
}
}else{
chain.doFilter(req,resp);
}
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
@@ -0,0 +1,79 @@
package com.beimi.config.web;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.beimi.core.engine.game.BeiMiGameEnum;
import com.beimi.core.engine.game.BeiMiGameEvent;
import com.beimi.core.engine.game.action.AllCardsAction;
import com.beimi.core.engine.game.action.EnoughAction;
import com.beimi.core.engine.game.action.EnterAction;
import com.beimi.core.engine.game.action.JoinAction;
import com.beimi.core.engine.game.action.dizhu.AutoAction;
import com.beimi.core.engine.game.action.dizhu.RaiseHandsAction;
import com.beimi.core.engine.game.action.majiang.PlayCardsAction;
import com.beimi.core.statemachine.BeiMiStateMachine;
import com.beimi.core.statemachine.config.StateConfigurer;
import com.beimi.core.statemachine.config.StateMachineTransitionConfigurer;
@Configuration
public class BeiMiDizhuStateMachineConfig<T, S> {
@Bean("dizhu")
public BeiMiStateMachine<String,String> create() throws Exception{
BeiMiStateMachine<String,String> beiMiStateMachine = new BeiMiStateMachine<String,String>();
this.configure(beiMiStateMachine.getConfig());
this.configure(beiMiStateMachine.getTransitions());
return beiMiStateMachine;
}
public void configure(StateConfigurer<String,String> states)
throws Exception {
states
.withStates()
.initial(BeiMiGameEnum.NONE.toString())
.state(BeiMiGameEnum.CRERATED.toString())
.state(BeiMiGameEnum.WAITTING.toString())
.state(BeiMiGameEnum.READY.toString())
.state(BeiMiGameEnum.BEGIN.toString())
.state(BeiMiGameEnum.PLAY.toString())
.state(BeiMiGameEnum.END.toString());
}
public void configure(StateMachineTransitionConfigurer<String, String> transitions)
throws Exception {
/**
* 状态切换:BEGIN->WAITTING->READY->PLAY->END
*/
transitions
.withExternal()
.source(BeiMiGameEnum.NONE.toString()).target(BeiMiGameEnum.CRERATED.toString())
.event(BeiMiGameEvent.ENTER.toString()).action(new EnterAction<String,String>())
.and()
.withExternal()
.source(BeiMiGameEnum.CRERATED.toString()).target(BeiMiGameEnum.WAITTING.toString())
.event(BeiMiGameEvent.JOIN.toString()).action(new JoinAction<String,String>())
.and()
.withExternal()
.source(BeiMiGameEnum.WAITTING.toString()).target(BeiMiGameEnum.READY.toString())
.event(BeiMiGameEvent.ENOUGH.toString()).action(new EnoughAction<String, String>())
.and()
.withExternal()
.source(BeiMiGameEnum.READY.toString()).target(BeiMiGameEnum.BEGIN.toString())
.event(BeiMiGameEvent.AUTO.toString()).action(new AutoAction<String,String>()) //抢地主
.and()
.withExternal()
.source(BeiMiGameEnum.BEGIN.toString()).target(BeiMiGameEnum.LASTHANDS.toString())
.event(BeiMiGameEvent.RAISEHANDS.toString()).action(new RaiseHandsAction<String,String>())
.and()
.withExternal()
.source(BeiMiGameEnum.LASTHANDS.toString()).target(BeiMiGameEnum.PLAY.toString())
.event(BeiMiGameEvent.PLAYCARDS.toString()).action(new PlayCardsAction<String,String>())
.and()
.withExternal()
.source(BeiMiGameEnum.PLAY.toString()).target(BeiMiGameEnum.END.toString())
.event(BeiMiGameEvent.ALLCARDS.toString()).action(new AllCardsAction<String,String>())
.and()
;
}
}
@@ -0,0 +1,23 @@
package com.beimi.config.web;
import com.lmax.disruptor.ExceptionHandler;
public class BeiMiExceptionHandler implements ExceptionHandler<Object>{
@Override
public void handleEventException(Throwable ex, long arg1, Object arg2) {
ex.printStackTrace();
}
@Override
public void handleOnShutdownException(Throwable ex) {
}
@Override
public void handleOnStartException(Throwable ex) {
// TODO Auto-generated method stub
}
}
@@ -0,0 +1,57 @@
package com.beimi.config.web;
import io.netty.channel.ChannelHandlerContext;
import java.io.IOException;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.listener.ExceptionListenerAdapter;
public class BeiMiExceptionListener extends ExceptionListenerAdapter {
private static final Logger log = LoggerFactory.getLogger(BeiMiExceptionListener.class);
@Override
public void onEventException(Exception e, List<Object> args, SocketIOClient client) {
if(e instanceof IOException){
log.info(e.getMessage());
}else{
log.error(e.getMessage(), e);
}
client.disconnect();
}
@Override
public void onDisconnectException(Exception e, SocketIOClient client) {
if(e instanceof IOException){
log.info(e.getMessage());
}else{
log.error(e.getMessage(), e);
}
client.disconnect();
}
@Override
public void onConnectException(Exception e, SocketIOClient client) {
if(e instanceof IOException){
log.info(e.getMessage());
}else{
log.error(e.getMessage(), e);
}
client.disconnect();
}
@Override
public boolean exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception {
if(e instanceof IOException){
log.info(e.getMessage());
}else{
log.error(e.getMessage(), e);
}
ctx.close();
return true;
}
}
@@ -0,0 +1,84 @@
package com.beimi.config.web;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.beimi.core.engine.game.BeiMiGameEnum;
import com.beimi.core.engine.game.BeiMiGameEvent;
import com.beimi.core.engine.game.action.AllCardsAction;
import com.beimi.core.engine.game.action.EnoughAction;
import com.beimi.core.engine.game.action.EnterAction;
import com.beimi.core.engine.game.action.JoinAction;
import com.beimi.core.engine.game.action.dizhu.PlayMJCardsAction;
import com.beimi.core.engine.game.action.majiang.DealMJCardAction;
import com.beimi.core.engine.game.action.majiang.MJRaiseHandsAction;
import com.beimi.core.engine.game.action.majiang.SelectAction;
import com.beimi.core.statemachine.BeiMiStateMachine;
import com.beimi.core.statemachine.config.StateConfigurer;
import com.beimi.core.statemachine.config.StateMachineTransitionConfigurer;
@Configuration
public class BeiMiMaJiangStateMachineConfig<T, S> {
@Bean("majiang")
public BeiMiStateMachine<String,String> create() throws Exception{
BeiMiStateMachine<String,String> beiMiStateMachine = new BeiMiStateMachine<String,String>();
this.configure(beiMiStateMachine.getConfig());
this.configure(beiMiStateMachine.getTransitions());
return beiMiStateMachine;
}
public void configure(StateConfigurer<String,String> states)
throws Exception {
states
.withStates()
.initial(BeiMiGameEnum.NONE.toString())
.state(BeiMiGameEnum.CRERATED.toString())
.state(BeiMiGameEnum.WAITTING.toString())
.state(BeiMiGameEnum.READY.toString())
.state(BeiMiGameEnum.BEGIN.toString())
.state(BeiMiGameEnum.PLAY.toString())
.state(BeiMiGameEnum.END.toString());
}
public void configure(StateMachineTransitionConfigurer<String, String> transitions)
throws Exception {
/**
* 状态切换:BEGIN->WAITTING->READY->PLAY->END
*/
transitions
.withExternal()
.source(BeiMiGameEnum.NONE.toString()).target(BeiMiGameEnum.CRERATED.toString())
.event(BeiMiGameEvent.ENTER.toString()).action(new EnterAction<String,String>())
.and()
.withExternal()
.source(BeiMiGameEnum.CRERATED.toString()).target(BeiMiGameEnum.WAITTING.toString())
.event(BeiMiGameEvent.JOIN.toString()).action(new JoinAction<String,String>())
.and()
.withExternal()
.source(BeiMiGameEnum.WAITTING.toString()).target(BeiMiGameEnum.READY.toString())
.event(BeiMiGameEvent.ENOUGH.toString()).action(new EnoughAction<String, String>())
.and()
.withExternal()
.source(BeiMiGameEnum.READY.toString()).target(BeiMiGameEnum.BEGIN.toString())
.event(BeiMiGameEvent.AUTO.toString()).action(new SelectAction<String,String>()) //抢地主
.and()
.withExternal()
.source(BeiMiGameEnum.BEGIN.toString()).target(BeiMiGameEnum.LASTHANDS.toString())
.event(BeiMiGameEvent.RAISEHANDS.toString()).action(new MJRaiseHandsAction<String,String>())
.and()
.withExternal()
.source(BeiMiGameEnum.LASTHANDS.toString()).target(BeiMiGameEnum.LASTHANDS.toString())
.event(BeiMiGameEvent.DEAL.toString()).action(new DealMJCardAction<String,String>())
.and()
.withExternal()
.source(BeiMiGameEnum.LASTHANDS.toString()).target(BeiMiGameEnum.PLAY.toString())
.event(BeiMiGameEvent.PLAYCARDS.toString()).action(new PlayMJCardsAction<String,String>())
.and()
.withExternal()
.source(BeiMiGameEnum.PLAY.toString()).target(BeiMiGameEnum.END.toString())
.event(BeiMiGameEvent.ALLCARDS.toString()).action(new AllCardsAction<String,String>())
.and()
;
}
}
@@ -0,0 +1,30 @@
package com.beimi.config.web;
import javax.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.beimi.config.web.model.Game;
import com.beimi.core.statemachine.BeiMiStateMachine;
import com.beimi.core.statemachine.impl.BeiMiMachineHandler;
@Configuration
public class BeiMiStateMachineHandlerConfig {
@Resource(name="dizhu")
private BeiMiStateMachine<String,String> dizhuConfigure ;
@Resource(name="majiang")
private BeiMiStateMachine<String,String> maJiangConfigure ;
@Bean("dizhuGame")
public Game dizhu() {
return new Game(new BeiMiMachineHandler(this.dizhuConfigure));
}
@Bean("majiangGame")
public Game majiang() {
return new Game(new BeiMiMachineHandler(this.maJiangConfigure));
}
}
@@ -0,0 +1,35 @@
package com.beimi.config.web;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.security.web.util.matcher.RequestMatcher;
public class DelegateRequestMatchingFilter implements Filter {
@SuppressWarnings("unused")
private RequestMatcher[] ignoredRequests;
public DelegateRequestMatchingFilter(RequestMatcher... matcher) {
this.ignoredRequests = matcher;
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
chain.doFilter(req,resp);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
@@ -0,0 +1,29 @@
package com.beimi.config.web;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import com.beimi.util.disruptor.UserDataEventFactory;
import com.beimi.util.disruptor.UserEventHandler;
import com.beimi.util.event.UserDataEvent;
import com.lmax.disruptor.SleepingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
@Component
public class DisruptorConfigure {
@SuppressWarnings({ "unchecked", "deprecation" })
@Bean(name="disruptor")
public Disruptor<UserDataEvent> disruptor() {
Executor executor = Executors.newCachedThreadPool();
UserDataEventFactory factory = new UserDataEventFactory();
Disruptor<UserDataEvent> disruptor = new Disruptor<UserDataEvent>(factory, 1024, executor, ProducerType.SINGLE , new SleepingWaitStrategy());
disruptor.setDefaultExceptionHandler(new BeiMiExceptionHandler());
disruptor.handleEventsWith(new UserEventHandler());
disruptor.start();
return disruptor;
}
}
@@ -0,0 +1,86 @@
package com.beimi.config.web;
import java.io.IOException;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.ReleaseId;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.kie.spring.KModuleBeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
@Configuration
public class DroolsConfiguration {
private static final String RULES_PATH = "config/rules/";
@Bean
@ConditionalOnMissingBean(KieFileSystem.class)
public KieFileSystem kieFileSystem() throws IOException {
KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
for (Resource file : getRuleFiles()) {
kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8"));
}
return kieFileSystem;
}
private Resource[] getRuleFiles() throws IOException {
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");
}
@Bean
@ConditionalOnMissingBean(KieContainer.class)
public KieContainer kieContainer() throws IOException {
final KieRepository kieRepository = getKieServices().getRepository();
kieRepository.addKieModule(new KieModule() {
public ReleaseId getReleaseId() {
return kieRepository.getDefaultReleaseId();
}
});
KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem());
kieBuilder.buildAll();
return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
}
private KieServices getKieServices() {
return KieServices.Factory.get();
}
@Bean
@ConditionalOnMissingBean(KieBase.class)
public KieBase kieBase() throws IOException {
return kieContainer().getKieBase();
}
@Bean
@ConditionalOnMissingBean(KieSession.class)
public KieSession kieSession() throws IOException {
return kieContainer().newKieSession();
}
/*
* As http://docs.jboss.org/drools/release/6.2.0.CR1/drools-docs/html/ch.kie.spring.html
* mentions: Without the org.kie.spring.KModuleBeanFactoryPostProcessor bean definition,
* the kie-spring integration will not work
*/
@Bean
@ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class)
public KModuleBeanFactoryPostProcessor kiePostProcessor() {
return new KModuleBeanFactoryPostProcessor();
}
}
@@ -0,0 +1,48 @@
package com.beimi.config.web;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
@Configuration
public class DruidConfiguration {
/**
* 注册一个StatViewServlet
* @return
*/
@Bean
public ServletRegistrationBean DruidStatViewServle2(){
//org.springframework.boot.context.embedded.ServletRegistrationBean提供类的进行注册.
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
//添加初始化参数:initParams
//白名单:
// servletRegistrationBean.addInitParameter("allow","127.0.0.1");
//IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to view this page.
// servletRegistrationBean.addInitParameter("deny","192.168.1.73");
//登录查看信息的账号密码.
servletRegistrationBean.addInitParameter("loginUsername","admin");
servletRegistrationBean.addInitParameter("loginPassword","123456");
//是否能够重置数据.
servletRegistrationBean.addInitParameter("resetEnable","false");
return servletRegistrationBean;
}
/**
* 注册一个:filterRegistrationBean
* @return
*/
@Bean
public FilterRegistrationBean druidStatFilter2(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
//添加过滤规则.
filterRegistrationBean.addUrlPatterns("/*");
//添加不需要忽略的格式信息.
filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid2/*");
return filterRegistrationBean;
}
}
@@ -0,0 +1,104 @@
package com.beimi.config.web;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.util.Properties;
import javax.annotation.PreDestroy;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import com.beimi.core.BMDataContext;
import com.beimi.util.UKTools;
import com.corundumstudio.socketio.AuthorizationListener;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.HandshakeData;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;
@org.springframework.context.annotation.Configuration
public class GameServerConfiguration
{
@Value("${uk.im.server.host}")
private String host;
@Value("${uk.im.server.port}")
private Integer port;
@Value("${web.upload-path}")
private String path;
@Value("${uk.im.server.threads}")
private String threads;
private SocketIOServer server ;
@Bean(name="webimport")
public Integer getWebIMPort() {
BMDataContext.setWebIMPort(port);
return port;
}
@Bean
public SocketIOServer socketIOServer() throws NoSuchAlgorithmException, IOException
{
Configuration config = new Configuration();
// config.setHostname("localhost");
config.setPort(port);
// config.getSocketConfig().setReuseAddress(true);
// config.setSocketConfig(new SocketConfig());
// config.setOrigin("http://im.uckefu.com");
config.setExceptionListener(new BeiMiExceptionListener());
File sslFile = new File(path , "ssl/https.properties") ;
if(sslFile.exists()){
Properties sslProperties = new Properties();
FileInputStream in = new FileInputStream(sslFile);
sslProperties.load(in);
in.close();
if(!StringUtils.isBlank(sslProperties.getProperty("key-store")) && !StringUtils.isBlank(sslProperties.getProperty("key-store-password"))){
config.setKeyStorePassword(UKTools.decryption(sslProperties.getProperty("key-store-password")));
InputStream stream = new FileInputStream(new File(path , "ssl/"+sslProperties.getProperty("key-store")));
config.setKeyStore(stream);
}
}
// config.setSSLProtocol("https");
int workThreads = !StringUtils.isBlank(threads) && threads.matches("[\\d]{1,6}") ? Integer.parseInt(threads) : 100 ;
config.setWorkerThreads(workThreads);
// config.setStoreFactory(new HazelcastStoreFactory());
config.setAuthorizationListener(new AuthorizationListener() {
public boolean isAuthorized(HandshakeData data) {
return true; //其他安全验证策略,IP,Token,用户名
}
});
/**
* 性能优化
*/
config.getSocketConfig().setReuseAddress(true);
config.getSocketConfig().setSoLinger(0);
config.getSocketConfig().setTcpNoDelay(true);
config.getSocketConfig().setTcpKeepAlive(true);
return server = new SocketIOServer(config);
}
@Bean
public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
return new SpringAnnotationScanner(socketServer);
}
@PreDestroy
public void destory() {
server.stop();
}
}
@@ -0,0 +1,92 @@
package com.beimi.config.web;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.GameEngine;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.GamePlayway;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.Generation;
import com.beimi.web.model.SysDic;
import com.beimi.web.model.SystemConfig;
import com.beimi.web.service.repository.jpa.GamePlaywayRepository;
import com.beimi.web.service.repository.jpa.GameRoomRepository;
import com.beimi.web.service.repository.jpa.GenerationRepository;
import com.beimi.web.service.repository.jpa.SysDicRepository;
import com.beimi.web.service.repository.jpa.SystemConfigRepository;
@Component
public class StartedEventListener implements ApplicationListener<ContextRefreshedEvent> {
@Resource
private GameEngine gameEngine ;
private SysDicRepository sysDicRes;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if(BMDataContext.getContext() == null){
BMDataContext.setApplicationContext(event.getApplicationContext());
}
BMDataContext.setGameEngine(gameEngine);
sysDicRes = event.getApplicationContext().getBean(SysDicRepository.class) ;
List<SysDic> sysDicList = sysDicRes.findAll() ;
for(SysDic dic : sysDicList){
CacheHelper.getSystemCacheBean().put(dic.getId(), dic, dic.getOrgi());
if(dic.getParentid().equals("0")){
List<SysDic> sysDicItemList = new ArrayList<SysDic>();
for(SysDic item : sysDicList){
if(item.getDicid()!=null && item.getDicid().equals(dic.getId())){
sysDicItemList.add(item) ;
}
}
CacheHelper.getSystemCacheBean().put(dic.getCode(), sysDicItemList, dic.getOrgi());
}
}
/**
* 加载系统全局配置
*/
SystemConfigRepository systemConfigRes = event.getApplicationContext().getBean(SystemConfigRepository.class) ;
SystemConfig config = systemConfigRes.findByOrgi(BMDataContext.SYSTEM_ORGI) ;
if(config != null){
CacheHelper.getSystemCacheBean().put("systemConfig", config, BMDataContext.SYSTEM_ORGI);
}
GamePlaywayRepository playwayRes = event.getApplicationContext().getBean(GamePlaywayRepository.class) ;
List<GamePlayway> gamePlaywayList = playwayRes.findAll() ;
if(gamePlaywayList.size() > 0){
for(GamePlayway playway : gamePlaywayList){
CacheHelper.getSystemCacheBean().put(playway.getId(), playway, playway.getOrgi());
}
}
GameRoomRepository gameRoomRes = event.getApplicationContext().getBean(GameRoomRepository.class) ;
List<GameRoom> gameRoomList = gameRoomRes.findAll() ;
if(gameRoomList.size() > 0){
for(GameRoom gameRoom : gameRoomList){
if(gameRoom.isCardroom()){
gameRoomRes.delete(gameRoom);//回收房卡房间资源
}else{
CacheHelper.getQueneCache().put(gameRoom, gameRoom.getOrgi());
CacheHelper.getGameRoomCacheBean().put(gameRoom.getId(), gameRoom, gameRoom.getOrgi());
}
}
}
GenerationRepository generationRes = event.getApplicationContext().getBean(GenerationRepository.class) ;
List<Generation> generationList = generationRes.findAll() ;
for(Generation generation : generationList){
CacheHelper.getSystemCacheBean().setAtomicLong(BMDataContext.ModelType.ROOM.toString(), generation.getStartinx());
}
}
}
@@ -0,0 +1,23 @@
package com.beimi.config.web;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.beimi.web.interceptor.CrossInterceptorHandler;
import com.beimi.web.interceptor.UserInterceptorHandler;
@Configuration
public class UKWebAppConfigurer
extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// addPathPatterns 用于添加拦截规则
// excludePathPatterns 用户排除拦截
registry.addInterceptor(new UserInterceptorHandler()).addPathPatterns("/**").excludePathPatterns("/login.html").excludePathPatterns("/tokens").excludePathPatterns("/api/**");
registry.addInterceptor(new CrossInterceptorHandler()).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
@@ -0,0 +1,89 @@
package com.beimi.config.web;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.WebUtils;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(tokenInfoTokenFilterSecurityInterceptor() , BasicAuthenticationFilter.class)
.antMatcher("*/*").authorizeRequests()
.anyRequest().permitAll()
.and().addFilterAfter(csrfHeaderFilter(), BasicAuthenticationFilter.class)
.addFilterAfter(apiTokenFilterSecurityInterceptor(), BasicAuthenticationFilter.class);
}
@Bean
public Filter tokenInfoTokenFilterSecurityInterceptor() throws Exception
{
RequestMatcher autconfig = new AntPathRequestMatcher("/autoconfig/**");
RequestMatcher configprops = new AntPathRequestMatcher("/configprops/**");
RequestMatcher beans = new AntPathRequestMatcher("/beans/**");
RequestMatcher dump = new AntPathRequestMatcher("/dump/**");
RequestMatcher env = new AntPathRequestMatcher("/env/**");
RequestMatcher health = new AntPathRequestMatcher("/health/**");
RequestMatcher info = new AntPathRequestMatcher("/info/**");
RequestMatcher mappings = new AntPathRequestMatcher("/mappings/**");
RequestMatcher metrics = new AntPathRequestMatcher("/metrics/**");
RequestMatcher trace = new AntPathRequestMatcher("/trace/**");
RequestMatcher druid = new AntPathRequestMatcher("/druid/**");
return new DelegateRequestMatchingFilter(autconfig , configprops , beans , dump , env , health , info , mappings , metrics , trace, druid);
}
/**
* 手机注册 和 游客注册 保留两个 免验证 访问
* @return
* @throws Exception
*/
@Bean
public Filter apiTokenFilterSecurityInterceptor() throws Exception
{
return new ApiRequestMatchingFilter(new AntPathRequestMatcher[]{new AntPathRequestMatcher("/api/register"),new AntPathRequestMatcher("/api/guest")} , new AntPathRequestMatcher("/api/**"));
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null
&& !token.equals(cookie.getValue())) {
// Token is being added to the XSRF-TOKEN cookie.
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
}
@@ -0,0 +1,46 @@
package com.beimi.config.web.model;
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import com.beimi.core.engine.game.state.GameEvent;
import com.beimi.core.statemachine.impl.BeiMiMachineHandler;
import com.beimi.core.statemachine.impl.MessageBuilder;
import com.beimi.web.model.GameRoom;
public class Game {
private final BeiMiMachineHandler handler;
public Game(BeiMiMachineHandler handler) {
this.handler = handler;
}
public void change(GameRoom gameRoom , String event) {
change(gameRoom, event , 0);
}
public void change(GameRoom gameRoom , String event , int interval ) {
handler.handleEventWithState(MessageBuilder.withPayload(event).setHeader("room", gameRoom.getId()).setHeader("interval", interval).build(), event);
}
public void change(GameEvent gameEvent) {
change(gameEvent , 0);
}
public void change(GameEvent gameEvent , int interval ) {
handler.handleEventWithState(MessageBuilder.withPayload(gameEvent.getEvent()).setHeader("room", gameEvent.getRoomid()).setHeader("interval", interval).build(), gameEvent.getEvent());
}
}
@@ -0,0 +1,325 @@
package com.beimi.core;
import org.springframework.context.ApplicationContext;
import java.util.*;
import com.beimi.core.engine.game.GameEngine;
public class BMDataContext {
public static final String USER_SESSION_NAME = "user";
public static final String GUEST_USER = "guest";
public static final String IM_USER_SESSION_NAME = "im_user";
public static final String GUEST_USER_ID_CODE = "BEIMIGUESTUSEKEY" ;
public static final String SERVICE_QUENE_NULL_STR = "service_quene_null" ;
public static final String DEFAULT_TYPE = "default" ; //默认分类代码
public static final String BEIMI_SYSTEM_DIC = "com.dic.system.template";
public static final String BEIMI_SYSTEM_GAME_TYPE_DIC = "com.dic.game.type";
public static final String BEIMI_SYSTEM_GAME_SCENE_DIC = "com.dic.scene.item";
public static final String BEIMI_SYSTEM_GAME_CARDTYPE_DIC = "com.dic.game.dizhu.cardtype";
public static final String BEIMI_SYSTEM_GAME_ROOMTITLE_DIC = "com.dic.game.room.title";
public static final String BEIMI_MESSAGE_EVENT = "command" ;
public static final String BEIMI_PLAYERS_EVENT = "players" ;
public static final String BEIMI_GAMESTATUS_EVENT = "gamestatus" ;
public static final String BEIMI_SEARCHROOM_EVENT = "searchroom" ;
public static final String BEIMI_GAME_PLAYWAY = "game_playway";
public static final String BEIMI_SYSTEM_AUTH_DIC = "com.dic.auth.resource";
public static final String BEIMI_SYSTEM_ROOM = "room" ;
public static String SYSTEM_ORGI = "beimi" ;
private static int WebIMPort = 9081 ;
private static boolean imServerRunning = false ; //IM服务状态
private static ApplicationContext applicationContext ;
public static Map<String , Boolean> model = new HashMap<String,Boolean>();
private static GameEngine gameEngine ;
public static int getWebIMPort() {
return WebIMPort;
}
public static void setWebIMPort(int webIMPort) {
WebIMPort = webIMPort;
}
public static void setApplicationContext(ApplicationContext context){
applicationContext = context ;
}
public static void setGameEngine(GameEngine engine){
gameEngine = engine ;
}
/**
* 根据ORGI找到对应 游戏配置
* @param orgi
* @return
*/
public static String getGameAccountConfig(String orgi){
return BMDataContext.ConfigNames.ACCOUNTCONFIG.toString()+"_"+orgi ;
}
/**
* 根据ORGI找到对应 游戏配置
* @param orgi
* @return
*/
public static String getGameConfig(String orgi){
return BMDataContext.ConfigNames.GAMECONFIG.toString()+"_"+orgi ;
}
/**
* 根据ORGI找到对应 游戏配置
* @param orgi
* @return
*/
public static String getGameAiConfig(String orgi){
return BMDataContext.ConfigNames.AICONFIG.toString()+"_"+orgi ;
}
public static ApplicationContext getContext(){
return applicationContext ;
}
public static GameEngine getGameEngine(){
return gameEngine;
}
/**
* 系统级的加密密码 , 从CA获取
* @return
*/
public static String getSystemSecrityPassword(){
return "BEIMI" ;
}
public enum NameSpaceEnum{
SYSTEM("/bm/system") ,
GAME("/bm/game");
private String namespace ;
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
NameSpaceEnum(String namespace){
this.namespace = namespace ;
}
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum ModelType{
ROOM,
HALL;
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum ConfigNames{
GAMECONFIG,
AICONFIG,
ACCOUNTCONFIG,
PLAYWAYCONFIG,
PLAYWAYGROUP,
PLAYWAYGROUPITEM;
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum UserDataEventType{
SAVE,UPDATE,DELETE;
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum PlayerAction{
GANG,
PENG,
HU,
CHI,
GUO;
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum PlayerGangAction{
MING, //明杠
AN, //暗杠
WAN; //弯杠
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum GameTypeEnum{
MAJIANG,
DIZHU,
DEZHOU;
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum PlayerTypeEnum{
AI, //AI
NORMAL, //普通玩家
OFFLINE, //托管玩家
LEAVE; //离开房间的玩家
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum GameStatusEnum{
READY, //AI
NOTREADY, //普通玩家
MANAGED,
PLAYING,
TIMEOUT; //登录会话过期
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum CardsTypeEnum{
ONE(1), //单张 3~K,A,2
TWO(2), //一对 3~K,A,2
THREE(3), //三张 3~K,A,2
FOUR(4), //三带一 AAA+K
FORMTWO(41), //三带对 AAA+K
FIVE(5), //单顺 连子 10JQKA
SIX(6), //双顺 连对 JJQQKK
SEVEN(7), //三顺 飞机 JJJQQQ
EIGHT(8), //飞机 带翅膀 JJJ+QQQ+K+A
EIGHTONE(81), //飞机 带翅膀 JJJ+QQQ+KK+AA
NINE(9), //四带二 JJJJ+Q+K
NINEONE(91), //四带二对 JJJJ+QQ+KK
TEN(10), //炸弹 JJJJ
ELEVEN(11); //王炸 0+0
private int type ;
CardsTypeEnum(int type){
this.type = type ;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
public enum MessageTypeEnum{
JOINROOM,
MESSAGE,
END,
TRANS, STATUS , AGENTSTATUS , SERVICE, WRITING;
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum SearchRoomResultType{
NOTEXIST, //房间不存在
FULL, //房间已满员
OK, //加入成功
DISABLE, //房间启用了 禁止非邀请加入
INVALID; //房主已离开房间
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum PVActionEnum{
INCOME, //
CONSUME,
EXCHANGE,
VERIFY;
public String toString(){
return super.toString().toLowerCase() ;
}
}
public enum PVAStatusEnum{
OK,
NOTENOUGH,
FAILD,
NOTEXIST,
INVALID;
public String toString(){
return super.toString().toLowerCase() ;
}
}
/**
* 收入类型 , 1、充值,2、兑换、3、赢了,4、赠送,5、抽奖,6、接受赠与
*/
public enum PVAInComeActionEnum{
RECHARGE,
EXCHANGE,
WIN,
WELFARE,
PRIZE,
GIFT;
public String toString(){
return super.toString().toLowerCase() ;
}
}
/**
* 支出 1、输了,2、逃跑扣除、3、兑换扣除,4、送好友
*/
public enum PVAConsumeActionEnum{
LOST,
ESCAPE,
DEDUCTION,
SEND;
public String toString(){
return super.toString().toLowerCase() ;
}
}
public static void setIMServerStatus(boolean running){
imServerRunning = running ;
}
public static boolean getIMServerStatus(){
return imServerRunning;
}
}
@@ -0,0 +1,395 @@
package com.beimi.core.engine.game;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.beimi.config.web.model.Game;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.AbstractTask;
import com.beimi.core.engine.game.task.dizhu.CreateAutoTask;
import com.beimi.util.GameUtils;
import com.beimi.util.UKTools;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.client.NettyClients;
import com.beimi.util.rules.model.Board;
import com.beimi.util.rules.model.DuZhuBoard;
import com.beimi.util.rules.model.GamePlayers;
import com.beimi.util.rules.model.Player;
import com.beimi.util.rules.model.RoomReady;
import com.beimi.util.server.handler.BeiMiClient;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
public class ActionTaskUtils {
/**
*
* @param times
* @param gameRoom
* @return
*/
public static AbstractTask createAutoTask(int times , GameRoom gameRoom){
return new CreateAutoTask(times , gameRoom , gameRoom.getOrgi()) ;
}
public static void sendEvent(String event, Message message,GameRoom gameRoom){
message.setCommand(event);
List<PlayUserClient> players = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi()) ;
for(PlayUserClient user : players){
BeiMiClient client = NettyClients.getInstance().getClient(user.getId()) ;
if(client!=null && online(user.getId(), user.getOrgi())){
client.getClient().sendEvent(BMDataContext.BEIMI_MESSAGE_EVENT, message);
}
}
}
/**
* 通知就绪
* @param gameRoom
* @param game
*/
public static void roomReady(GameRoom gameRoom, Game game){
/**
*
*/
boolean enough = false ;
List<PlayUserClient> playerList = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi()) ;
if(gameRoom.getPlayers() == playerList.size()){
gameRoom.setStatus(BeiMiGameEnum.READY.toString());
boolean hasnotready = false ;
for(PlayUserClient player : playerList){
if(player.isRoomready() == false){
hasnotready = true ; break ;
}
}
if(hasnotready == false){
enough = true ; //所有玩家都已经点击了 开始游戏
}
/**
* 检查当前玩家列表中的所有玩家是否已经全部 就绪,如果已经全部就绪,则开始游戏 , 否则,只发送 roomready事件
*/
ActionTaskUtils.sendEvent("roomready", new RoomReady(gameRoom), gameRoom);
}else{
gameRoom.setStatus(BeiMiGameEnum.WAITTING.toString());
}
CacheHelper.getGameRoomCacheBean().put(gameRoom.getId(), gameRoom, gameRoom.getOrgi());
/**
* 所有人都已经举手
*/
if(enough == true){
game.change(gameRoom , BeiMiGameEvent.ENOUGH.toString()); //通知状态机 , 此处应由状态机处理异步执行
}
}
public static void sendEvent(String event, String userid, Message message){
message.setCommand(event);
BeiMiClient client = NettyClients.getInstance().getClient(userid) ;
if(client!=null){
if(online(userid , client.getOrgi())){
client.getClient().sendEvent(BMDataContext.BEIMI_MESSAGE_EVENT, message);
}
}
}
/**
* 发送消息给 玩家
* @param beiMiClient
* @param event
* @param gameRoom
*/
public static void sendPlayers(BeiMiClient beiMiClient , GameRoom gameRoom){
if(online(beiMiClient.getUserid() , beiMiClient.getOrgi())){
beiMiClient.getClient().sendEvent(BMDataContext.BEIMI_MESSAGE_EVENT, new GamePlayers(gameRoom.getPlayers() , CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), beiMiClient.getOrgi()), BMDataContext.BEIMI_PLAYERS_EVENT));
}
}
/**
* 检查玩家是否在线
* @param userid
* @param orgi
* @return
*/
public static boolean online(String userid, String orgi){
PlayUserClient playerUserClient = (PlayUserClient) CacheHelper.getApiUserCacheBean().getCacheObject(userid, orgi) ;
return playerUserClient!=null && !BMDataContext.PlayerTypeEnum.OFFLINE.toString().equals(playerUserClient.getPlayertype()) && !BMDataContext.PlayerTypeEnum.LEAVE.toString().equals(playerUserClient.getPlayertype()) ;
}
/**
*
* @param gameRoom
* @param players
*/
public static void sendPlayers(GameRoom gameRoom , List<PlayUserClient> players){
for(PlayUserClient user : players){
BeiMiClient client = NettyClients.getInstance().getClient(user.getId()) ;
if(client!=null && online(client.getUserid() , client.getOrgi())){
client.getClient().sendEvent(BMDataContext.BEIMI_MESSAGE_EVENT, new GamePlayers(gameRoom.getPlayers() , CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), client.getOrgi()), BMDataContext.BEIMI_PLAYERS_EVENT));
}
}
}
/**
* 发送消息给 玩家
* @param beiMiClient
* @param event
* @param gameRoom
*/
public static void sendEvent(PlayUserClient playerUser , Message message){
if(online(playerUser.getId() , playerUser.getOrgi())){
NettyClients.getInstance().sendGameEventMessage(playerUser.getId(), BMDataContext.BEIMI_MESSAGE_EVENT , message);
}
}
/**
* 发送消息给 玩家
* @param beiMiClient
* @param event
* @param gameRoom
*/
public static void sendEvent(String userid , Message message){
BeiMiClient client = NettyClients.getInstance().getClient(userid) ;
if(client!=null && online(userid , client.getOrgi())){
NettyClients.getInstance().sendGameEventMessage(userid, BMDataContext.BEIMI_MESSAGE_EVENT , message);
}
}
public static PlayUserClient getPlayUserClient(String roomid,String player , String orgi){
PlayUserClient playUserClient = null;
List<PlayUserClient> players = CacheHelper.getGamePlayerCacheBean().getCacheObject(roomid, orgi) ;
for(PlayUserClient user : players){
if(player.equals(user.getId())){
playUserClient = user ;
}
}
return playUserClient;
}
/**
* 更新玩家状态
* @param userid
* @param orgi
*/
public static void updatePlayerClientStatus(PlayUserClient playUser, String status){
GameUtils.updatePlayerClientStatus(playUser.getId(), playUser.getOrgi(), status);
}
public static Object json(Object data){
return UKTools.json(data) ;
}
/**
* 临时放这里,重构的时候 放到 游戏类型的 实现类里
* 抢地主的时候,首个抢地主 不翻倍
* @param board
* @param player
* @return
*/
public static DuZhuBoard doCatch(DuZhuBoard board, Player player , boolean result){
player.setAccept(result); //抢地主
player.setDocatch(true);
board.setDocatch(true);
if(result){ //抢了地主
if(board.isAdded() == false){
board.setAdded(true);
}else{
board.setRatio(board.getRatio()*2);
}
board.setBanker(player.getPlayuser());
}
return board ;
}
/**
* 临时放这里,重构的时候 放到 游戏类型的 实现类里
* @param board
* @param player
* @return
*/
public static void doBomb(Board board , boolean add){
if(add){ //抢了地主
board.setRatio(board.getRatio()*2);
}
}
/**
* 校验当前出牌是否合规
* @param playCardType
* @param lastCardType
* @return
*/
public static boolean allow(CardType playCardType , CardType lastCardType){
boolean allow = false ;
if(playCardType.isKing()){ //王炸,无敌
allow = true ;
}else if(playCardType.isBomb()){
if(lastCardType.isBomb()){ //都是炸弹
if(playCardType.getMaxcard() > lastCardType.getMaxcard()){
allow = true ;
}
}else if(lastCardType.isKing()){
allow = false ;
}else{
allow = true ;
}
}else if(lastCardType.isBomb()){ //最后一手牌是炸弹 , 当前出牌不是炸弹
allow = false ;
}else if(playCardType.getCardtype() == lastCardType.getCardtype() && playCardType.getCardtype()>0 && lastCardType.getCardtype() > 0){
if(playCardType.getMaxcard() > lastCardType.getMaxcard()){
allow = true ;
}else if(playCardType.getMaxcardvalue() == 53){
allow = true ;
}
}
return allow ;
}
/**
* 分类
* @param cards
* @return
*/
public static Map<Integer , Integer> type(byte[] cards){
Map<Integer,Integer> types = new HashMap<Integer,Integer>();
for(int i=0 ; i<cards.length ; i++){
int card = cards[i]/4 ;
if(types.get(card) == null){
types.put(card, 1) ;
}else{
types.put(card, types.get(card)+1) ;
}
}
return types ;
}
/**
* 牌型识别
* @param cards
* @return
*/
public static CardType identification(byte[] cards){
CardType cardTypeBean = new CardType();
Map<Integer,Integer> types = new HashMap<Integer,Integer>();
int max = -1 , maxcard = -1 , cardtype = 0 , mincard = -1 , min = 100;
for(int i=0 ; i<cards.length ; i++){
int card = cards[i]/4 ;
if(types.get(card) == null){
types.put(card, 1) ;
}else{
types.put(card, types.get(card)+1) ;
}
if(types.get(card) > max){
max = types.get(card) ;
maxcard = card ;
}
if(types.get(card) == max){
if(mincard < 0 || mincard > card){
mincard = card ;
}
}
if(cards[i] > cardTypeBean.getMaxcardvalue()){
cardTypeBean.setMaxcardvalue(cards[i]);
}
}
Iterator<Integer> iterator = types.keySet().iterator() ;
while(iterator.hasNext()){
Integer key = iterator.next() ;
if(types.get(key) < min){
min = types.get(key) ;
}
}
cardTypeBean.setCardnum(max);
cardTypeBean.setMincard(mincard);
cardTypeBean.setTypesize(types.size());
cardTypeBean.setMaxcard(maxcard);
switch(types.size()){
case 1 :
switch(max){
case 1 : cardtype = BMDataContext.CardsTypeEnum.ONE.getType() ;break; //单张
case 2 :
if(mincard == 13){
cardtype = BMDataContext.CardsTypeEnum.ELEVEN.getType();
}else{
cardtype = BMDataContext.CardsTypeEnum.TWO.getType() ;
}
break; //一对
case 3 : cardtype = BMDataContext.CardsTypeEnum.THREE.getType() ;break; //三张
case 4 : cardtype = BMDataContext.CardsTypeEnum.TEN.getType() ;break; //炸弹
}
;break ;
case 2 :
switch(max){
case 3 :
if(min == 1){//三带一
cardtype = BMDataContext.CardsTypeEnum.FOUR.getType() ;
}else if(min == 2){//三带一对
cardtype = BMDataContext.CardsTypeEnum.FORMTWO.getType() ;
}else if(min == 3){//飞机不带
cardtype = BMDataContext.CardsTypeEnum.SEVEN.getType() ;
}
break;
case 4 : cardtype = BMDataContext.CardsTypeEnum.NINE.getType() ;break; //四带一对
}
;break ;
case 3 :
switch(max){
case 1 : ;break; //无牌型
case 2 : if(cards.length == 6 && isAva(types, mincard)){cardtype = BMDataContext.CardsTypeEnum.SIX.getType() ;}break; //3连对
case 3 : if(isAva(types, mincard) && min == max){cardtype = BMDataContext.CardsTypeEnum.SEVEN.getType() ;}break; //三顺
case 4 : if(cards.length == 6 || cards.length == 8) {cardtype = BMDataContext.CardsTypeEnum.NINE.getType() ;}break; //四带二
}
break;
case 4 :
switch(max){
case 1 : ;break; //无牌型
case 2 : if(cards.length == 8 && isAva(types, mincard)){cardtype = BMDataContext.CardsTypeEnum.SIX.getType() ;}break; //4连对
case 3 :
if(isAva(types, mincard)){
if(cards.length == 8){
cardtype = BMDataContext.CardsTypeEnum.EIGHT.getType() ;
}else if(cards.length == 10){
cardtype = BMDataContext.CardsTypeEnum.EIGHTONE.getType() ;
}
}
break; //飞机
};
break ;
case 5 :
switch(max){
case 1 : if(isAva(types ,mincard) && max == min){cardtype = BMDataContext.CardsTypeEnum.FIVE.getType() ;}break; //连子
case 2 : if(cards.length == 10 && isAva(types, mincard)){cardtype = BMDataContext.CardsTypeEnum.SIX.getType() ;}break; //5连对
case 3 : if(isAva(types, mincard) && max == min){cardtype = BMDataContext.CardsTypeEnum.SEVEN.getType() ;}break; //5飞机
};break ;
case 6 :
switch(max){
case 1 : if(isAva(types ,mincard) && max == min){cardtype = BMDataContext.CardsTypeEnum.FIVE.getType() ;}break; //连子
case 2 : if(isAva(types ,mincard) && max == min){cardtype = BMDataContext.CardsTypeEnum.SIX.getType() ;}break; //6连对
case 3 : if(isAva(types ,mincard) && max == min){cardtype = BMDataContext.CardsTypeEnum.SEVEN.getType() ;}break; //6飞机
};break ;
default:
switch(max){
case 1 : if(isAva(types ,mincard)){cardtype = BMDataContext.CardsTypeEnum.FIVE.getType() ;}break; //连子
case 2 : if(isAva(types ,mincard) && max == min){cardtype = BMDataContext.CardsTypeEnum.SIX.getType() ;}break; //连对
};break ;
}
cardTypeBean.setCardtype(cardtype);
cardTypeBean.setKing(cardtype == BMDataContext.CardsTypeEnum.ELEVEN.getType());
cardTypeBean.setBomb(cardtype == BMDataContext.CardsTypeEnum.TEN.getType());
return cardTypeBean ;
}
private static boolean isAva(Map<Integer,Integer> types , int mincard){
boolean ava = true ;
for(int i=mincard ; i<(mincard + types.size()) ; i++){
if(types.get(i) == null){
ava = false ;
}
}
return ava ;
}
}
@@ -0,0 +1,45 @@
package com.beimi.core.engine.game;
import java.util.ArrayList;
import java.util.List;
import com.beimi.core.engine.game.model.Type;
public class BeiMiGame implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String id ;
private String code ;
private String name ;
private List<Type> types = new ArrayList<Type>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Type> getTypes() {
return types;
}
public void setTypes(List<Type> types) {
this.types = types;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
@@ -0,0 +1,15 @@
package com.beimi.core.engine.game;
public enum BeiMiGameEnum {
/**
* 游戏的基本状态,开局->等待玩家(AI)->凑齐一桌子->打牌->结束
*/
NONE, //无状态
CRERATED, //进入房间
BEGIN , //开局
WAITTING, //等待玩家
READY, //凑齐一桌子
LASTHANDS, //翻底牌
PLAY, //打牌
END; //结束
}
@@ -0,0 +1,21 @@
package com.beimi.core.engine.game;
/**
* 所有棋牌类游戏 的基本状态
* 根据游戏类型不同,状态下的事件有所不同
* @author chenhao
*
*/
public enum BeiMiGameEvent {
ENTER, //创建房间 (仅第一个加入房间的人触发的事件)
JOIN, //成员加入
AUTO, //自动 , 抢地主
ENOUGH, //凑够一桌子
RAISEHANDS, //流程处理完毕,开始出牌
PLAYCARDS, //出牌
ALLCARDS, //1、单个玩家打完牌(地主,推到胡);2、打完桌面的所有牌(血战,血流,德州)
DEAL, //抓牌动作
SELECT ; //麻将的特别事件 定缺
}
@@ -0,0 +1,5 @@
package com.beimi.core.engine.game;
public interface BeiMiGameTask {
public void execute();
}
@@ -0,0 +1,73 @@
package com.beimi.core.engine.game;
public class CardType implements java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int maxcard ; //最大的牌
private int cardtype ; //牌型
private int typesize ; //不同牌数量
private boolean king ; //王炸
private boolean bomb; //炸弹
private int mincard ; //最小的牌
private int cardnum ; //最大牌张数 JJJQ= 3
private byte maxcardvalue ;
public CardType(){}
public CardType(int maxcard , int cardtype , boolean king , boolean bomb){
this.maxcard = maxcard ;
this.cardtype = cardtype ;
this.king = king ;
this.bomb = bomb ;
}
public int getMaxcard() {
return maxcard;
}
public void setMaxcard(int maxcard) {
this.maxcard = maxcard;
}
public int getCardtype() {
return cardtype;
}
public void setCardtype(int cardtype) {
this.cardtype = cardtype;
}
public boolean isKing() {
return king;
}
public void setKing(boolean king) {
this.king = king;
}
public boolean isBomb() {
return bomb;
}
public void setBomb(boolean bomb) {
this.bomb = bomb;
}
public int getTypesize() {
return typesize;
}
public void setTypesize(int typesize) {
this.typesize = typesize;
}
public int getMincard() {
return mincard;
}
public void setMincard(int mincard) {
this.mincard = mincard;
}
public int getCardnum() {
return cardnum;
}
public void setCardnum(int cardnum) {
this.cardnum = cardnum;
}
public byte getMaxcardvalue() {
return maxcardvalue;
}
public void setMaxcardvalue(byte maxcardvalue) {
this.maxcardvalue = maxcardvalue;
}
}
@@ -0,0 +1,91 @@
package com.beimi.core.engine.game;
public class GameBoard implements Message , java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = -907633644768054042L;
public GameBoard(String userid, boolean docatch, boolean grab , int ratio){
this.userid = userid ;
this.docatch = docatch ;
this.ratio = ratio ;
this.grab = grab ;
}
public GameBoard(String userid, byte[] lasthands, int ratio){
this.userid = userid ;
this.lasthands = lasthands ;
this.ratio = ratio ;
}
public GameBoard(String userid,int ratio){
this.userid = userid ;
this.ratio = ratio ;
}
public GameBoard(String userid , String banker ,int ratio){
this.userid = userid ;
this.ratio = ratio ;
this.banker = banker ;
}
private byte[] lasthands ;
private String userid ;
private boolean docatch ;
private boolean grab ;
private int ratio ;
private String banker ;
private String command ;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public boolean isDocatch() {
return docatch;
}
public void setDocatch(boolean docatch) {
this.docatch = docatch;
}
public int getRatio() {
return ratio;
}
public void setRatio(int ratio) {
this.ratio = ratio;
}
public boolean isGrab() {
return grab;
}
public void setGrab(boolean grab) {
this.grab = grab;
}
public byte[] getLasthands() {
return lasthands;
}
public void setLasthands(byte[] lasthands) {
this.lasthands = lasthands;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public String getBanker() {
return banker;
}
public void setBanker(String banker) {
this.banker = banker;
}
}
@@ -0,0 +1,739 @@
package com.beimi.core.engine.game;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.state.GameEvent;
import com.beimi.core.engine.game.task.majiang.CreateMJRaiseHandsTask;
import com.beimi.util.GameUtils;
import com.beimi.util.RandomCharUtil;
import com.beimi.util.UKTools;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.client.NettyClients;
import com.beimi.util.rules.model.Action;
import com.beimi.util.rules.model.ActionEvent;
import com.beimi.util.rules.model.Board;
import com.beimi.util.rules.model.DuZhuBoard;
import com.beimi.util.rules.model.JoinRoom;
import com.beimi.util.rules.model.NextPlayer;
import com.beimi.util.rules.model.Player;
import com.beimi.util.rules.model.Playeready;
import com.beimi.util.rules.model.RecoveryData;
import com.beimi.util.rules.model.SelectColor;
import com.beimi.util.rules.model.TakeCards;
import com.beimi.util.server.handler.BeiMiClient;
import com.beimi.web.model.GamePlayway;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
import com.beimi.web.service.repository.es.PlayUserClientESRepository;
import com.beimi.web.service.repository.jpa.GameRoomRepository;
import com.corundumstudio.socketio.SocketIOServer;
@Service(value="beimiGameEngine")
public class GameEngine {
@Autowired
protected SocketIOServer server;
@Resource
private KieSession kieSession;
public void gameRequest(String userid ,String playway , String room , String orgi , PlayUserClient userClient , BeiMiClient beiMiClient ){
GameEvent gameEvent = gameRequest(userClient.getId(), beiMiClient.getPlayway(), beiMiClient, beiMiClient.getOrgi(), userClient) ;
if(gameEvent != null){
/**
* 举手了,表示游戏可以开始了
*/
if(userClient!=null){
userClient.setGamestatus(BMDataContext.GameStatusEnum.READY.toString());
}
/**
* 游戏状态 , 玩家请求 游戏房间,活动房间状态后,发送事件给 StateMachine,由 StateMachine驱动 游戏状态 , 此处只负责通知房间内的玩家
* 1、有新的玩家加入
* 2、给当前新加入的玩家发送房间中所有玩家信息(不包含隐私信息,根据业务需求,修改PlayUserClient的字段,剔除掉隐私信息后发送)
*/
ActionTaskUtils.sendEvent("joinroom", new JoinRoom(userClient, gameEvent.getIndex(), gameEvent.getGameRoom().getPlayers() , gameEvent.getGameRoom()) , gameEvent.getGameRoom());
/**
* 发送给单一玩家的消息
*/
ActionTaskUtils.sendPlayers(beiMiClient, gameEvent.getGameRoom());
/**
* 当前是在游戏中还是 未开始
*/
Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(gameEvent.getRoomid(), gameEvent.getOrgi());
if(board !=null){
Player currentPlayer = null;
for(Player player : board.getPlayers()){
if(player.getPlayuser().equals(userClient.getId())){
currentPlayer = player ; break ;
}
}
if(currentPlayer!=null){
boolean automic = false ;
if((board.getLast()!=null && board.getLast().getUserid().equals(currentPlayer.getPlayuser())) || (board.getLast() == null && board.getBanker().equals(currentPlayer.getPlayuser()))){
automic = true ;
}
ActionTaskUtils.sendEvent("recovery", new RecoveryData(currentPlayer , board.getLasthands() , board.getNextplayer()!=null ? board.getNextplayer().getNextplayer() : null , 25 , automic , board) , gameEvent.getGameRoom());
}
}else{
//通知状态
GameUtils.getGame(beiMiClient.getPlayway() , gameEvent.getOrgi()).change(gameEvent); //通知状态机 , 此处应由状态机处理异步执行
}
}
}
/**
* 玩家房间选择, 新请求,游戏撮合, 如果当前玩家是断线重连, 或者是 退出后进入的,则第一步检查是否已在房间
* 如果已在房间,直接返回
* @param userid
* @param orgi
* @return
*/
public GameEvent gameRequest(String userid ,String playway , BeiMiClient beiMiClient , String orgi , PlayUserClient playUser){
GameEvent gameEvent = null ;
String roomid = (String) CacheHelper.getRoomMappingCacheBean().getCacheObject(userid, orgi) ;
GamePlayway gamePlayway = (GamePlayway) CacheHelper.getSystemCacheBean().getCacheObject(playway, orgi) ;
boolean needtakequene = false;
if(gamePlayway!=null){
gameEvent = new GameEvent(gamePlayway.getPlayers() , gamePlayway.getCardsnum() , orgi) ;
GameRoom gameRoom = null ;
if(!StringUtils.isBlank(roomid) && CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi)!=null){//
gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi) ; //直接加入到 系统缓存 (只有一个地方对GameRoom进行二次写入,避免分布式锁)
}else{
if(beiMiClient.getExtparams()!=null && BMDataContext.BEIMI_SYSTEM_ROOM.equals(beiMiClient.getExtparams().get("gamemodel"))){ //房卡游戏 , 创建ROOM
gameRoom = this.creatGameRoom(gamePlayway, userid , true , beiMiClient) ;
}else{ //
/**
* 大厅游戏 , 撮合游戏 , 发送异步消息,通知RingBuffer进行游戏撮合,撮合算法描述如下:
* 1、按照查找
*
*/
gameRoom = (GameRoom) CacheHelper.getQueneCache().poll(playway , orgi) ;
if(gameRoom != null){
/**
* 修正获取gameroom获取的问题,因为删除房间的时候,为了不损失性能,没有将 队列里的房间信息删除,如果有玩家获取到这个垃圾信息
* 则立即进行重新获取房价,
*/
while(CacheHelper.getGameRoomCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi()) == null){
gameRoom = (GameRoom) CacheHelper.getQueneCache().poll(playway , orgi) ;
if(gameRoom == null){
break ;
}
}
}
if(gameRoom==null){ //无房间 需要
gameRoom = this.creatGameRoom(gamePlayway, userid , false , beiMiClient) ;
}else{
playUser.setPlayerindex(System.currentTimeMillis());//从后往前坐,房主进入以后优先坐在 首位
needtakequene = true ;
}
}
}
if(gameRoom!=null){
/**
* 设置游戏当前已经进行的局数
*/
gameRoom.setCurrentnum(0);
/**
* 更新缓存
*/
CacheHelper.getGameRoomCacheBean().put(gameRoom.getId(), gameRoom, orgi);
/**
* 如果当前房间到达了最大玩家数量,则不再加入到 撮合队列
*/
List<PlayUserClient> playerList = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi()) ;
if(playerList.size() == 0){
gameEvent.setEvent(BeiMiGameEvent.ENTER.toString());
}else{
gameEvent.setEvent(BeiMiGameEvent.JOIN.toString());
}
gameEvent.setGameRoom(gameRoom);
gameEvent.setRoomid(gameRoom.getId());
/**
* 无条件加入房间
*/
this.joinRoom(gameRoom, playUser, playerList);
for(PlayUserClient temp : playerList){
if(temp.getId().equals(playUser.getId())){
gameEvent.setIndex(playerList.indexOf(temp)); break ;
}
}
/**
* 如果当前房间到达了最大玩家数量,则不再加入到 撮合队列
*/
if(playerList.size() < gamePlayway.getPlayers() && needtakequene == true){
CacheHelper.getQueneCache().put(gameRoom, orgi); //未达到最大玩家数量,加入到游戏撮合 队列,继续撮合
}
}
}
return gameEvent;
}
/**
*
* 玩家加入房间
* @param gameRoom
* @param playUser
* @param playerList
*/
public void joinRoom(GameRoom gameRoom , PlayUserClient playUser , List<PlayUserClient> playerList){
boolean inroom = false ;
for(PlayUserClient user : playerList){
if(user.getId().equals(playUser.getId())){
inroom = true ; break ;
}
}
if(inroom == false){
playUser.setPlayerindex(System.currentTimeMillis());
playUser.setGamestatus(BMDataContext.GameStatusEnum.READY.toString());
playUser.setPlayertype(BMDataContext.PlayerTypeEnum.NORMAL.toString());
playUser.setRoomid(gameRoom.getId());
playUser.setRoomready(false);
playerList.add(playUser) ;
NettyClients.getInstance().joinRoom(playUser.getId(), gameRoom.getId());
CacheHelper.getGamePlayerCacheBean().put(playUser.getId(), playUser, playUser.getOrgi()); //将用户加入到 room MultiCache
}
/**
* 不管状态如何,玩家一定会加入到这个房间
*/
CacheHelper.getRoomMappingCacheBean().put(playUser.getId(), gameRoom.getId(), playUser.getOrgi());
}
/**
* 抢地主,斗地主
* @param roomid
* @param orgi
* @return
*/
public void actionRequest(String roomid, PlayUserClient playUser, String orgi , boolean accept){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi) ;
if(gameRoom!=null){
DuZhuBoard board = (DuZhuBoard) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
Player player = board.player(playUser.getId()) ;
board = ActionTaskUtils.doCatch(board, player , accept) ;
ActionTaskUtils.sendEvent("catchresult",new GameBoard(player.getPlayuser() , player.isAccept(), board.isDocatch() , board.getRatio()),gameRoom) ;
GameUtils.getGame(gameRoom.getPlayway() , orgi).change(gameRoom , BeiMiGameEvent.AUTO.toString() , 15); //通知状态机 , 继续执行
CacheHelper.getBoardCacheBean().put(gameRoom.getId() , board , gameRoom.getOrgi()) ;
CacheHelper.getExpireCache().put(gameRoom.getRoomid(), ActionTaskUtils.createAutoTask(1, gameRoom));
}
}
/**
* 抢地主,斗地主
* @param roomid
* @param orgi
* @return
*/
public void startGameRequest(String roomid, PlayUserClient playUser, String orgi , boolean opendeal){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi) ;
if(gameRoom!=null){
playUser.setRoomready(true);
if(opendeal == true){
playUser.setOpendeal(opendeal);
}
CacheHelper.getGamePlayerCacheBean().put(playUser.getId(), playUser, playUser.getOrgi());
ActionTaskUtils.roomReady(gameRoom, GameUtils.getGame(gameRoom.getPlayway() , gameRoom.getOrgi()));
UKTools.published(playUser,BMDataContext.getContext().getBean(PlayUserClientESRepository.class));
ActionTaskUtils.sendEvent(playUser.getId(), new Playeready(playUser.getId() , "playeready"));
}
}
/**
* 抢地主,斗地主
* @param roomid
* @param orgi
* @return
*/
public void cardTips(String roomid, PlayUserClient playUser, String orgi , String cardtips){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi) ;
if(gameRoom!=null){
DuZhuBoard board = (DuZhuBoard) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
Player player = board.player(playUser.getId()) ;
TakeCards takeCards = null ;
if(!StringUtils.isBlank(cardtips)){
String[] cards = cardtips.split(",") ;
byte[] tipCards = new byte[cards.length] ;
for(int i= 0 ; i<cards.length ; i++){
tipCards[i] = Byte.parseByte(cards[i]) ;
}
takeCards = board.cardtip(player, board.getCardTips(player, tipCards)) ;
}
if(takeCards == null || takeCards.getCards() == null){
if(board.getLast() != null && !board.getLast().getUserid().equals(player.getPlayuser())){ //当前无出牌信息,刚开始出牌,或者出牌无玩家 压
takeCards = board.cardtip(player, board.getLast()) ;
}else{
takeCards = board.cardtip(player, null) ;
}
}
if(takeCards.getCards() == null){
takeCards.setAllow(false); //没有 管的起的牌
}
ActionTaskUtils.sendEvent("cardtips", takeCards ,gameRoom) ;
}
}
/**
* 出牌,并校验出牌是否合规
* @param roomid
*
* @param auto 是否自动出牌,超时/托管/AI会调用 = true
* @param orgi
* @return
*/
public TakeCards takeCardsRequest(String roomid, String playUserClient, String orgi , boolean auto , byte[] playCards){
TakeCards takeCards = null ;
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi) ;
if(gameRoom!=null){
Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
if(board!=null){
Player player = board.player(playUserClient) ;
if(board.getNextplayer()!=null && player.getPlayuser().equals(board.getNextplayer().getNextplayer()) && board.getNextplayer().isTakecard() == false){
takeCards = board.takeCardsRequest(gameRoom, board, player, orgi, auto, playCards) ;
}
}
}
return takeCards ;
}
/**
* 检查是否所有玩家 都已经处于就绪状态,如果所有玩家都点击了 继续开始游戏,则发送一个 ALL事件,继续游戏,
* 否则,等待10秒时间,到期后如果玩家还没有就绪,就将该玩家T出去,等待新玩家加入
* @param roomid
* @param userid
* @param orgi
* @return
*/
public void restartRequest(String roomid , PlayUserClient playerUser, BeiMiClient beiMiClient , boolean opendeal){
boolean notReady = false ;
List<PlayUserClient> playerList = null ;
GameRoom gameRoom = null ;
if(!StringUtils.isBlank(roomid)){
gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, playerUser.getOrgi()) ;
playerList = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi()) ;
if(playerList!=null && playerList.size() > 0){
/**
* 有一个 等待
*/
for(PlayUserClient player : playerList){
if(player.isRoomready() == false){
notReady = true ; break ;
}
}
}
}
if(notReady == true && gameRoom!=null){
/**
* 需要增加一个状态机的触发事件:等待其他人就绪,超过5秒以后未就绪的,直接踢掉,然后等待机器人加入
*/
this.startGameRequest(roomid, playerUser, playerUser.getOrgi(), opendeal);
}else if(playerList == null || playerList.size() == 0 || gameRoom == null){//房间已解散
BMDataContext.getGameEngine().gameRequest(playerUser.getId(), beiMiClient.getPlayway(), beiMiClient.getRoom(), beiMiClient.getOrgi(), playerUser , beiMiClient) ;
/**
* 结算后重新开始游戏
*/
playerUser.setRoomready(true);
CacheHelper.getGamePlayerCacheBean().put(playerUser.getId(), playerUser, playerUser.getOrgi());
}
}
/**
* 出牌,并校验出牌是否合规
* @param roomid
*
* @param userid
* @param orgi
* @return
*/
public SelectColor selectColorRequest(String roomid, String userid, String orgi , String color){
SelectColor selectColor = null ;
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi) ;
if(gameRoom!=null){
Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
if(board!=null){
//超时了 执行自动出牌
// Player[] players = board.getPlayers() ;
/**
* 检查是否所有玩家都已经选择完毕 , 如果所有人都选择完毕,即可开始
*/
selectColor = new SelectColor(board.getBanker());
if(!StringUtils.isBlank(color)){
if(!StringUtils.isBlank(color) && color.matches("[0-2]{1}")){
selectColor.setColor(Integer.parseInt(color));
}else{
selectColor.setColor(0);
}
selectColor.setTime(System.currentTimeMillis());
selectColor.setCommand("selectresult");
selectColor.setUserid(userid);
}
boolean allselected = true ;
for(Player ply : board.getPlayers()){
if(ply.getPlayuser().equals(userid)){
if(!StringUtils.isBlank(color) && color.matches("[0-2]{1}")){
ply.setColor(Integer.parseInt(color));
}else{
ply.setColor(0);
}
ply.setSelected(true);
}
if(!ply.isSelected()){
allselected = false ;
}
}
CacheHelper.getBoardCacheBean().put(gameRoom.getId() , board, gameRoom.getOrgi()); //更新缓存数据
ActionTaskUtils.sendEvent("selectresult", selectColor , gameRoom);
/**
* 检查是否全部都已经 定缺, 如果已全部定缺, 则发送 开打
*/
if(allselected){
/**
* 重置计时器,立即执行
*/
CacheHelper.getExpireCache().put(gameRoom.getId(), new CreateMJRaiseHandsTask(1 , gameRoom , gameRoom.getOrgi()) );
GameUtils.getGame(gameRoom.getPlayway() , orgi).change(gameRoom , BeiMiGameEvent.RAISEHANDS.toString() , 0);
}
}
}
return selectColor ;
}
/**
* 麻将 杠碰吃胡过
* @param roomid
*
* @param userid
* @param orgi
* @return
*/
public ActionEvent actionEventRequest(String roomid, String userid, String orgi , String action){
ActionEvent actionEvent = null ;
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi) ;
if(gameRoom!=null){
Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
if(board!=null){
Player player = board.player(userid) ;
byte card = board.getLast().getCard() ;
actionEvent = new ActionEvent(board.getBanker() , userid , card , action);
if(!StringUtils.isBlank(action) && action.equals(BMDataContext.PlayerAction.GUO.toString())){
/**
* 用户动作,选择 了 过, 下一个玩家直接开始抓牌
* bug,待修复:如果有多个玩家可以碰,则一个碰了,其他玩家就无法操作了
*/
board.dealRequest(gameRoom, board, orgi , false , null);
}else if(!StringUtils.isBlank(action) && action.equals(BMDataContext.PlayerAction.PENG.toString()) && allowAction(card, player.getActions() , BMDataContext.PlayerAction.PENG.toString())){
Action playerAction = new Action(userid , action , card);
int color = card / 36 ;
int value = card % 36 / 4 ;
List<Byte> otherCardList = new ArrayList<Byte>();
for(int i=0 ; i<player.getCards().length ; i++){
if(player.getCards()[i]/36 == color && (player.getCards()[i]%36) / 4 == value){
continue ;
}
otherCardList.add(player.getCards()[i]) ;
}
byte[] otherCards = new byte[otherCardList.size()] ;
for(int i=0 ; i<otherCardList.size() ; i++){
otherCards[i] = otherCardList.get(i) ;
}
player.setCards(otherCards);
player.getActions().add(playerAction) ;
board.setNextplayer(new NextPlayer(userid , false));
actionEvent.setTarget(board.getLast().getUserid());
ActionTaskUtils.sendEvent("selectaction", actionEvent , gameRoom);
CacheHelper.getBoardCacheBean().put(gameRoom.getId() , board, gameRoom.getOrgi()); //更新缓存数据
board.playcards(board, gameRoom, player, orgi);
}else if(!StringUtils.isBlank(action) && action.equals(BMDataContext.PlayerAction.GANG.toString()) && allowAction(card, player.getActions() , BMDataContext.PlayerAction.GANG.toString())){
if(board.getNextplayer().getNextplayer().equals(userid)){
card = GameUtils.getGangCard(player.getCards()) ;
actionEvent = new ActionEvent(board.getBanker() , userid , card , action);
actionEvent.setActype(BMDataContext.PlayerGangAction.AN.toString());
}else{
actionEvent.setActype(BMDataContext.PlayerGangAction.MING.toString()); //还需要进一步区分一下是否 弯杠
}
/**
* 检查是否有弯杠
*/
Action playerAction = new Action(userid , action , card);
for(Action ac : player.getActions()){
if(ac.getCard() == card && ac.getAction().equals(BMDataContext.PlayerAction.PENG.toString())){
ac.setGang(true);
ac.setType(BMDataContext.PlayerGangAction.WAN.toString());
playerAction = ac ;
break ;
}
}
int color = card / 36 ;
int value = card % 36 / 4 ;
List<Byte> otherCardList = new ArrayList<Byte>();
for(int i=0 ; i<player.getCards().length ; i++){
if(player.getCards()[i]/36 == color && (player.getCards()[i]%36) / 4 == value){
continue ;
}
otherCardList.add(player.getCards()[i]) ;
}
byte[] otherCards = new byte[otherCardList.size()] ;
for(int i=0 ; i<otherCardList.size() ; i++){
otherCards[i] = otherCardList.get(i) ;
}
player.setCards(otherCards);
player.getActions().add(playerAction) ;
actionEvent.setTarget("all"); //只有明杠 是 其他人打出的 , target 是单一对象
ActionTaskUtils.sendEvent("selectaction", actionEvent , gameRoom);
/**
* 杠了以后, 从 当前 牌的 最后一张开始抓牌
*/
board.dealRequest(gameRoom, board, orgi , true , userid);
}else if(!StringUtils.isBlank(action) && action.equals(BMDataContext.PlayerAction.HU.toString())){ //判断下是不是 真的胡了 ,避免外挂乱发的数据
Action playerAction = new Action(userid , action , card);
player.getActions().add(playerAction) ;
/**
* 记录胡牌的相关信息,推倒胡 | 血战 | 血流
*/
board.setNextplayer(new NextPlayer(userid , false));
actionEvent.setTarget(board.getLast().getUserid());
/**
* 用于客户端播放 胡牌的 动画 , 点胡 和 自摸 ,播放不同的动画效果
*/
ActionTaskUtils.sendEvent("selectaction", actionEvent , gameRoom);
CacheHelper.getBoardCacheBean().put(gameRoom.getId() , board, gameRoom.getOrgi()); //更新缓存数据
/**
* 胡牌方式 从 Playway 配置中读取 , 可选的 胡牌方式 有 推倒胡 | 血战 | 血流
* 根据 配置读取 牌局结束的配置规则 , 如果是推倒胡,则直接进入结算 , 如果是血战,则胡了以后 继续往下进行 ,
* 如果是 血战到底,则继续往下走,可以多次胡牌,当期Player记录相关的胡牌信息
*/
board.playcards(board, gameRoom, player, orgi);
}
}
}
return actionEvent ;
}
/**
* 为防止同步数据错误,校验是否允许刚碰牌
* @param card
* @param actions
* @return
*/
public boolean allowAction(byte card , List<Action> actions , String actiontype){
int take_color = card / 36 ;
int take_value = card%36 / 4 ;
boolean allow = true ;
for(Action action : actions){
int color = action.getCard() / 36 ;
int value = action.getCard() % 36 / 4 ;
if(take_color == color && take_value == value && action.getAction().equals(actiontype)){
allow = false ; break ;
}
}
return allow ;
}
/**
* 出牌,不出牌
* @param roomid
* @param orgi
* @return
*/
public void noCardsRequest(String roomid, PlayUserClient playUser, String orgi){
}
/**
* 加入房间,房卡游戏
* @param roomid
* @param orgi
* @return
*/
public GameRoom joinRoom(String roomid, PlayUserClient playUser, String orgi){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi) ;
if(gameRoom!=null){
CacheHelper.getGamePlayerCacheBean().put(gameRoom.getId(), playUser, orgi); //将用户加入到 room MultiCache
}
return gameRoom ;
}
/**
* 退出房间
* 1、房卡模式,userid是房主,则解散房间
* 2、大厅模式,如果游戏未开始并且房间仅有一人,则解散房间
* @param orgi
* @return
*/
public GameRoom leaveRoom(PlayUserClient playUser , String orgi){
GameRoom gameRoom = whichRoom(playUser.getId(), orgi) ;
if(gameRoom!=null){
List<PlayUserClient> players = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), orgi) ;
if(gameRoom.isCardroom()){
CacheHelper.getGameRoomCacheBean().delete(gameRoom.getId(), gameRoom.getOrgi()) ;
CacheHelper.getGamePlayerCacheBean().clean(gameRoom.getId() , orgi) ;
UKTools.published(gameRoom , null , BMDataContext.getContext().getBean(GameRoomRepository.class) , BMDataContext.UserDataEventType.DELETE.toString());
}else{
if(players.size() <= 1){
//解散房间 , 保留 ROOM资源 , 避免 从队列中取出ROOM
CacheHelper.getGamePlayerCacheBean().clean(gameRoom.getId() , orgi) ;
}else{
CacheHelper.getGamePlayerCacheBean().delete(playUser.getId(), orgi) ;
}
}
}
return gameRoom;
}
/**
* 当前用户所在的房间
* @param userid
* @param orgi
* @return
*/
public GameRoom whichRoom(String userid, String orgi){
GameRoom gameRoom = null ;
String roomid = (String) CacheHelper.getRoomMappingCacheBean().getCacheObject(userid, orgi) ;
if(!StringUtils.isBlank(roomid)){//
gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(roomid, orgi) ; //直接加入到 系统缓存 (只有一个地方对GameRoom进行二次写入,避免分布式锁)
}
return gameRoom;
}
/**
* 结束 当前牌局
* @param orgi
* @return
*/
public void finished(String roomid, String orgi){
if(!StringUtils.isBlank(roomid)){//
CacheHelper.getExpireCache().remove(roomid);
CacheHelper.getBoardCacheBean().delete(roomid, orgi) ;
}
}
/**
* 创建新房间 ,需要传入房间的玩法 , 玩法定义在 系统运营后台,玩法创建后,放入系统缓存 , 客户端进入房间的时候,传入 玩法ID参数
* @param playway
* @param userid
* @return
*/
private GameRoom creatGameRoom(GamePlayway playway , String userid , boolean cardroom , BeiMiClient beiMiClient){
GameRoom gameRoom = new GameRoom() ;
gameRoom.setCreatetime(new Date());
gameRoom.setRoomid(UKTools.getUUID());
gameRoom.setUpdatetime(new Date());
if(playway!=null){
gameRoom.setPlayway(playway.getId());
gameRoom.setRoomtype(playway.getRoomtype());
gameRoom.setPlayers(playway.getPlayers());
}
gameRoom.setPlayers(playway.getPlayers());
gameRoom.setCardsnum(playway.getCardsnum());
gameRoom.setCurpalyers(1);
gameRoom.setCardroom(cardroom);
gameRoom.setStatus(BeiMiGameEnum.CRERATED.toString());
gameRoom.setCardsnum(playway.getCardsnum());
gameRoom.setCurrentnum(0);
gameRoom.setCreater(userid);
gameRoom.setMaster(userid);
gameRoom.setNumofgames(playway.getNumofgames()); //无限制
gameRoom.setOrgi(playway.getOrgi());
/**
* 房卡模式启动游戏
*/
if(beiMiClient.getExtparams()!=null && BMDataContext.BEIMI_SYSTEM_ROOM.equals(beiMiClient.getExtparams().get("gamemodel"))){
gameRoom.setRoomtype(BMDataContext.ModelType.ROOM.toString());
gameRoom.setCardroom(true);
gameRoom.setExtparams(beiMiClient.getExtparams());
/**
* 产生 房间 ID , 麻烦的是需要处理冲突 ,准备采用的算法是 先生成一个号码池子,然后重分布是缓存的 Queue里获取
*/
gameRoom.setRoomid(RandomCharUtil.getRandomNumberChar(6));
/**
* 分配房间号码 , 并且,启用 规则引擎,对房间信息进行赋值
*/
kieSession.insert(gameRoom) ;
kieSession.fireAllRules() ;
}else{
gameRoom.setRoomtype(BMDataContext.ModelType.HALL.toString());
}
CacheHelper.getQueneCache().put(gameRoom, playway.getOrgi()); //未达到最大玩家数量,加入到游戏撮合 队列,继续撮合
UKTools.published(gameRoom, null, BMDataContext.getContext().getBean(GameRoomRepository.class) , BMDataContext.UserDataEventType.SAVE.toString());
return gameRoom ;
}
/**
* 解散房间 , 解散的时候,需要验证下,当前对象是否是房间的创建人
*/
public void dismissRoom(GameRoom gameRoom , String userid,String orgi){
if(gameRoom.getMaster().equals(userid)){
CacheHelper.getGamePlayerCacheBean().delete(gameRoom.getId(), orgi) ;
List<PlayUserClient> players = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), orgi) ;
for(PlayUserClient player : players){
/**
* 解散房间的时候,只清理 AI
*/
if(player.getPlayertype().equals(BMDataContext.PlayerTypeEnum.AI.toString())){
CacheHelper.getGamePlayerCacheBean().delete(player.getId(), orgi) ;
CacheHelper.getRoomMappingCacheBean().delete(player.getId(), orgi) ;
}
}
/**
* 先不删
*/
// UKTools.published(gameRoom, null, BMDataContext.getContext().getBean(GameRoomRepository.class) , BMDataContext.UserDataEventType.DELETE.toString());
}
}
}
@@ -0,0 +1,15 @@
package com.beimi.core.engine.game;
public interface Message {
/**
* 发送到客户端的指令
* @return
*/
public String getCommand() ;
/**
* 指令
* @param command
*/
public void setCommand(String command) ;
}
@@ -0,0 +1,11 @@
package com.beimi.core.engine.game;
import org.cache2k.expiry.ValueWithExpiryTime;
public class StateMachineTask implements ValueWithExpiryTime{
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+2000;
}
}
@@ -0,0 +1,32 @@
package com.beimi.core.engine.game.action;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.CreateAllCardsTask;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.GameRoom;
/**
* 反底牌发给地主
* @author iceworld
*
* @param <T>
* @param <S>
*/
public class AllCardsAction<T,S> implements Action<T, S>{
@Override
public void execute(Message<T> message, BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
CacheHelper.getExpireCache().put(gameRoom.getRoomid(), new CreateAllCardsTask(0 , gameRoom , gameRoom.getOrgi()));
}
}
}
}
@@ -0,0 +1,29 @@
package com.beimi.core.engine.game.action;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.CreateBeginTask;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.GameRoom;
/**
* 凑够了,开牌
* @author iceworld
*
*/
public class EnoughAction<T,S> implements Action<T, S>{
@Override
public void execute(Message<T> message , BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
CacheHelper.getExpireCache().put(gameRoom.getRoomid(), new CreateBeginTask(1 , gameRoom , gameRoom.getOrgi()));
}
}
}
}
@@ -0,0 +1,46 @@
package com.beimi.core.engine.game.action;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.CreateAITask;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.CacheConfigTools;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.AiConfig;
import com.beimi.web.model.GameRoom;
/**
* 创建房间的人,房卡模式下的 房主, 大厅模式下的首个进入房间的人
* @author iceworld
*
*/
public class EnterAction<T,S> implements Action<T, S>{
/**
* 进入房间后开启 5秒计时模式,计时结束后未撮合玩家成功 的,召唤机器人,
* 撮合成功的,立即开启游戏
*/
@Override
public void execute(Message<T> message, BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
if(!gameRoom.isCardroom()) {
AiConfig aiConfig = CacheConfigTools.getAiConfig(gameRoom.getOrgi());
if (aiConfig.isEnableai()) {
CacheHelper.getExpireCache().put(gameRoom.getOrgi(), new CreateAITask(aiConfig.getWaittime(), gameRoom, gameRoom.getOrgi()));
}
}
/**
* 更新状态
*/
gameRoom.setStatus(configurer.getTarget().toString());
CacheHelper.getGameRoomCacheBean().put(gameRoom.getId(), gameRoom, gameRoom.getOrgi());
}
}
}
}
@@ -0,0 +1,13 @@
package com.beimi.core.engine.game.action;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
public class EventAction<T,S> implements Action<T, S>{
@Override
public void execute(Message<T> message, BeiMiExtentionTransitionConfigurer<T,S> configurer) {
}
}
@@ -0,0 +1,41 @@
package com.beimi.core.engine.game.action;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.ActionTaskUtils;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.GameUtils;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.GameRoom;
/**
* 创建房间的人,房卡模式下的 房主, 大厅模式下的首个进入房间的人
* @author iceworld
*
*/
public class JoinAction<T,S> implements Action<T, S>{
/**
* JOIN事件,检查是否 凑齐一桌子,如果凑齐了,直接开始,并取消计时器
* 如果不够一桌子,啥也不做,等人活等计时器到事件
* 撮合成功的,立即开启游戏
* 通知所有成员的消息在 GameEventHandler里处理了
*
*/
@Override
public void execute(Message<T> message, BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
/**
* 发送一个 Enough 事件
*/
ActionTaskUtils.roomReady(gameRoom, GameUtils.getGame(gameRoom.getPlayway() , gameRoom.getOrgi()));
}
}
}
}
@@ -0,0 +1,30 @@
package com.beimi.core.engine.game.action.dizhu;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.dizhu.CreateAutoTask;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.GameRoom;
/**
* 凑够了,开牌
* @author iceworld
*
*/
public class AutoAction<T,S> implements Action<T, S>{
@Override
public void execute(Message<T> message , BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
int interval = (int) message.getMessageHeaders().getHeaders().get("interval") ;
CacheHelper.getExpireCache().put(gameRoom.getRoomid(), new CreateAutoTask(interval , gameRoom , gameRoom.getOrgi()));
}
}
}
}
@@ -0,0 +1,36 @@
package com.beimi.core.engine.game.action.dizhu;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.majiang.CreateMJPlayCardsTask;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.rules.model.Board;
import com.beimi.web.model.GameRoom;
/**
* 凑够了,开牌
* @author iceworld
*
*/
public class PlayMJCardsAction<T,S> implements Action<T, S>{
@Override
public void execute(Message<T> message , BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi()) ;
int interval = (int) message.getMessageHeaders().getHeaders().get("interval") ;
String nextPlayer = board.getBanker();
if(!StringUtils.isBlank(board.getNextplayer().getNextplayer())){
nextPlayer = board.getNextplayer().getNextplayer() ;
}
CacheHelper.getExpireCache().put(gameRoom.getRoomid(), new CreateMJPlayCardsTask(interval , nextPlayer , gameRoom , gameRoom.getOrgi()));
}
}
}
}
@@ -0,0 +1,32 @@
package com.beimi.core.engine.game.action.dizhu;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.dizhu.CreateRaiseHandsTask;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.GameRoom;
/**
* 反底牌发给地主
* @author iceworld
*
* @param <T>
* @param <S>
*/
public class RaiseHandsAction<T,S> implements Action<T, S>{
@Override
public void execute(Message<T> message, BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
CacheHelper.getExpireCache().put(gameRoom.getRoomid(), new CreateRaiseHandsTask(0 , gameRoom , gameRoom.getOrgi()));
}
}
}
}
@@ -0,0 +1,32 @@
package com.beimi.core.engine.game.action.majiang;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.majiang.CreateDealMJCardTask;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.GameRoom;
/**
* 抓牌
* @author iceworld
*
* @param <T>
* @param <S>
*/
public class DealMJCardAction<T,S> implements Action<T, S>{
@Override
public void execute(Message<T> message, BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
CacheHelper.getExpireCache().put(gameRoom.getRoomid(), new CreateDealMJCardTask(5 , gameRoom , gameRoom.getOrgi()));
}
}
}
}
@@ -0,0 +1,32 @@
package com.beimi.core.engine.game.action.majiang;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.majiang.CreateMJRaiseHandsTask;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.GameRoom;
/**
* 反底牌发给地主
* @author iceworld
*
* @param <T>
* @param <S>
*/
public class MJRaiseHandsAction<T,S> implements Action<T, S>{
@Override
public void execute(Message<T> message, BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
CacheHelper.getExpireCache().put(gameRoom.getRoomid(), new CreateMJRaiseHandsTask(5 , gameRoom , gameRoom.getOrgi()));
}
}
}
}
@@ -0,0 +1,36 @@
package com.beimi.core.engine.game.action.majiang;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.dizhu.CreatePlayCardsTask;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.rules.model.DuZhuBoard;
import com.beimi.web.model.GameRoom;
/**
* 凑够了,开牌
* @author iceworld
*
*/
public class PlayCardsAction<T,S> implements Action<T, S>{
@Override
public void execute(Message<T> message , BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
DuZhuBoard board = (DuZhuBoard) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi()) ;
int interval = (int) message.getMessageHeaders().getHeaders().get("interval") ;
String nextPlayer = board.getBanker();
if(!StringUtils.isBlank(board.getNextplayer().getNextplayer())){
nextPlayer = board.getNextplayer().getNextplayer() ;
}
CacheHelper.getExpireCache().put(gameRoom.getRoomid(), new CreatePlayCardsTask(interval , nextPlayer , gameRoom , gameRoom.getOrgi()));
}
}
}
}
@@ -0,0 +1,30 @@
package com.beimi.core.engine.game.action.majiang;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.task.majiang.CreateSelectTask;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.GameRoom;
/**
* 凑够了,开牌
* @author iceworld
*
*/
public class SelectAction<T,S> implements Action<T, S>{
@Override
public void execute(Message<T> message , BeiMiExtentionTransitionConfigurer<T,S> configurer) {
String room = (String)message.getMessageHeaders().getHeaders().get("room") ;
if(!StringUtils.isBlank(room)){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(room, BMDataContext.SYSTEM_ORGI) ;
if(gameRoom!=null){
int interval = (int) message.getMessageHeaders().getHeaders().get("interval") ;
CacheHelper.getExpireCache().put(gameRoom.getRoomid(), new CreateSelectTask(interval , gameRoom , gameRoom.getOrgi()));
}
}
}
}
@@ -0,0 +1,21 @@
package com.beimi.core.engine.game.iface;
import java.util.List;
import com.beimi.util.rules.model.Board;
import com.beimi.web.model.GamePlayway;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
/**
* 棋牌游戏接口API
* @author iceworld
*
*/
public interface ChessGame {
/**
* 创建一局新游戏
* @return
*/
public Board process(List<PlayUserClient> playUsers , GameRoom gameRoom ,GamePlayway playway , String banker , int cardsnum) ;
}
@@ -0,0 +1,33 @@
package com.beimi.core.engine.game.impl;
import java.io.Serializable;
import com.beimi.core.engine.game.Message;
public class Banker implements Message,Serializable{
/**
*
*/
private static final long serialVersionUID = -9011347288522873348L;
private String command ;
private String userid ;
public Banker(String userid){
this.userid = userid ;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
}
@@ -0,0 +1,89 @@
package com.beimi.core.engine.game.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import org.apache.commons.lang.StringUtils;
import com.beimi.core.engine.game.iface.ChessGame;
import com.beimi.util.GameUtils;
import com.beimi.util.rules.model.Board;
import com.beimi.util.rules.model.DuZhuBoard;
import com.beimi.util.rules.model.Player;
import com.beimi.web.model.GamePlayway;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
public class DizhuGame implements ChessGame{
/**
* 开始斗地主游戏
* @return
*/
public Board process(List<PlayUserClient> playUsers , GameRoom gameRoom , GamePlayway playway ,String banker , int cardsnum){
gameRoom.setCurrentnum(gameRoom.getCurrentnum() + 1);
Board board = new DuZhuBoard() ;
board.setCards(null);
List<Byte> temp = new ArrayList<Byte>() ;
for(int i= 0 ; i<54 ; i++){
temp.add((byte)i) ;
}
/**
* 洗牌次数,参数指定,建议洗牌次数 为1次,多次洗牌的随机效果更好,例如:7次
*/
for(int i = 0 ; i<playway.getShuffletimes() + 1; i++){
Collections.shuffle(temp);
}
byte[] cards = new byte[54] ;
for(int i=0 ; i<temp.size() ; i++){
cards[i] = temp.get(i) ;
}
board.setCards(cards);
board.setRatio(15); //默认倍率 15
int random = playUsers.size() * gameRoom.getCardsnum() ;
board.setPosition((byte)new Random().nextInt(random)); //按照人数计算在随机界牌 的位置,避免出现在底牌里
Player[] players = new Player[playUsers.size()];
int inx = 0 ;
for(PlayUserClient playUser : playUsers){
Player player = new Player(playUser.getId()) ;
player.setCards(new byte[cardsnum]);
players[inx++] = player ;
}
for(int i = 0 ; i<gameRoom.getCardsnum()*gameRoom.getPlayers(); i++){
int pos = i%players.length ;
players[pos].getCards()[i/players.length] = cards[i] ;
if(i == board.getPosition()){
players[pos].setRandomcard(true); //起到地主牌的人
}
}
for(Player tempPlayer : players){
Arrays.sort(tempPlayer.getCards());
tempPlayer.setCards(GameUtils.reverseCards(tempPlayer.getCards()));
}
board.setRoom(gameRoom.getId());
Player tempbanker = players[0];
if(!StringUtils.isBlank(banker)){
for(int i= 0 ; i<players.length ; i++){
Player player = players[i] ;
if(player.equals(banker)){
if(i < (players.length - 1)){
tempbanker = players[i+1] ;
}
}
}
}
board.setPlayers(players);
if(tempbanker!=null){
board.setBanker(tempbanker.getPlayuser());
}
return board;
}
}
@@ -0,0 +1,138 @@
package com.beimi.core.engine.game.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import org.apache.commons.lang.StringUtils;
import com.beimi.core.engine.game.iface.ChessGame;
import com.beimi.util.rules.model.Board;
import com.beimi.util.rules.model.MaJiangBoard;
import com.beimi.util.rules.model.Player;
import com.beimi.web.model.GamePlayway;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
public class MaJiangGame implements ChessGame{
/**
* 开始麻将游戏 , 麻将牌 生成规则(总共136张牌,还不会玩 带 春夏秋冬 梅兰竹菊 的玩法,暂不处理) ,
* 1~108:1万~9万小计 36 1筒~9筒小计361条~9条小计36 0-107
* 东南西北中发白 7*4 = 28张 -4~-32,
* 前端 癞子牌(宝牌) 统一 用 0 表示
* 癞子牌确定规则:通常是 最后一张牌 牌面 +1
* @return
*/
public Board process(List<PlayUserClient> playUsers , GameRoom gameRoom , GamePlayway playway ,String banker , int cardsnum){
Board board = new MaJiangBoard() ;
board.setCards(null);
List<Byte> temp = new ArrayList<Byte>(136) ;
for(int i= 0 ; i<108 ; i++){
temp.add((byte)i) ;
}
/**
* 血流/战玩法 , 无风 ,广东麻将, 有风 , 需要根据配置的玩法 获取
*/
if(playway.isWind()){
for(int i= -4 ; i>-32 ; i--){
temp.add(0 , (byte)i) ;
}
}
/**
* 洗牌次数,参数指定,建议洗牌次数 为1次,多次洗牌的随机效果更好,例如:7次
*/
for(int i = 0 ; i<playway.getShuffletimes()+1 ; i++){
Collections.shuffle(temp);
}
byte[] cards = new byte[136] ;
for(int i=0 ; i<temp.size() ; i++){
cards[i] = temp.get(i) ;
}
board.setCards(cards);
board.setRatio(2); //默认番 2
/**
* 以下为定癞子牌(根据玩法需要)
*/
int random = (byte)new Random().nextInt(6) ; //骰子 0~6
board.setPosition(random);
byte[] powerful = new byte[1];
if(cards[cards.length - 2] >=0){
if(cards[cards.length - 2]/4 % 9 == 8){
powerful[0] = (byte) (cards[cards.length - 2]/4 - 8) ; //癞子牌, 万筒条牌面 +1
}else{
powerful[0] = (byte) (cards[cards.length - 2]/4 + 1) ; //癞子牌, 万筒条牌面 +1
}
}else{//东南西北风, 中发白 , 是中的 跳过
if(cards[cards.length - 2] / 4 == -3){
powerful[0] = -2 ;
}else if(cards[cards.length - 2] / 4 == -1){
powerful[0] = -7 ;
}else{
powerful[0] = (byte) (cards[cards.length - 2] / 4 + 1) ;
}
}
board.setPowerful(powerful); //填癞子牌
Player[] players = new Player[playUsers.size()];
int inx = 0 ;
for(PlayUserClient playUser : playUsers){
Player player = new Player(playUser.getId()) ;
if(player.getPlayuser().equals(banker)){
player.setCards(new byte[cardsnum+1]); //庄家
player.setBanker(true);
}else{
player.setCards(new byte[cardsnum]);
}
players[inx++] = player ;
}
/**
* 切墩 , 每次 4张, 发够 12张,然后再挑一张牌 , 切墩 跳过了 骰子
*/
for(int i = 0 ; i<3; i++){
for(int j = 0 ; j<gameRoom.getPlayers(); j++){
for(int cs=0 ; cs < 4 ; cs++){
players[j].getCards()[i*4+cs] = temp.remove(0) ;
}
}
}
/**
* 挑牌,庄 挑 1
*/
for(int i=0 ; i< players.length ; i++){
if(players[i].isBanker()){
players[i].getCards()[12] = temp.remove(0) ;
players[i].getCards()[13] = temp.remove(1) ;
}else{
players[i].getCards()[12] = temp.remove(0) ;
}
}
for(Player tempPlayer : players){
Arrays.sort(tempPlayer.getCards());
}
board.setDeskcards(temp); //待打 的麻将 牌
board.setRoom(gameRoom.getId());
Player tempbanker = players[0];
if(!StringUtils.isBlank(banker)){
for(int i= 0 ; i<players.length ; i++){
Player player = players[i] ;
if(player.getPlayuser().equals(banker)){
tempbanker = player ; break ;
}
}
}
board.setPlayers(players);
if(tempbanker!=null){
board.setBanker(tempbanker.getPlayuser());
}
return board;
}
}
@@ -0,0 +1,72 @@
package com.beimi.core.engine.game.impl;
import java.io.Serializable;
import com.beimi.core.engine.game.Message;
import com.beimi.util.rules.model.Board;
import com.beimi.util.rules.model.Player;
public class UserBoard implements Message,Serializable{
/**
*
*/
private static final long serialVersionUID = -1224310911110772375L;
private Player player ;
private Player[] players ;
private int deskcards ; //剩下多少张牌
private String command ;
/**
* 发给玩家的牌,开启特权后可以将某个其他玩家的牌 显示出来
* @param board
* @param curruser
*/
public UserBoard(Board board , String curruser , String command){
players = new Player[board.getPlayers().length-1] ;
this.command = command ;
if(board.getDeskcards()!=null){
this.deskcards = board.getDeskcards().size() ;
}
int inx = 0 ;
for(Player temp : board.getPlayers()){
if(temp.getPlayuser().equals(curruser)){
player = temp ;
}else{
Player clonePlayer = temp.clone() ;
clonePlayer.setDeskcards(clonePlayer.getCards().length);
clonePlayer.setCards(null); //克隆对象,然后将 其他玩家手里的牌清空
players[inx++] = clonePlayer;
}
}
}
public Player getPlayer() {
return player;
}
public void setPlayer(Player player) {
this.player = player;
}
public Player[] getPlayers() {
return players;
}
public void setPlayers(Player[] players) {
this.players = players;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public int getDeskcards() {
return deskcards;
}
public void setDeskcards(int deskcards) {
this.deskcards = deskcards;
}
}
@@ -0,0 +1,97 @@
package com.beimi.core.engine.game.model;
import com.beimi.core.engine.game.Message;
/**
* 存储牌型
* @author iceworld
*
*/
public class MJCardMessage implements Message,java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private boolean gang ;
private boolean peng ;
private boolean chi ;
private boolean hu;
private boolean deal ; //是否发牌动作
private byte card ;
private String command;
private String userid ;
private String takeuser ; //出牌的人
public MJCardMessage(){
}
public MJCardMessage(boolean gang , boolean peng , boolean hu){
this.gang = gang ;
this.peng = peng ;
this.hu = hu ;
}
public boolean isGang() {
return gang;
}
public void setGang(boolean gang) {
this.gang = gang;
}
public boolean isPeng() {
return peng;
}
public void setPeng(boolean peng) {
this.peng = peng;
}
public boolean isChi() {
return chi;
}
public void setChi(boolean chi) {
this.chi = chi;
}
public boolean isHu() {
return hu;
}
public void setHu(boolean hu) {
this.hu = hu;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public byte getCard() {
return card;
}
public void setCard(byte card) {
this.card = card;
}
public String getTakeuser() {
return takeuser;
}
public void setTakeuser(String takeuser) {
this.takeuser = takeuser;
}
public boolean isDeal() {
return deal;
}
public void setDeal(boolean deal) {
this.deal = deal;
}
}
@@ -0,0 +1,166 @@
package com.beimi.core.engine.game.model;
import com.beimi.web.model.GamePlaywayGroup;
import com.beimi.web.model.GamePlaywayGroupItem;
import java.util.List;
public class Playway implements java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
public Playway(String id, String name , String code , int score , int mincoins , int maxcoins , boolean changecard, boolean shuffle){
this.id = id ;
this.name = name ;
this.score = score ;
this.code = code ;
this.mincoins = mincoins ;
this.maxcoins = maxcoins ;
this.changecard = changecard ;
this.shuffle = shuffle ;
}
private String id;
private String name ;
private String code ;
private int score; //底分
private int mincoins ; //最小金币数量
private int maxcoins ; //最大金币数量
private boolean changecard ; //换牌
private int onlineusers ; //在线用户数
private boolean shuffle ; //是否洗牌
private String level ; //级别
private String skin ; //图标颜色
private String memo ; //备注
private boolean free ; //开启房卡限免
private List<GamePlaywayGroup> groups ;
private List<GamePlaywayGroupItem> items ;
private String roomtitle ; //玩法标题
private boolean extpro ; //启用扩展属性配置(房卡游戏中的自定义规则)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getMincoins() {
return mincoins;
}
public void setMincoins(int mincoins) {
this.mincoins = mincoins;
}
public int getMaxcoins() {
return maxcoins;
}
public void setMaxcoins(int maxcoins) {
this.maxcoins = maxcoins;
}
public boolean isChangecard() {
return changecard;
}
public void setChangecard(boolean changecard) {
this.changecard = changecard;
}
public int getOnlineusers() {
return onlineusers;
}
public void setOnlineusers(int onlineusers) {
this.onlineusers = onlineusers;
}
public boolean isShuffle() {
return shuffle;
}
public void setShuffle(boolean shuffle) {
this.shuffle = shuffle;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getSkin() {
return skin;
}
public void setSkin(String skin) {
this.skin = skin;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
public boolean isFree() {
return free;
}
public void setFree(boolean free) {
this.free = free;
}
public String getRoomtitle() {
return roomtitle;
}
public void setRoomtitle(String roomtitle) {
this.roomtitle = roomtitle;
}
public boolean isExtpro() {
return extpro;
}
public void setExtpro(boolean extpro) {
this.extpro = extpro;
}
public List<GamePlaywayGroup> getGroups() {
return groups;
}
public void setGroups(List<GamePlaywayGroup> groups) {
this.groups = groups;
}
public List<GamePlaywayGroupItem> getItems() {
return items;
}
public void setItems(List<GamePlaywayGroupItem> items) {
this.items = items;
}
}
@@ -0,0 +1,81 @@
package com.beimi.core.engine.game.model;
import java.util.ArrayList;
import java.util.List;
import com.beimi.core.engine.game.Message;
public class Summary implements Message,java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String game ; //房间ID
private String board; //场次 ID
private int ratio ; //倍率
private String command ;
private boolean finished = true ;
private boolean gameRoomOver ;
private int score ; //总分
private List<SummaryPlayer> players = new ArrayList<SummaryPlayer>() ;
public Summary(){}
public Summary(String game , String board , int ratio , int score){
this.game = game ;
this.board = board ;
this.ratio = ratio ;
this.score = score ;
}
public String getGame() {
return game;
}
public void setGame(String game) {
this.game = game;
}
public String getBoard() {
return board;
}
public void setBoard(String board) {
this.board = board;
}
public int getRatio() {
return ratio;
}
public void setRatio(int ratio) {
this.ratio = ratio;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public List<SummaryPlayer> getPlayers() {
return players;
}
public void setPlayers(List<SummaryPlayer> players) {
this.players = players;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public boolean isFinished() {
return finished;
}
public void setFinished(boolean finished) {
this.finished = finished;
}
public boolean isGameRoomOver() {
return gameRoomOver;
}
public void setGameRoomOver(boolean gameRoomOver) {
this.gameRoomOver = gameRoomOver;
}
}
@@ -0,0 +1,85 @@
package com.beimi.core.engine.game.model;
public class SummaryPlayer implements java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String userid ;
private String username ;
private int ratio ;
private int score ;
private boolean gameover ;//破产了
private int balance ; //玩家账户余额
private boolean win ;
private byte[] cards ;
private boolean dizhu ;
public SummaryPlayer(){}
public SummaryPlayer(String userid , String username , int ratio , int score, boolean win , boolean dizhu){
this.userid = userid ;
this.username = username ;
this.ratio = ratio ;
this.score = score ;
this.win = win ;
this.dizhu = dizhu ;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public int getRatio() {
return ratio;
}
public void setRatio(int ratio) {
this.ratio = ratio;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public boolean isWin() {
return win;
}
public void setWin(boolean win) {
this.win = win;
}
public byte[] getCards() {
return cards;
}
public void setCards(byte[] cards) {
this.cards = cards;
}
public boolean isGameover() {
return gameover;
}
public void setGameover(boolean gameover) {
this.gameover = gameover;
}
public boolean isDizhu() {
return dizhu;
}
public void setDizhu(boolean dizhu) {
this.dizhu = dizhu;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
}
@@ -0,0 +1,45 @@
package com.beimi.core.engine.game.model;
import java.util.ArrayList;
import java.util.List;
public class Type implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public Type(String id , String name , String code){
this.id = id ;
this.name = name ;
this.code = code ;
}
private String id ;
private String name ;
private String code ;
private List<Playway> playways = new ArrayList<Playway>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<Playway> getPlayways() {
return playways;
}
public void setPlayways(List<Playway> playways) {
this.playways = playways;
}
}
@@ -0,0 +1,75 @@
package com.beimi.core.engine.game.pva;
import com.beimi.core.BMDataContext;
import com.beimi.util.UKTools;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.PlayUser;
import com.beimi.web.model.PlayUserClient;
import com.beimi.web.service.repository.es.PlayUserESRepository;
import com.beimi.web.service.repository.jpa.PlayUserRepository;
public class GoldPVAImpl extends Pva{
/**
* 充值
* PlayUserClient 仅是 PlayUser的部分字段的镜像,操作个人账号,需要先从数据库存储库中取出PlayUser,
* 然后账号的虚拟资产变化只针对PlayUser操作,操作完成后,赋值到 PlayUserClient 然后推送给房间的客户端和当前玩家
*/
@Override
public PVAOperatorResult income(PlayUserClient playUserClient,String action , int amount) {
PVAOperatorResult result = new PVAOperatorResult(BMDataContext.PVAStatusEnum.OK.toString(), BMDataContext.PVActionEnum.INCOME.toString() , amount);
playUserClient = (PlayUserClient) CacheHelper.getApiUserCacheBean().getCacheObject(playUserClient.getId(), playUserClient.getOrgi()) ;
/**
* 不处理AI
*/
if(playUserClient !=null){
PlayUser playUser = super.playerUser(playUserClient);
if(amount > 0 && playUser != null){
result.setPlayer(playUser);
playUser.setGoldcoins(playUser.getGoldcoins() + amount);
result.setBalance(playUser.getGoldcoins()); //账户金额变更,需要重新进行RSA签名
playUserClient.setGoldcoins(playUser.getGoldcoins());
CacheHelper.getApiUserCacheBean().put(playUserClient.getId(), playUserClient, playUserClient.getOrgi());
UKTools.published(playUser, BMDataContext.getContext().getBean(PlayUserESRepository.class) , BMDataContext.getContext().getBean(PlayUserRepository.class) );
}
}
return result;
}
/**
* 消费
*/
@Override
public PVAOperatorResult consume(PlayUserClient playUserClient,String action , int amount) {
PVAOperatorResult result = new PVAOperatorResult(BMDataContext.PVAStatusEnum.OK.toString(), BMDataContext.PVActionEnum.CONSUME.toString() , amount);
playUserClient = (PlayUserClient) CacheHelper.getApiUserCacheBean().getCacheObject(playUserClient.getId(), playUserClient.getOrgi()) ;
/**
* 不处理AI
*/
if(playUserClient !=null){
PlayUser playUser = super.playerUser(playUserClient);
if(amount > 0 && playUser != null){
result.setPlayer(playUser);
if(playUser.getGoldcoins() >= amount){
playUser.setGoldcoins(playUser.getGoldcoins() - amount);
playUserClient.setGoldcoins(playUser.getGoldcoins());
result.setBalance(playUser.getGoldcoins()); //账户金额变更,需要重新进行RSA签名
CacheHelper.getApiUserCacheBean().put(playUserClient.getId(), playUserClient, playUserClient.getOrgi());
UKTools.published(playUser, BMDataContext.getContext().getBean(PlayUserESRepository.class) , BMDataContext.getContext().getBean(PlayUserRepository.class) );
}else{//
result = new PVAOperatorResult(BMDataContext.PVAStatusEnum.NOTENOUGH.toString(), BMDataContext.PVActionEnum.CONSUME.toString(), playUser, amount);
}
}
}
return result ;
}
/**
* 兑换,金币兑换 , 暂时不做实现,无用 , 金币是最基本消费 资产类型,无兑换功能
*/
@Override
public PVAOperatorResult exchange(PlayUserClient playUserClient, String action ,int amount, String giftid) {
return new PVAOperatorResult(BMDataContext.PVAStatusEnum.INVALID.toString(), BMDataContext.PVActionEnum.EXCHANGE.toString(), super.playerUser(playUserClient), amount);
}
}
@@ -0,0 +1,82 @@
package com.beimi.core.engine.game.pva;
import com.beimi.core.BMDataContext;
import com.beimi.web.model.PlayUser;
public class PVAOperatorResult {
private String status ; //操作状态 , 成功|失败|等待|未知|无权限|非法操作|用户不存在
private int balance ; //余额
private int amount ; //改变的金额
private String action ; //操作类型
private String message ;//操作提示消息
public PVAOperatorResult(String status, String action , PlayUser playUser){
this(status, action, playUser, 0 , null) ;
}
public PVAOperatorResult(String status, String action , int amount){
this(status, action, null , amount , null) ;
}
public PVAOperatorResult(String status, String action , PlayUser playUser , int amount){
this(status, action, playUser, amount , null) ;
}
/**
*
* @param status
* @param action
* @param balance
* @param message
*/
public PVAOperatorResult(String status, String action , PlayUser playUser ,int amount, String message){
this.action = action ;
if(playUser!=null){
this.status = status ;
this.balance = playUser.getGoldcoins() ;
}else{
this.status = BMDataContext.PVAStatusEnum.NOTEXIST.toString();
this.balance = 0 ;
}
this.message = message ;
}
public void setPlayer(PlayUser playUser){
if(playUser!=null){
this.balance = playUser.getGoldcoins() ;
}else{
this.status = BMDataContext.PVAStatusEnum.NOTEXIST.toString();
this.balance = 0 ;
}
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
@@ -0,0 +1,71 @@
package com.beimi.core.engine.game.pva;
import com.beimi.core.BMDataContext;
import com.beimi.web.model.PlayUser;
import com.beimi.web.model.PlayUserClient;
import com.beimi.web.service.repository.es.PlayUserESRepository;
/**
*
* Personal virtual assets(个人虚拟资产) , 注意:所有的 设计个人账户虚拟资产的 变更的 操作,
* 都需要先做校验、事务处理和 账号资产状况的 RSA , PVA信息需要经常和 订单系统 交互
* @author iceworld
*
*/
public abstract class Pva{
/**
* 充值,返回当前账户余额 , 充值后的业务逻辑处理,如果当前有未处理的订单,需要优先处理
* @param playuser
* @param action , 收入类型 , 1、充值,2、兑换、3、赢了,4、赠送,6、抽奖,7、接受赠与
* @param amount
* @return
*/
public abstract PVAOperatorResult income(PlayUserClient playUserClient,String action,int amount);
/**
* 消费,返回当前账户余额 , 消费业务逻辑处理,需要优先验证 当前账户是否有足够的余额用于消费
* @param playuser
* @param action , 支出类型 , 1、输了,2、逃跑扣除、3、兑换扣除,4、送好友
* @param amount
* @return
*/
public abstract PVAOperatorResult consume(PlayUserClient playUserClient,String action,int amount) ;
/**
* 兑换 , 兑换的业务逻辑处理,需要验证当前账户是否有足够的余额用于 兑换 , 兑换扣费完成之后,需要 生成新的余额的 签名信息
* @param playuser
* @param amount
* @param action , 兑换礼品
* @param giftid
* @return
*/
public abstract PVAOperatorResult exchange(PlayUserClient playUserClient ,String action, int amount , String giftid) ;
/**
* 验证当前玩家的余额是否有异常
* @param playuser
* @return
*/
public PVAOperatorResult verify(PlayUserClient playUserClient){
PlayUser playUser = playerUser(playUserClient);
/**
* playUser.getSign();
*/
return new PVAOperatorResult(BMDataContext.PVAStatusEnum.OK.toString(), BMDataContext.PVActionEnum.VERIFY.toString(), playUser);
}
/**
* 获得PlayUser
* @param playUserClient
* @return
*/
public PlayUser playerUser(PlayUserClient playUserClient){
PlayUser playUser = null ;
if(playUserClient!=null){
PlayUserESRepository playUserEsRes = BMDataContext.getContext().getBean(PlayUserESRepository.class) ;
playUser = playUserEsRes.findById(playUserClient.getId()) ;
}
return playUser ;
}
}
@@ -0,0 +1,92 @@
package com.beimi.core.engine.game.state;
import com.beimi.web.model.GameRoom;
public class GameEvent implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1606276594008150495L;
public GameEvent(int players , int cardsnum , String orgi){
this.players = players ;
this.time = System.currentTimeMillis() ;
this.orgi = orgi ;
this.cardsnum = cardsnum ;
}
public GameEvent(String roomid , String event , int players , int cardsnum , long time , String orgi){
this.roomid = roomid ;
this.event = event ;
this.players = players ;
this.time = time ;
this.orgi = orgi ;
this.cardsnum = cardsnum ;
}
public String roomid ;
private String event ;
private String orgi ;
private int cardsnum ;
private GameRoom gameRoom ;
private int index ; //当前玩家 顺序号
private int players ;
private long time ;
public String getRoomid() {
return roomid;
}
public void setRoomid(String roomid) {
this.roomid = roomid;
}
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}
public int getPlayers() {
return players;
}
public void setPlayers(int players) {
this.players = players;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public String getOrgi() {
return orgi;
}
public void setOrgi(String orgi) {
this.orgi = orgi;
}
public int getCardsnum() {
return cardsnum;
}
public void setCardsnum(int cardsnum) {
this.cardsnum = cardsnum;
}
public GameRoom getGameRoom() {
return gameRoom;
}
public void setGameRoom(GameRoom gameRoom) {
this.gameRoom = gameRoom;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
@@ -0,0 +1,41 @@
package com.beimi.core.engine.game.task;
import org.cache2k.expiry.ValueWithExpiryTime;
import com.beimi.config.web.model.Game;
import com.beimi.core.engine.game.ActionTaskUtils;
import com.beimi.core.engine.game.Message;
import com.beimi.util.GameUtils;
import com.beimi.util.UKTools;
import com.beimi.web.model.GamePlayway;
import com.beimi.web.model.GameRoom;
public abstract class AbstractTask implements ValueWithExpiryTime {
/**
* 根据玩法,找到对应的状态机
* @param playway
* @param orgi
* @return
*/
public Game getGame(String playway , String orgi){
return GameUtils.getGame(playway , orgi) ;
}
public void sendEvent(String event , Message message , GameRoom gameRoom){
ActionTaskUtils.sendEvent(event, message, gameRoom);
}
public Object json(Object data){
return UKTools.json(data) ;
}
/**
* 根据当前 ROOM的 玩法, 确定下一步的流程
* @param playway
* @param currentStatus
* @return
*/
public String getNextEvent(GamePlayway playway,String currentStatus){
return "" ;
}
}
@@ -0,0 +1,69 @@
package com.beimi.core.engine.game.task;
import java.util.List;
import org.cache2k.expiry.ValueWithExpiryTime;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.ActionTaskUtils;
import com.beimi.core.engine.game.BeiMiGameTask;
import com.beimi.util.GameUtils;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUser;
import com.beimi.web.model.PlayUserClient;
public class CreateAITask extends AbstractTask implements ValueWithExpiryTime , BeiMiGameTask{
private long timer ;
private GameRoom gameRoom = null ;
private String orgi ;
public CreateAITask(long timer , GameRoom gameRoom, String orgi){
super();
this.timer = timer ;
this.gameRoom = gameRoom ;
this.orgi = orgi ;
}
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+timer*1000; //5秒后执行
}
public void execute(){
//执行生成AI
GameUtils.removeGameRoom(gameRoom.getId(), gameRoom.getPlayway(), orgi);
List<PlayUserClient> playerList = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi()) ;
/**
* 清理 未就绪玩家
*/
for(int i=0 ; i<playerList.size() ; ){
PlayUserClient player = playerList.get(i) ;
if(!player.getGamestatus().equals(BMDataContext.GameStatusEnum.READY.toString())){
playerList.remove(i) ;
CacheHelper.getGamePlayerCacheBean().delete(player.getId(), orgi) ;
continue ;
}
i++;
}
int aicount = gameRoom.getPlayers() - playerList.size() ;
if(aicount>0){
for(int i=0 ; i<aicount ; i++){
PlayUserClient playerUser = GameUtils.create(new PlayUser() , BMDataContext.PlayerTypeEnum.AI.toString()) ;
playerUser.setPlayerindex(System.currentTimeMillis()); //按照加入房间的时间排序,有玩家离开后,重新发送玩家信息列表,重新座位
playerUser.setRoomid(gameRoom.getId());
playerUser.setRoomready(true);
CacheHelper.getGamePlayerCacheBean().put(playerUser.getId(), playerUser, orgi); //将用户加入到 room MultiCache
playerList.add(playerUser) ;
}
ActionTaskUtils.sendPlayers(gameRoom, playerList);
/**
* 发送一个 Enough 事件
*/
ActionTaskUtils.roomReady(gameRoom, super.getGame(gameRoom.getPlayway(), orgi));
}
}
}
@@ -0,0 +1,89 @@
package com.beimi.core.engine.game.task;
import org.cache2k.expiry.ValueWithExpiryTime;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.ActionTaskUtils;
import com.beimi.core.engine.game.BeiMiGameTask;
import com.beimi.core.engine.game.model.Summary;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.rules.model.Board;
import com.beimi.util.rules.model.Player;
import com.beimi.web.model.GamePlayway;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
public class CreateAllCardsTask extends AbstractTask implements ValueWithExpiryTime , BeiMiGameTask{
private long timer ;
private GameRoom gameRoom = null ;
private String orgi ;
public CreateAllCardsTask(long timer , GameRoom gameRoom, String orgi){
super();
this.timer = timer ;
this.gameRoom = gameRoom ;
this.orgi = orgi ;
}
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+timer*1000; //5秒后执行
}
public void execute(){
Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
board.setFinished(true);
GamePlayway gamePlayWay = (GamePlayway) CacheHelper.getSystemCacheBean().getCacheObject(gameRoom.getPlayway(), gameRoom.getOrgi()) ;
boolean gameOver = false ;
if(gamePlayWay!=null){
/**
* 结算信息 , 更新 玩家信息
*/
Summary summary = board.summary(board, gameRoom, gamePlayWay) ;
sendEvent("allcards", summary , gameRoom) ; //通知所有客户端结束牌局,进入结算
if(summary.isGameRoomOver()){
gameOver = true ;
}
}
for(Player player : board.getPlayers()){
PlayUserClient playUserClient = (PlayUserClient) CacheHelper.getApiUserCacheBean().getCacheObject(player.getPlayuser(), this.orgi) ;
if(playUserClient!=null){
if(!playUserClient.getPlayertype().equals(BMDataContext.PlayerTypeEnum.AI.toString())){
playUserClient.setGamestatus(BMDataContext.GameStatusEnum.NOTREADY.toString());
CacheHelper.getApiUserCacheBean().put(playUserClient.getId(),playUserClient, gameRoom.getOrgi()) ;
if(playUserClient.getPlayertype().equals(BMDataContext.PlayerTypeEnum.NORMAL.toString())){
/**
* 历史遗留的问题,CacheHelper.getApiUserCacheBean()获取的是真实玩家的 数据,包括玩家的状态,CacheHelper.getGamePlayerCacheBean()存放的是包含机器人玩家的数据
*/
playUserClient = (PlayUserClient) CacheHelper.getGamePlayerCacheBean().getPlayer(player.getPlayuser(), this.orgi) ;
playUserClient.setRoomready(false);
CacheHelper.getGamePlayerCacheBean().put(playUserClient.getId(),playUserClient, gameRoom.getOrgi()) ;
}else if(playUserClient.getPlayertype().equals(BMDataContext.PlayerTypeEnum.LEAVE.toString()) || playUserClient.getPlayertype().equals(BMDataContext.PlayerTypeEnum.OFFLINE.toString())){
/**
* 离线和托管玩家,离开房间以后,牌局结束时从当前房间清理出去
*/
ActionTaskUtils.updatePlayerClientStatus(playUserClient, playUserClient.getPlayertype());
}
}
}
}
if(gameOver){
CacheHelper.getGamePlayerCacheBean().clean(gameRoom.getId() ,orgi) ;
for(Player player : board.getPlayers()){
CacheHelper.getGameRoomCacheBean().delete(player.getPlayuser(), gameRoom.getOrgi()) ;
CacheHelper.getRoomMappingCacheBean().delete(player.getPlayuser(), this.orgi) ;
}
if(gameRoom.isCardroom() == false){ //房卡模式,清理掉房卡资源
/**
* 重新加入房间资源到 队列
*/
CacheHelper.getQueneCache().put(gameRoom, gameRoom.getOrgi());
}
}
BMDataContext.getGameEngine().finished(gameRoom.getId(), orgi);
}
}
@@ -0,0 +1,84 @@
package com.beimi.core.engine.game.task;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.cache2k.expiry.ValueWithExpiryTime;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.ActionTaskUtils;
import com.beimi.core.engine.game.BeiMiGameEvent;
import com.beimi.core.engine.game.BeiMiGameTask;
import com.beimi.core.engine.game.impl.Banker;
import com.beimi.core.engine.game.impl.UserBoard;
import com.beimi.util.GameUtils;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.rules.model.Board;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
public class CreateBeginTask extends AbstractTask implements ValueWithExpiryTime , BeiMiGameTask{
private long timer ;
private GameRoom gameRoom = null ;
private String orgi ;
public CreateBeginTask(long timer , GameRoom gameRoom, String orgi){
super();
this.timer = timer ;
this.gameRoom = gameRoom ;
this.orgi = orgi ;
}
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+timer*1000; //5秒后执行
}
public void execute(){
List<PlayUserClient> playerList = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), orgi) ;
/**
*
* 顺手 把牌发了,注:此处应根据 GameRoom的类型获取 发牌方式
*/
boolean inroom = false;
if(!StringUtils.isBlank(gameRoom.getLastwinner())){
for(PlayUserClient player : playerList){
if(player.getId().equals(gameRoom.getLastwinner())){
inroom = true ;
}
}
}
if(inroom == false){
gameRoom.setLastwinner(playerList.get(0).getId());
}
/**
* 通知所有玩家 新的庄
*/
ActionTaskUtils.sendEvent("banker", new Banker(gameRoom.getLastwinner()), gameRoom);
Board board = GameUtils.playGame(playerList, gameRoom, gameRoom.getLastwinner(), gameRoom.getCardsnum()) ;
CacheHelper.getBoardCacheBean().put(gameRoom.getId(), board, gameRoom.getOrgi());
for(Object temp : playerList){
PlayUserClient playerUser = (PlayUserClient) temp ;
playerUser.setGamestatus(BMDataContext.GameStatusEnum.PLAYING.toString());
/**
* 更新状态到 PLAYING
*/
if(CacheHelper.getApiUserCacheBean().getCacheObject(playerUser.getId(), playerUser.getOrgi())!=null){
CacheHelper.getApiUserCacheBean().put(playerUser.getId(), playerUser, orgi);
}
/**
* 每个人收到的 牌面不同,所以不用 ROOM发送广播消息,而是用 遍历房间里所有成员发送消息的方式
*/
ActionTaskUtils.sendEvent(playerUser, new UserBoard(board , playerUser.getId() , "play"));
}
CacheHelper.getGameRoomCacheBean().put(gameRoom.getId(), gameRoom, gameRoom.getOrgi());
/**
* 发送一个 Begin 事件
*/
super.getGame(gameRoom.getPlayway(), orgi).change(gameRoom , BeiMiGameEvent.AUTO.toString() , 2); //通知状态机 , 此处应由状态机处理异步执行
}
}
@@ -0,0 +1,129 @@
package com.beimi.core.engine.game.task.dizhu;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.ActionTaskUtils;
import com.beimi.core.engine.game.BeiMiGameEvent;
import com.beimi.core.engine.game.BeiMiGameTask;
import com.beimi.core.engine.game.GameBoard;
import com.beimi.core.engine.game.task.AbstractTask;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.rules.model.DuZhuBoard;
import com.beimi.util.rules.model.Player;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
/**
* 抢地主
* @author iceworld
*
*/
public class CreateAutoTask extends AbstractTask implements BeiMiGameTask{
private long timer ;
private GameRoom gameRoom = null ;
private String orgi ;
public CreateAutoTask(long timer , GameRoom gameRoom, String orgi){
super();
this.timer = timer ;
this.gameRoom = gameRoom ;
this.orgi = orgi ;
}
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+timer*1000; //5秒后执行
}
public void execute(){
DuZhuBoard board = (DuZhuBoard) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
Player randomCardPlayer = null , catchPlayer = null;
int index = 0 ;
if(board!=null){
/**
* 抢地主,首个抢地主的人 在发牌的时候已经生成
*/
for(int i=0 ; i<board.getPlayers().length ; i++){
Player player = board.getPlayers()[i] ;
if(player.isRandomcard()){
randomCardPlayer = player ;
index = i;
break ;
}
}
if(randomCardPlayer.isDocatch()){
catchPlayer = board.next(index);
}else{
catchPlayer = randomCardPlayer;
}
/**
* 第二次抢地主条件:
* 1、抓到随机牌的人
* 2、已经叫过一次地主了
* 3、其他有人抢了地主
* 4、首次地主选择 了 叫地主
*/
if(catchPlayer == null){
/**
* 抓到随机牌的人如果选择了不叫地主,则二次选择的玩家是下一个 抢了地主的玩家
*/
if(randomCardPlayer.isRecatch() == false && !board.getBanker().equals(randomCardPlayer.getPlayuser()) && randomCardPlayer.isAccept()){
catchPlayer = randomCardPlayer ; //起到地主牌的人第二次抢地主 , 抢完就结束了
randomCardPlayer.setRecatch(true);
}else if(board.getBanker() == null){
//流局了
}else if(!StringUtils.isBlank(board.getBanker()) && randomCardPlayer.isAccept() == false && randomCardPlayer.isDocatch()){
//下一个抢地主的人
Player temp = board.nextPlayer(index) ;
if(temp.isAccept() && temp.isRecatch() == false){
catchPlayer = temp ;
temp.setRecatch(true);
}
}
}
}
/**
* 地主抢完了即可进入玩牌的流程了,否则,一直发送 AUTO事件,进行抢地主
*/
if(catchPlayer!=null){
catchPlayer.setDocatch(true);//抢过了
// board.setBanker(catchPlayer.getPlayuser()); //玩家 点击 抢地主按钮后 赋值
sendEvent("catch", new GameBoard(catchPlayer.getPlayuser() , board.isDocatch() , catchPlayer.isAccept() , board.getRatio()), gameRoom) ;
boolean isNormal = true ;
List<PlayUserClient> users = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), orgi) ;
for(PlayUserClient playUser : users){
if(catchPlayer.getPlayuser().equals(playUser.getId())){
if(!playUser.getPlayertype().equals(BMDataContext.PlayerTypeEnum.NORMAL.toString())){
//AI或托管,自动抢地主,后台配置 自动抢地主的触发时间,或者 抢还是不抢, 无配置的情况下,默认的是抢地主
isNormal = false ;
/**
* 根据 配置参数获取是否选择叫地主
*/
board = ActionTaskUtils.doCatch(board, catchPlayer , true) ;
break ;
}
}
}
if(isNormal){ //真人
super.getGame(gameRoom.getPlayway(), orgi).change(gameRoom , BeiMiGameEvent.AUTO.toString() , 17); //通知状态机 , 此处应由状态机处理异步执行
}else{ //AI或托管
sendEvent("catchresult", new GameBoard(catchPlayer.getPlayuser() , catchPlayer.isAccept(), catchPlayer.isAccept() , board.getRatio()) , gameRoom) ;
super.getGame(gameRoom.getPlayway(), orgi).change(gameRoom , BeiMiGameEvent.AUTO.toString() , 2); //通知状态机 , 此处应由状态机处理异步执行
board.setDocatch(true); //变成抢地主
}
CacheHelper.getBoardCacheBean().put(gameRoom.getId(), board, orgi);
}else{
//开始打牌,地主的人是最后一个抢了地主的人
super.getGame(gameRoom.getPlayway(), orgi).change(gameRoom , BeiMiGameEvent.RAISEHANDS.toString()); //通知状态机 , 全部都抢过地主了 , 把底牌发给 最后一个抢到地主的人
}
}
}
@@ -0,0 +1,40 @@
package com.beimi.core.engine.game.task.dizhu;
import org.cache2k.expiry.ValueWithExpiryTime;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.BeiMiGameTask;
import com.beimi.core.engine.game.task.AbstractTask;
import com.beimi.web.model.GameRoom;
/**
* 出牌计时器,默认25秒,超时执行
* @author zhangtianyi
*
*/
public class CreatePlayCardsTask extends AbstractTask implements ValueWithExpiryTime , BeiMiGameTask{
private long timer ;
private GameRoom gameRoom = null ;
private String orgi ;
private String player ;
public CreatePlayCardsTask(long timer ,String userid, GameRoom gameRoom, String orgi){
super();
this.timer = timer ;
this.gameRoom = gameRoom ;
this.orgi = orgi ;
this.player = userid ;
}
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+timer*1000; //5秒后执行
}
public void execute(){
/**
* 合并代码,玩家 出牌超时处理和 玩家出牌统一使用一处代码
*/
BMDataContext.getGameEngine().takeCardsRequest(this.gameRoom.getId(), this.player, orgi,true, null);
}
}
@@ -0,0 +1,84 @@
package com.beimi.core.engine.game.task.dizhu;
import java.util.Arrays;
import org.apache.commons.lang.ArrayUtils;
import org.cache2k.expiry.ValueWithExpiryTime;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.ActionTaskUtils;
import com.beimi.core.engine.game.BeiMiGameEvent;
import com.beimi.core.engine.game.BeiMiGameTask;
import com.beimi.core.engine.game.GameBoard;
import com.beimi.core.engine.game.task.AbstractTask;
import com.beimi.util.GameUtils;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.rules.model.DuZhuBoard;
import com.beimi.util.rules.model.NextPlayer;
import com.beimi.util.rules.model.Player;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
public class CreateRaiseHandsTask extends AbstractTask implements ValueWithExpiryTime , BeiMiGameTask{
private long timer ;
private GameRoom gameRoom = null ;
private String orgi ;
public CreateRaiseHandsTask(long timer , GameRoom gameRoom, String orgi){
super();
this.timer = timer ;
this.gameRoom = gameRoom ;
this.orgi = orgi ;
}
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+timer*1000; //5秒后执行
}
public void execute(){
/**
*
* 顺手 把牌发了,注:此处应根据 GameRoom的类型获取 发牌方式
*/
DuZhuBoard board = (DuZhuBoard) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
Player lastHandsPlayer = null ;
for(Player player : board.getPlayers()){
if(player.getPlayuser().equals(board.getBanker())){//抢到地主的人
byte[] lastHands = board.pollLastHands() ;
board.setLasthands(lastHands);
board.setNextplayer(new NextPlayer(player.getPlayuser(), false));
player.setCards(ArrayUtils.addAll(player.getCards(), lastHands)) ;//翻底牌
Arrays.sort(player.getCards()); //重新排序
player.setCards(GameUtils.reverseCards(player.getCards())); //从大到小 倒序
lastHandsPlayer = player ;
break ;
}
}
/**
* 计算底牌倍率
*/
board.setRatio(board.getRatio() * board.calcRatio());
/**
* 发送一个通知,翻底牌消息
*/
sendEvent("lasthands", new GameBoard(lastHandsPlayer.getPlayuser() , board.getLasthands(), board.getRatio()) , gameRoom) ;
/**
* 更新牌局状态
*/
CacheHelper.getBoardCacheBean().put(gameRoom.getId(), board, orgi);
/**
* 发送一个 开始打牌的事件 , 判断当前出牌人是 玩家还是 AI,如果是 AI,则默认 1秒时间,如果是玩家,则超时时间是25秒
*/
PlayUserClient playUserClient = ActionTaskUtils.getPlayUserClient(gameRoom.getId(), lastHandsPlayer.getPlayuser(), orgi) ;
if(BMDataContext.PlayerTypeEnum.NORMAL.toString().equals(playUserClient.getPlayertype())){
super.getGame(gameRoom.getPlayway(), orgi).change(gameRoom , BeiMiGameEvent.PLAYCARDS.toString() , 25); //应该从 游戏后台配置参数中获取
}else{
super.getGame(gameRoom.getPlayway(), orgi).change(gameRoom , BeiMiGameEvent.PLAYCARDS.toString() ,3); //应该从游戏后台配置参数中获取
}
}
}
@@ -0,0 +1,41 @@
package com.beimi.core.engine.game.task.majiang;
import org.cache2k.expiry.ValueWithExpiryTime;
import com.beimi.core.engine.game.BeiMiGameTask;
import com.beimi.core.engine.game.task.AbstractTask;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.rules.model.Board;
import com.beimi.web.model.GameRoom;
/**
* 出牌计时器,默认25秒,超时执行
* @author zhangtianyi
*
*/
public class CreateDealMJCardTask extends AbstractTask implements ValueWithExpiryTime , BeiMiGameTask{
private long timer ;
private GameRoom gameRoom = null ;
private String orgi ;
public CreateDealMJCardTask(long timer , GameRoom gameRoom, String orgi){
super();
this.timer = timer ;
this.gameRoom = gameRoom ;
this.orgi = orgi ;
}
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+timer*1000; //5秒后执行
}
/**
* 杠碰吃胡 时间到 了,执行发牌动作
*/
public void execute(){
Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
if(board!=null){
board.dealRequest(gameRoom, board, orgi , false, null);
}
}
}
@@ -0,0 +1,40 @@
package com.beimi.core.engine.game.task.majiang;
import org.cache2k.expiry.ValueWithExpiryTime;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.BeiMiGameTask;
import com.beimi.core.engine.game.task.AbstractTask;
import com.beimi.web.model.GameRoom;
/**
* 出牌计时器,默认25秒,超时执行
* @author zhangtianyi
*
*/
public class CreateMJPlayCardsTask extends AbstractTask implements ValueWithExpiryTime , BeiMiGameTask{
private long timer ;
private GameRoom gameRoom = null ;
private String orgi ;
private String player ;
public CreateMJPlayCardsTask(long timer ,String userid, GameRoom gameRoom, String orgi){
super();
this.timer = timer ;
this.gameRoom = gameRoom ;
this.orgi = orgi ;
this.player = userid ;
}
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+timer*1000; //5秒后执行
}
public void execute(){
/**
* 合并代码,玩家 出牌超时处理和 玩家出牌统一使用一处代码
*/
BMDataContext.getGameEngine().takeCardsRequest(this.gameRoom.getId(), this.player, orgi,true, null);
}
}
@@ -0,0 +1,79 @@
package com.beimi.core.engine.game.task.majiang;
import org.cache2k.expiry.ValueWithExpiryTime;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.ActionTaskUtils;
import com.beimi.core.engine.game.BeiMiGameEvent;
import com.beimi.core.engine.game.BeiMiGameTask;
import com.beimi.core.engine.game.GameBoard;
import com.beimi.core.engine.game.task.AbstractTask;
import com.beimi.util.GameUtils;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.rules.model.Board;
import com.beimi.util.rules.model.NextPlayer;
import com.beimi.util.rules.model.Player;
import com.beimi.util.rules.model.SelectColor;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
public class CreateMJRaiseHandsTask extends AbstractTask implements ValueWithExpiryTime , BeiMiGameTask{
private long timer ;
private GameRoom gameRoom = null ;
private String orgi ;
public CreateMJRaiseHandsTask(long timer , GameRoom gameRoom, String orgi){
super();
this.timer = timer ;
this.gameRoom = gameRoom ;
this.orgi = orgi ;
}
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+timer*1000; //5秒后执行
}
public void execute(){
/**
*
* 检查是否所有人都已经定缺,如果定缺完毕,则通知庄家开始出牌,如果有未完成定缺的,则自动选择
*/
Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
Player banker = null ;
for(Player player : board.getPlayers()){
if(player.getPlayuser().equals(board.getBanker())){
banker = player ;
}
if(!player.isSelected()){
SelectColor color = new SelectColor( board.getBanker(), player.getPlayuser()) ;
color.setColor(GameUtils.selectColor(player.getCards()));
ActionTaskUtils.sendEvent("selectresult" , color , gameRoom);
player.setColor(color.getColor());
player.setSelected(true);break ;
}
}
if(banker!=null){
board.setNextplayer(new NextPlayer(board.getBanker(), false));
CacheHelper.getBoardCacheBean().put(gameRoom.getId() , board, gameRoom.getOrgi()); //更新缓存数据
/**
* 发送一个通知,告诉大家 , 开始出牌了
*/
sendEvent("lasthands", new GameBoard(banker.getPlayuser(), board.getBanker() , board.getRatio()) , gameRoom) ;
/**
* 更新牌局状态
*/
CacheHelper.getBoardCacheBean().put(gameRoom.getId(), board, orgi);
/**
* 发送一个 开始打牌的事件 , 判断当前出牌人是 玩家还是 AI,如果是 AI,则默认 1秒时间,如果是玩家,则超时时间是25秒
*/
PlayUserClient playUserClient = ActionTaskUtils.getPlayUserClient(gameRoom.getId(), banker.getPlayuser(), orgi) ;
if(BMDataContext.PlayerTypeEnum.NORMAL.toString().equals(playUserClient.getPlayertype())){
super.getGame(gameRoom.getPlayway(), orgi).change(gameRoom , BeiMiGameEvent.PLAYCARDS.toString() , 8); //应该从 游戏后台配置参数中获取
}else{
super.getGame(gameRoom.getPlayway(), orgi).change(gameRoom , BeiMiGameEvent.PLAYCARDS.toString() ,3); //应该从游戏后台配置参数中获取
}
}
}
}
@@ -0,0 +1,71 @@
package com.beimi.core.engine.game.task.majiang;
import java.util.List;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.ActionTaskUtils;
import com.beimi.core.engine.game.BeiMiGameEvent;
import com.beimi.core.engine.game.BeiMiGameTask;
import com.beimi.core.engine.game.task.AbstractTask;
import com.beimi.util.GameUtils;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.rules.model.Board;
import com.beimi.util.rules.model.Player;
import com.beimi.util.rules.model.SelectColor;
import com.beimi.web.model.GameRoom;
import com.beimi.web.model.PlayUserClient;
/**
* 定缺
* @author iceworld
*
*/
public class CreateSelectTask extends AbstractTask implements BeiMiGameTask{
private long timer ;
private GameRoom gameRoom = null ;
private String orgi ;
public CreateSelectTask(long timer , GameRoom gameRoom, String orgi){
super();
this.timer = timer ;
this.gameRoom = gameRoom ;
this.orgi = orgi ;
}
@Override
public long getCacheExpiryTime() {
return System.currentTimeMillis()+timer*1000; //5秒后执行
}
public void execute(){
Board board = (Board) CacheHelper.getBoardCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi());
/**
* 通知状态机 , 大家开始定缺, 流程引导 , 可以通过配置选择是否需要此节点流程
*/
ActionTaskUtils.sendEvent("selectcolor" , new SelectColor(board.getBanker()) , gameRoom);
List<PlayUserClient> playerList = CacheHelper.getGamePlayerCacheBean().getCacheObject(gameRoom.getId(), gameRoom.getOrgi()) ;
for(PlayUserClient player : playerList){
if(!BMDataContext.PlayerTypeEnum.NORMAL.toString().equals(player.getPlayertype())){//AI定缺 并通知玩家
/**
* 定缺算法 , 万筒条
*/
for(Player ply : board.getPlayers()){
if(ply.getPlayuser().equals(player.getId())){
SelectColor color = new SelectColor( board.getBanker(), player.getId()) ;
color.setColor(GameUtils.selectColor(ply.getCards()));
ActionTaskUtils.sendEvent("selectresult" , color , gameRoom);
ply.setColor(color.getColor());
ply.setSelected(true);
break ;
}
}
}
}
CacheHelper.getBoardCacheBean().put(gameRoom.getId() , board, gameRoom.getOrgi()); //更新缓存数据
super.getGame(gameRoom.getPlayway(), orgi).change(gameRoom , BeiMiGameEvent.RAISEHANDS.toString());
}
}
@@ -0,0 +1,28 @@
package com.beimi.core.statemachine;
import com.beimi.core.statemachine.config.StateConfigurer;
import com.beimi.core.statemachine.config.StateMachineTransitionConfigurer;
import com.beimi.core.statemachine.impl.BeiMiStateContext;
import com.beimi.core.statemachine.impl.BeiMiTransitionConfigurer;
public class BeiMiStateMachine<T,S> {
/**
*
*/
private StateConfigurer<String,String> config = new BeiMiStateContext<String,String>();
private StateMachineTransitionConfigurer<T,S> transitions = new BeiMiTransitionConfigurer<T,S>() ;
public StateConfigurer<String,String> getConfig() {
return config;
}
public void setConfig(StateConfigurer<String,String> config) {
this.config = config;
}
public StateMachineTransitionConfigurer<T,S> getTransitions() {
return transitions;
}
public void setTransitions(
StateMachineTransitionConfigurer<T,S> transitions) {
this.transitions = transitions;
}
}
@@ -0,0 +1,8 @@
package com.beimi.core.statemachine.action;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
import com.beimi.core.statemachine.message.Message;
public interface Action<T,S> {
void execute(Message<T> message , BeiMiExtentionTransitionConfigurer<T, S> configurer);
}
@@ -0,0 +1,5 @@
package com.beimi.core.statemachine.config;
public interface AbstractTransitionConfigurer<I> {
I and() ;
}
@@ -0,0 +1,5 @@
package com.beimi.core.statemachine.config;
public class DefaultStateConfigurer {
}
@@ -0,0 +1,6 @@
package com.beimi.core.statemachine.config;
public interface ExternalTransitionConfigurer<S,E> extends TransitionConfigurer<ExternalTransitionConfigurer<S, E>, S, E>{
public ExternalTransitionConfigurer<S, E> target(S target);
}
@@ -0,0 +1,23 @@
package com.beimi.core.statemachine.config;
public interface StateConfigurer<S, E> {
/**
* Specify a initial state {@code S}.
*
* @param initial the initial state
* @return configurer for chaining
*/
StateConfigurer<S, E> initial(S initial);
/**
* Specify a state {@code S}.
*
* @param state the state
* @return configurer for chaining
*/
StateConfigurer<S, E> state(S state);
StateConfigurer<S, E> withStates() throws Exception;
}
@@ -0,0 +1,11 @@
package com.beimi.core.statemachine.config;
public interface StateMachineStateConfigurer<S , E> {
/**
* Gets a configurer for states.
*
* @return {@link StateConfigurer} for chaining
* @throws Exception if configuration error happens
*/
StateConfigurer<S, E> withStates() throws Exception;
}
@@ -0,0 +1,19 @@
package com.beimi.core.statemachine.config;
import com.beimi.core.statemachine.impl.BeiMiExtentionTransitionConfigurer;
public interface StateMachineTransitionConfigurer<S,E> {
/**
* Gets a configurer for external transition.
*
* @return {@link ExternalTransitionConfigurer} for chaining
* @throws Exception if configuration error happens
* @see #withLocal()
*/
ExternalTransitionConfigurer<S, E> withExternal() throws Exception;
void apply(BeiMiExtentionTransitionConfigurer<S, E> transition);
BeiMiExtentionTransitionConfigurer<S,E> transition(S event) ;
}
@@ -0,0 +1,46 @@
package com.beimi.core.statemachine.config;
import com.beimi.core.statemachine.action.Action;
public interface TransitionConfigurer<T, S, E> extends AbstractTransitionConfigurer<StateMachineTransitionConfigurer<S, E>>{
/**
* Specify a source state {@code S} for this {@link Transition}.
*
* @param source the source state {@code S}
* @return configurer for chaining
*/
T source(S source);
/**
*
* @param target
* @return
*/
T target(S target);
/**
* Specify event {@code E} for this {@link Transition} which will be triggered
* by a event trigger.
*
* @param event the event for transition
* @return configurer for chaining
*/
T event(E event);
/**
* Specify {@link Action} for this {@link Transition}.
*
* @param action the action
* @return configurer for chaining
*/
T action(Action<S, E> action);
/**
* Specify {@link Action} for this {@link Transition}.
*
* @param action the action
* @param error action that will be called if any unexpected exception is thrown by the action.
* @return configurer for chaining
*/
T action(Action<S, E> action, Action<S, E> error);
}
@@ -0,0 +1,9 @@
package com.beimi.core.statemachine.context;
public class StateContext<T,S> {
public String getMessageHeader(String string) {
return null;
}
}
@@ -0,0 +1,102 @@
package com.beimi.core.statemachine.impl;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.config.ExternalTransitionConfigurer;
import com.beimi.core.statemachine.config.StateMachineTransitionConfigurer;
public class BeiMiExtentionTransitionConfigurer<T, S> implements ExternalTransitionConfigurer<T, S>{
private StateMachineTransitionConfigurer<T, S> configure ;
private T source = null , target = null ;
private S event = null;
private Action<T, S> action = null , errorAction = null;
public BeiMiExtentionTransitionConfigurer(StateMachineTransitionConfigurer<T, S> configure){
this.configure = configure ;
}
@Override
public ExternalTransitionConfigurer<T, S> source(T source) {
this.source = source ;
return this;
}
@Override
public ExternalTransitionConfigurer<T, S> event(S event) {
this.event = event ;
return this;
}
@Override
public ExternalTransitionConfigurer<T, S> action(Action<T, S> action) {
this.action = action;
return this;
}
@Override
public ExternalTransitionConfigurer<T, S> action(Action<T, S> action,
Action<T, S> error) {
this.action = action;
this.errorAction = error ;
return null;
}
@Override
public StateMachineTransitionConfigurer<T, S> and() {
configure.apply(this);
return configure;
}
@Override
public ExternalTransitionConfigurer<T, S> target(T target) {
this.target = target ;
return this;
}
public StateMachineTransitionConfigurer<T, S> getConfigure() {
return configure;
}
public void setConfigure(StateMachineTransitionConfigurer<T, S> configure) {
this.configure = configure;
}
public T getSource() {
return source;
}
public void setSource(T source) {
this.source = source;
}
public T getTarget() {
return target;
}
public void setTarget(T target) {
this.target = target;
}
public S getEvent() {
return event;
}
public void setEvent(S event) {
this.event = event;
}
public Action<T, S> getAction() {
return action;
}
public void setAction(Action<T, S> action) {
this.action = action;
}
public Action<T, S> getErrorAction() {
return errorAction;
}
public void setErrorAction(Action<T, S> errorAction) {
this.errorAction = errorAction;
}
}
@@ -0,0 +1,52 @@
package com.beimi.core.statemachine.impl;
import org.apache.log4j.Logger;
import com.beimi.core.statemachine.BeiMiStateMachine;
import com.beimi.core.statemachine.action.Action;
import com.beimi.core.statemachine.message.Message;
/**
*
* @author chenghao
*
*/
public class BeiMiMachineHandler {
private BeiMiStateMachine<String,String> config ;
public BeiMiMachineHandler(BeiMiStateMachine<String,String> config){
this.config = config ;
}
/**
* Handle event with entity.
* 1、获得当前事件的Transition
* 2、处理Action
* 3、校验当前状态是否是从 上一个状态 转变来的(不做实现)
* 4、变更状态到下一步
*
* @param event the event
* @param state the state
* @return true if event was accepted
*/
public boolean handleEventWithState(Message<String> event, String state) {
BeiMiExtentionTransitionConfigurer<String, String> transition = config.getTransitions().transition(state) ;
if(transition!=null){
Action<String, String> action = transition.getAction() ;
if(action!=null){
/**
* 1、任务的执行应该为异步执行,可以考虑放入 RingBuffer中处理
* 2、启用异步线程并增加线程池处理
*/
action.execute(event , transition);
/**
* 修改当前状态,并持久化
*/
}else{
//抛出异常
Logger.getLogger(this.getClass()).info("Transition's Action is null");
}
}
return config!=null;
}
}
@@ -0,0 +1,44 @@
package com.beimi.core.statemachine.impl;
import java.util.LinkedList;
import com.beimi.core.statemachine.config.StateConfigurer;
public class BeiMiStateContext<T,S> implements StateConfigurer<T,S>{
private LinkedList<T> stateContextList = new LinkedList<T>();
private T initial ; //初始状态
@Override
public StateConfigurer<T,S> initial(T initial) {
this.initial = initial ;
this.stateContextList.add(initial) ; //首个元素
return this;
}
@Override
public StateConfigurer<T,S> state(T state) {
this.stateContextList.add(state) ;
return this;
}
@Override
public StateConfigurer<T,S> withStates() throws Exception {
return this;
}
public LinkedList<T> getStateContextList() {
return stateContextList;
}
public void setStateContextList(LinkedList<T> stateContextList) {
this.stateContextList = stateContextList;
}
public T getInitial() {
return initial;
}
public void setInitial(T initial) {
this.initial = initial;
}
}
@@ -0,0 +1,27 @@
package com.beimi.core.statemachine.impl;
import java.util.HashMap;
import java.util.Map;
import com.beimi.core.statemachine.config.ExternalTransitionConfigurer;
import com.beimi.core.statemachine.config.StateMachineTransitionConfigurer;
public class BeiMiTransitionConfigurer<T,S> implements StateMachineTransitionConfigurer<T,S>{
private Map<S, BeiMiExtentionTransitionConfigurer<T, S>> transitions = new HashMap<S,BeiMiExtentionTransitionConfigurer<T,S>>();
@Override
public ExternalTransitionConfigurer<T, S> withExternal() throws Exception {
return new BeiMiExtentionTransitionConfigurer<T, S>(this);
}
@Override
public void apply(BeiMiExtentionTransitionConfigurer<T, S> transition) {
transitions.put(transition.getEvent(), transition);
}
@Override
public BeiMiExtentionTransitionConfigurer<T, S> transition(T event) {
return transitions.get(event);
}
}
@@ -0,0 +1,57 @@
package com.beimi.core.statemachine.impl;
import com.beimi.core.statemachine.message.GenericMessage;
import com.beimi.core.statemachine.message.Message;
import com.beimi.core.statemachine.message.MessageHeaders;
/**
* The default message builder; creates immutable {@link GenericMessage}s.
* Named MessageBuilder instead of DefaultMessageBuilder for backwards
* compatibility.
*
* @author Arjen Poutsma
* @author Mark Fisher
* @author Oleg Zhurakousky
* @author Dave Syer
* @author Gary Russell
* @author Artem Bilan
*/
public final class MessageBuilder<T> {
private final T payload;
private MessageHeaders readOnlyHeaders = new MessageHeaders();
/**
* Private constructor to be invoked from the static factory methods only.
*/
private MessageBuilder(T payload) {
this.payload = payload;
}
public T getPayload() {
return this.payload;
}
public MessageBuilder<T> setHeader(String headerName, Object headerValue) {
this.readOnlyHeaders.getHeaders().put(headerName, headerValue) ;
return this;
}
/**
* Create a builder for a new {@link Message} instance with the provided payload.
*
* @param payload the payload for the new message
* @param <T> The type of the payload.
* @return A MessageBuilder.
*/
public static <T> MessageBuilder<T> withPayload(T payload) {
return new MessageBuilder<T>(payload);
}
public Message<T> build() {
return new GenericMessage<T>(this.payload, this.readOnlyHeaders);
}
}
@@ -0,0 +1,33 @@
package com.beimi.core.statemachine.message;
import java.io.Serializable;
import java.util.Map;
public class GenericMessage<T> implements Message<T>, Serializable {
/**
*
*/
private static final long serialVersionUID = 663603304301142068L;
private final T payload;
private final MessageHeaders headers;
public GenericMessage(T payload, Map<String, Object> headers) {
this(payload, new MessageHeaders(headers));
}
public GenericMessage(T payload, MessageHeaders headers) {
this.payload = payload;
this.headers = headers;
}
public MessageHeaders getMessageHeaders() {
return headers;
}
@Override
public T getPayload() {
return payload;
}
}
@@ -0,0 +1,16 @@
package com.beimi.core.statemachine.message;
public interface Message<T> {
/**
* Return the message payload.
*/
T getPayload();
/**
* Return message headers for the message (never {@code null} but may be empty).
*/
MessageHeaders getMessageHeaders();
}
@@ -0,0 +1,24 @@
package com.beimi.core.statemachine.message;
import java.util.HashMap;
import java.util.Map;
public class MessageHeaders {
private final Map<String, Object> headers ;
public MessageHeaders(){
this.headers = new HashMap<String, Object>() ;
}
public MessageHeaders(Map<String, Object> headers){
if(headers!=null){
this.headers = headers ;
}else{
this.headers = new HashMap<String, Object>() ;
}
}
public Map<String, Object> getHeaders() {
return headers;
}
}
+49
View File
@@ -0,0 +1,49 @@
package com.beimi.util;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
public class Base62 {
private static final int BINARY = 0x2;
private static final int NUMBER_61 = 0x0000003d;
static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z' };
public static String encode(long value){
return encode(String.valueOf(value)).toLowerCase() ;
}
public static String encode(String str){
String md5Hex = DigestUtils.md5Hex(str);
// 6 digit binary can indicate 62 letter & number from 0-9a-zA-Z
int binaryLength = 6 * 6;
long binaryLengthFixer = Long.valueOf(StringUtils.repeat("1", binaryLength), BINARY);
for (int i = 0; i < 4;) {
String subString = StringUtils.substring(md5Hex, i * 8, (i + 1) * 8);
subString = Long.toBinaryString(Long.valueOf(subString, 16) & binaryLengthFixer);
subString = StringUtils.leftPad(subString, binaryLength, "0");
StringBuilder sbBuilder = new StringBuilder();
for (int j = 0; j < 6; j++) {
String subString2 = StringUtils.substring(subString, j * 6, (j + 1) * 6);
int charIndex = Integer.valueOf(subString2, BINARY) & NUMBER_61;
sbBuilder.append(DIGITS[charIndex]);
}
String shortUrl = sbBuilder.toString();
if(shortUrl!=null){
return shortUrl;
}
}
// if all 4 possibilities are already exists
return null;
}
@SuppressWarnings("unused")
private static void print(Object messagr){
System.out.println(messagr);
}
}
@@ -0,0 +1,40 @@
package com.beimi.util;
public class BrowserClient {
private String useragent ;
private String os ;
private String browser ;
private String version ;
private String osversion ;
public String getUseragent() {
return useragent;
}
public void setUseragent(String useragent) {
this.useragent = useragent;
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public String getBrowser() {
return browser;
}
public void setBrowser(String browser) {
this.browser = browser;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getOsversion() {
return osversion;
}
public void setOsversion(String osversion) {
this.osversion = osversion;
}
}
@@ -0,0 +1,64 @@
package com.beimi.util;
import java.util.List;
import com.beimi.core.BMDataContext;
import com.beimi.util.cache.CacheHelper;
import com.beimi.web.model.AccountConfig;
import com.beimi.web.model.AiConfig;
import com.beimi.web.model.GameConfig;
import com.beimi.web.service.repository.jpa.AccountConfigRepository;
import com.beimi.web.service.repository.jpa.AiConfigRepository;
import com.beimi.web.service.repository.jpa.GameConfigRepository;
/**
* 用于获取缓存配置
* @author iceworld
*
*/
public class CacheConfigTools {
public static AccountConfig getGameAccountConfig(String orgi){
AccountConfig config = (AccountConfig) CacheHelper.getSystemCacheBean().getCacheObject(BMDataContext.getGameAccountConfig(orgi), orgi) ;
if(config == null){
AccountConfigRepository accountRes = BMDataContext.getContext().getBean(AccountConfigRepository.class) ;
List<AccountConfig> gameAccountList = accountRes.findByOrgi(orgi) ;
if(gameAccountList!=null && gameAccountList.size() >0){
config = gameAccountList.get(0) ;
}else{
config = new AccountConfig() ;
}
CacheHelper.getSystemCacheBean().put(BMDataContext.getGameAccountConfig(orgi), config, orgi);
}
return config;
}
public static GameConfig getGameConfig(String orgi){
GameConfig config = (GameConfig) CacheHelper.getSystemCacheBean().getCacheObject(BMDataContext.getGameConfig(orgi), orgi) ;
if(config == null){
GameConfigRepository gameConfigRes = BMDataContext.getContext().getBean(GameConfigRepository.class) ;
List<GameConfig> gameConfigList = gameConfigRes.findByOrgi(orgi) ;
if(gameConfigList!=null && gameConfigList.size() >0){
config = gameConfigList.get(0) ;
}else{
config = new GameConfig() ;
}
CacheHelper.getSystemCacheBean().put(BMDataContext.getGameConfig(orgi), config, orgi);
}
return config;
}
public static AiConfig getAiConfig(String orgi){
AiConfig config = (AiConfig) CacheHelper.getSystemCacheBean().getCacheObject(BMDataContext.getGameAiConfig(orgi), orgi) ;
if(config == null){
AiConfigRepository aiConfigRes = BMDataContext.getContext().getBean(AiConfigRepository.class) ;
List<AiConfig> gameAccountList = aiConfigRes.findByOrgi(orgi) ;
if(gameAccountList!=null && gameAccountList.size() >0){
config = gameAccountList.get(0) ;
}else{
config = new AiConfig() ;
}
CacheHelper.getSystemCacheBean().put(BMDataContext.getGameAiConfig(orgi), config, orgi);
}
return config;
}
}
@@ -0,0 +1,52 @@
package com.beimi.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 检测是否为移动端设备访问 , 网络共享源码
*
* @author : Cuichenglong
* @group : tgb8
* @Version : 1.00
* @Date : 2014-7-7 下午01:34:31
*/
public class CheckMobile {
// \b 是单词边界(连着的两个(字母字符 与 非字母字符) 之间的逻辑上的间隔),
// 字符串在编译时会被转码一次,所以是 "\\b"
// \B 是单词内部逻辑间隔(连着的两个字母字符之间的逻辑上的间隔)
static String phoneReg = "\\b(ip(hone|od)|android|opera m(ob|in)i"
+"|windows (phone|ce)|blackberry"
+"|s(ymbian|eries60|amsung)|p(laybook|alm|rofile/midp"
+"|laystation portable)|nokia|fennec|htc[-_]"
+"|mobile|up.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
static String tableReg = "\\b(ipad|tablet|(Nexus 7)|up.browser"
+"|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
//移动设备正则匹配:手机端、平板
static Pattern phonePat = Pattern.compile(phoneReg, Pattern.CASE_INSENSITIVE);
static Pattern tablePat = Pattern.compile(tableReg, Pattern.CASE_INSENSITIVE);
/**
* 检测是否是移动设备访问
*
* @Title: check
* @Date : 2014-7-7 下午01:29:07
* @param userAgent 浏览器标识
* @return true:移动设备接入,false:pc端接入
*/
public static boolean check(String userAgent){
if(null == userAgent){
userAgent = "";
}
// 匹配
Matcher matcherPhone = phonePat.matcher(userAgent);
Matcher matcherTable = tablePat.matcher(userAgent);
if(matcherPhone.find() || matcherTable.find()){
return true;
} else {
return false;
}
}
}
@@ -0,0 +1,40 @@
package com.beimi.util;
import java.util.Date;
import org.apache.commons.beanutils.converters.DateTimeConverter;
public class DateConverter extends DateTimeConverter {
public DateConverter() {
}
public DateConverter(Object defaultValue) {
super(defaultValue);
}
/* (non-Javadoc)
* @see org.apache.commons.beanutils.converters.AbstractConverter#getDefaultType()
*/
@SuppressWarnings("rawtypes")
protected Class getDefaultType() {
return Date.class;
}
/*
* (non-Javadoc)
* @see org.apache.commons.beanutils.converters.DateTimeConverter#convertToType(java.lang.Class, java.lang.Object)
*/
@SuppressWarnings("rawtypes")
@Override
protected Object convertToType(Class arg0, Object arg1) throws Exception {
if (arg1 == null) {
return null;
}
String value = arg1.toString().trim();
if (value.length() == 0) {
return null;
}
return super.convertToType(arg0, arg1);
}
}
@@ -0,0 +1,155 @@
package com.beimi.util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.LoggerFactory;
public class FFmpegCmdExecuter {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(FFmpegCmdExecuter.class);
public static String FFMPEG = "ffmpeg";
/**
* mp3 to amr
* @param src
* @param dest
*/
public static void mp3ToAmr(String src ,String dest){
logger.info("mp3 to amr:" + dest);
List<String> cmd = new ArrayList<String>();
cmd.add(FFMPEG);
cmd.add("-i");
cmd.add(src);
cmd.add("-ac");
cmd.add("1");
cmd.add("-ar");
cmd.add("8000");
cmd.add(dest);
exec(cmd);
}
/**
* wav to mp3
* @param src
* @param dest
*/
public static void wavToMp3(String src,String dest){
logger.info("wav to mp3:"+dest);
List<String> cmd = new ArrayList<String>();
cmd.add(FFMPEG);
cmd.add("-i");
cmd.add(src);
cmd.add("-acodec");
cmd.add("libmp3lame");
cmd.add(dest);
exec(cmd);
}
/**
* amr to mp3
* @param src
* @param dest
*/
public static void amrToMp3(String src ,String dest){
logger.info("amr to mp3:"+dest);
List<String> cmd = new ArrayList<String>();
cmd.add(FFMPEG);
cmd.add("-i");
cmd.add(src);
cmd.add(dest);
exec(cmd);
}
/**
* ִָ
* @param cmd ִָ
*/
public static void exec( List<String> cmd){
BufferedReader stdout = null;
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(cmd);
builder.redirectErrorStream(true);
Process proc = builder.start();
stdout = new BufferedReader(
new InputStreamReader(proc.getInputStream()));
String line;
while ((line = stdout.readLine()) != null) {
logger.debug(line);
}
proc.waitFor();
} catch (Exception e) {
e.printStackTrace();
}finally{
IOUtils.closeQuietly(stdout);
}
}
/**
* ˮӡͼƬƵˮӡ
* @param src
* @param dest
* @param water
* @param wmPosition
* @param alpha
* @param wmPosition
* @return
*/
public static void videoWater(String src,String dest,String water,int wmPosition, float alpha,String platform) {
List<String> cmd = new ArrayList<String>();
cmd.add(FFMPEG);
cmd.add("-i");
cmd.add(src);
cmd.add("-i");
cmd.add(water);
cmd.add("-filter_complex");
cmd.add("''overlay=main_w-overlay_w:main_h-overlay_h''");
cmd.add("-strict");
cmd.add("-2");
if(NumberUtils.toInt(platform, 0)==3){
cmd.add("-ar");
cmd.add("8000");
}
cmd.add("-b");
cmd.add("877k");
cmd.add("-qscale");
cmd.add("0.01");
//ios
cmd.add("-movflags");
cmd.add("faststart");
cmd.add(dest);
exec(cmd);
}
/**
* ˮӡͼƬƵˮӡ
* @param src
* @param dest
*/
public static void videoPic(String src,String dest) {
List<String> cmd = new ArrayList<String>();
cmd.add(FFMPEG);
cmd.add("-i");
cmd.add(src);
cmd.add("-ss");
cmd.add("-00:00:01");
cmd.add("-vframes");
cmd.add("1");
cmd.add(dest);
exec(cmd);
}
}
+630
View File
@@ -0,0 +1,630 @@
package com.beimi.util;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.beimi.web.model.*;
import com.beimi.web.service.repository.jpa.GamePlaywayGroupItemRepository;
import com.beimi.web.service.repository.jpa.GamePlaywayGroupRepository;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Sort;
import com.beimi.config.web.model.Game;
import com.beimi.core.BMDataContext;
import com.beimi.core.engine.game.BeiMiGame;
import com.beimi.core.engine.game.iface.ChessGame;
import com.beimi.core.engine.game.impl.DizhuGame;
import com.beimi.core.engine.game.impl.MaJiangGame;
import com.beimi.core.engine.game.model.MJCardMessage;
import com.beimi.core.engine.game.model.Playway;
import com.beimi.core.engine.game.model.Type;
import com.beimi.util.cache.CacheHelper;
import com.beimi.util.rules.model.Action;
import com.beimi.util.rules.model.Board;
import com.beimi.util.rules.model.Player;
import com.beimi.web.service.repository.jpa.GamePlaywayRepository;
public class GameUtils {
private static Map<String,ChessGame> games = new HashMap<String,ChessGame>();
static{
games.put("dizhu", new DizhuGame()) ;
games.put("majiang", new MaJiangGame()) ;
}
public static Game getGame(String playway ,String orgi){
GamePlayway gamePlayway = (GamePlayway) CacheHelper.getSystemCacheBean().getCacheObject(playway, orgi) ;
Game game = null ;
if(gamePlayway!=null){
SysDic dic = (SysDic) CacheHelper.getSystemCacheBean().getCacheObject(gamePlayway.getGame(), gamePlayway.getOrgi()) ;
if(dic.getCode().equals("dizhu") || gamePlayway.getCode().equals("dizhu")){
game = (Game) BMDataContext.getContext().getBean("dizhuGame") ;
}else if(dic.getCode().equals("majiang") || gamePlayway.getCode().equals("majiang")){
game = (Game) BMDataContext.getContext().getBean("majiangGame") ;
}
}
return game;
}
/**
* 移除GameRoom
* @param gameRoom
* @param orgi
*/
public static void removeGameRoom(String roomid,String playway,String orgi){
CacheHelper.getQueneCache().delete(roomid);
}
/**
* 更新玩家状态
* @param userid
* @param orgi
*/
public static void updatePlayerClientStatus(String userid , String orgi , String status){
PlayUserClient playUser = (PlayUserClient) CacheHelper.getApiUserCacheBean().getCacheObject(userid, orgi) ;
if(playUser!=null){
playUser.setPlayertype(status);//托管玩家
CacheHelper.getApiUserCacheBean().put(userid,playUser , orgi);
if(playUser!=null && !BMDataContext.GameStatusEnum.PLAYING.toString().equals(playUser.getGamestatus())){
playUser = (PlayUserClient) CacheHelper.getGamePlayerCacheBean().getPlayer(userid, orgi) ;
CacheHelper.getGamePlayerCacheBean().delete(userid, orgi) ;
CacheHelper.getRoomMappingCacheBean().delete(userid, orgi) ;
/**
* 检查,如果房间没 真人玩家了或者当前玩家是房主 ,就可以解散房间了
*/
if(playUser!= null && !StringUtils.isBlank(playUser.getRoomid())){
GameRoom gameRoom = (GameRoom) CacheHelper.getGameRoomCacheBean().getCacheObject(playUser.getRoomid(), orgi) ;
if(gameRoom.getMaster().equals(playUser.getId())){
/**
* 解散房间,应该需要一个专门的 方法来处理,别直接删缓存了,这样不好!!!
*/
BMDataContext.getGameEngine().dismissRoom(gameRoom, userid, orgi);
}
}
}
}
}
/**
* 创建一个AI玩家
* @param player
* @return
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static PlayUserClient create(PlayUser player,String playertype) {
return create(player, null , null , playertype) ;
}
/**
* 开始游戏,根据玩法创建游戏 对局
* @return
*/
public static Board playGame(List<PlayUserClient> playUsers , GameRoom gameRoom , String banker , int cardsnum){
Board board = null ;
GamePlayway gamePlayWay = (GamePlayway) CacheHelper.getSystemCacheBean().getCacheObject(gameRoom.getPlayway(), gameRoom.getOrgi()) ;
if(gamePlayWay!=null){
ChessGame chessGame = games.get(gamePlayWay.getCode());
if(chessGame!=null){
board = chessGame.process(playUsers, gameRoom, gamePlayWay , banker, cardsnum);
}
}
return board;
}
/**
* 创建一个普通玩家
* @param player
* @return
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static PlayUserClient create(PlayUser player , IP ipdata , HttpServletRequest request ) throws IllegalAccessException, InvocationTargetException{
return create(player, ipdata, request, BMDataContext.PlayerTypeEnum.NORMAL.toString()) ;
}
public static byte[] reverseCards(byte[] cards) {
byte[] target_cards = new byte[cards.length];
for (int i = 0; i < cards.length; i++) {
// 反转后数组的第一个元素等于源数组的最后一个元素:
target_cards[i] = cards[cards.length - i - 1];
}
return target_cards;
}
/**
* 注册用户
* @param player
* @return
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static PlayUserClient create(PlayUser player , IP ipdata , HttpServletRequest request , String playertype){
PlayUserClient playUserClient = null ;
if(player!= null){
if(StringUtils.isBlank(player.getUsername())){
player.setUsername("Guest_"+Base62.encode(UKTools.getUUID().toLowerCase()));
}
if(!StringUtils.isBlank(player.getPassword())){
player.setPassword(UKTools.md5(player.getPassword()));
}else{
player.setPassword(UKTools.md5(RandomKey.genRandomNum(6)));//随机生成一个6位数的密码 ,备用
}
player.setPlayertype(playertype); //玩家类型
player.setCreatetime(new Date());
player.setUpdatetime(new Date());
player.setLastlogintime(new Date());
BrowserClient client = UKTools.parseClient(request) ;
player.setOstype(client.getOs());
player.setBrowser(client.getBrowser());
if(request!=null){
String usetAgent = request.getHeader("User-Agent") ;
if(!StringUtils.isBlank(usetAgent)){
if(usetAgent.length() > 255){
player.setUseragent(usetAgent.substring(0,250));
}else{
player.setUseragent(usetAgent);
}
}
}
if(ipdata!=null){
player.setRegion(ipdata.getRegion());
player.setCountry(ipdata.getCountry());
player.setProvince(ipdata.getProvince());
player.setCity(ipdata.getCity());
player.setIsp(ipdata.getIsp());
}
player.setOrgi(BMDataContext.SYSTEM_ORGI);
AiConfig aiConfig = CacheConfigTools.getAiConfig(player.getOrgi()) ;
if(BMDataContext.PlayerTypeEnum.AI.toString().equals(playertype) && aiConfig != null){
player.setGoldcoins(aiConfig.getInitcoins());
player.setCards(aiConfig.getInitcards());
player.setDiamonds(aiConfig.getInitdiamonds());
}else{
AccountConfig config = CacheConfigTools.getGameAccountConfig(BMDataContext.SYSTEM_ORGI) ;
if(config!=null){
player.setGoldcoins(config.getInitcoins());
player.setCards(config.getInitcards());
player.setDiamonds(config.getInitdiamonds());
}
}
if(!StringUtils.isBlank(player.getId())){
playUserClient = new PlayUserClient() ;
try {
BeanUtils.copyProperties(playUserClient , player);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
return playUserClient ;
}
/**
* 获取游戏全局配置,后台管理界面上的配置功能
* @param orgi
* @return
*/
@SuppressWarnings("unchecked")
public static List<GamePlayway> playwayConfig(String gametype,String orgi){
List<GamePlayway> gamePlayList = (List<GamePlayway>) CacheHelper.getSystemCacheBean().getCacheObject(gametype+"."+BMDataContext.ConfigNames.PLAYWAYCONFIG.toString(), orgi) ;
if(gamePlayList == null){
gamePlayList = BMDataContext.getContext().getBean(GamePlaywayRepository.class).findByOrgiAndTypeid(orgi, gametype , new Sort(Sort.Direction.ASC, "sortindex")) ;
CacheHelper.getSystemCacheBean().put(gametype+"."+BMDataContext.ConfigNames.PLAYWAYCONFIG.toString() , gamePlayList , orgi) ;
}
return gamePlayList ;
}
/**
* 获取房卡游戏的自定义配置,后台管理界面上的配置功能
* @param orgi
* @return
*/
@SuppressWarnings("unchecked")
public static List<GamePlaywayGroup> playwayGroupsConfig(String orgi){
List<GamePlaywayGroup> gamePlaywayGroupsList = (List<GamePlaywayGroup>) CacheHelper.getSystemCacheBean().getCacheObject(BMDataContext.ConfigNames.PLAYWAYGROUP.toString(), orgi) ;
if(gamePlaywayGroupsList == null){
gamePlaywayGroupsList = BMDataContext.getContext().getBean(GamePlaywayGroupRepository.class).findByOrgi(orgi, new Sort(Sort.Direction.ASC, "sortindex")) ;
CacheHelper.getSystemCacheBean().put(BMDataContext.ConfigNames.PLAYWAYGROUP.toString() , gamePlaywayGroupsList , orgi) ;
}
return gamePlaywayGroupsList ;
}
/**
* 获取房卡游戏的自定义配置,后台管理界面上的配置功能
* @param orgi
* @return
*/
@SuppressWarnings("unchecked")
public static List<GamePlaywayGroupItem> playwayGroupItemConfig(String orgi){
List<GamePlaywayGroupItem> gamePlaywayGroupsList = (List<GamePlaywayGroupItem>) CacheHelper.getSystemCacheBean().getCacheObject(BMDataContext.ConfigNames.PLAYWAYGROUPITEM.toString(), orgi) ;
if(gamePlaywayGroupsList == null){
gamePlaywayGroupsList = BMDataContext.getContext().getBean(GamePlaywayGroupItemRepository.class).findByOrgi(orgi, new Sort(Sort.Direction.ASC, "sortindex")) ;
CacheHelper.getSystemCacheBean().put(BMDataContext.ConfigNames.PLAYWAYGROUPITEM.toString() , gamePlaywayGroupsList , orgi) ;
}
return gamePlaywayGroupsList ;
}
/**
*
* @param gametype
* @param orgi
*/
public static void cleanPlaywayCache(String gametype,String orgi){
CacheHelper.getSystemCacheBean().delete(gametype+"."+BMDataContext.ConfigNames.PLAYWAYCONFIG.toString(), orgi) ;
}
/**
* 封装Game信息,基于缓存操作
* @param gametype
* @return
*/
public static List<BeiMiGame> games(String gametype){
List<BeiMiGame> beiMiGameList = new ArrayList<BeiMiGame>();
if(!StringUtils.isBlank(gametype)){
/**
* 找到游戏配置的 模式 和玩法,如果多选,则默认进入的是 大厅模式,如果是单选,则进入的是选场模式
*/
String[] games = gametype.split(",") ;
for(String game : games){
BeiMiGame beiMiGame = new BeiMiGame();
for(SysDic sysDic : BeiMiDic.getInstance().getDic(BMDataContext.BEIMI_SYSTEM_GAME_TYPE_DIC)){
if(sysDic.getId().equals(game)){
beiMiGame.setName(sysDic.getName());
beiMiGame.setId(sysDic.getId());
beiMiGame.setCode(sysDic.getCode());
List<SysDic> gameModelList = BeiMiDic.getInstance().getDic(BMDataContext.BEIMI_SYSTEM_GAME_TYPE_DIC, game) ;
for(SysDic gameModel : gameModelList){
Type type = new Type(gameModel.getId(), gameModel.getName() , gameModel.getCode()) ;
beiMiGame.getTypes().add(type) ;
List<GamePlayway> gamePlaywayList = playwayConfig(gameModel.getId(), gameModel.getOrgi()) ;
List<GamePlaywayGroup> gamePlaywayGroups = playwayGroupsConfig(gameModel.getOrgi()) ;
List<GamePlaywayGroupItem> gamePlaywayGroupItems = playwayGroupItemConfig(gameModel.getOrgi()) ;
for(GamePlayway gamePlayway : gamePlaywayList){
Playway playway = new Playway(gamePlayway.getId(), gamePlayway.getName() , gamePlayway.getCode(), gamePlayway.getScore() , gamePlayway.getMincoins(), gamePlayway.getMaxcoins(), gamePlayway.isChangecard() , gamePlayway.isShuffle()) ;
playway.setLevel(gamePlayway.getTypelevel());
playway.setGroups(new ArrayList<GamePlaywayGroup>());
playway.setItems(new ArrayList<GamePlaywayGroupItem>());
for(GamePlaywayGroup group : gamePlaywayGroups){
if(group.getPlaywayid().equals(gamePlayway.getId())){
playway.getGroups().add(group) ;
}
}
for(GamePlaywayGroupItem item : gamePlaywayGroupItems){
if(item.getPlaywayid().equals(gamePlayway.getId())){
playway.getItems().add(item) ;
}
}
playway.setSkin(gamePlayway.getTypecolor());
playway.setMemo(gamePlayway.getMemo());
playway.setRoomtitle(gamePlayway.getRoomtitle());
playway.setFree(gamePlayway.isFree());
playway.setExtpro(gamePlayway.isExtpro());
type.getPlayways().add(playway) ;
}
}
beiMiGameList.add(beiMiGame) ;
}
}
}
}
return beiMiGameList ;
}
public static void main(String[] args){
long start = System.nanoTime() ;
byte[] cards = new byte[]{21,22,24,28,88,92,96} ;
byte takecard = 20 ;
List<Byte> test = new ArrayList<Byte>();
for(byte temp : cards){
test.add(temp) ;
}
test.add(takecard) ;
Collections.sort(test);
for(byte temp : test){
int value = (temp%36) / 4 ; //牌面值
int rote = temp / 36 ; //花色
System.out.print(value+1);
if(rote == 0){
System.out.print("万,");
}else if(rote == 1){
System.out.print("筒,");
}else if(rote == 2){
System.out.print("条,");
}
}
Player player = new Player("USER1") ;
player.setColor(3);
player.setActions(new ArrayList<Action>());
for(int i=0 ; i<5000000 ; i++){
GameUtils.processMJCard(player, cards, takecard, false) ;
}
long end = System.nanoTime() - start ;
System.out.println("判断500W次胡牌花费时间:"+(end)+"纳秒,约等于:"+ end/1000000f+"ms");
}
/**
* 麻将的出牌判断,杠碰吃胡
* @param cards
* @param card
* @param deal 是否抓牌
* @return
*/
public static MJCardMessage processMJCard(Player player,byte[] cards , byte takecard , boolean deal){
MJCardMessage mjCard = new MJCardMessage();
mjCard.setCommand("action");
mjCard.setUserid(player.getPlayuser());
Map<Integer, Byte> data = new HashMap<Integer, Byte>();
boolean que = false ;
if(cards.length > 0){
for(byte temp : cards){
int value = (temp%36) / 4 ; //牌面值
int rote = temp / 36 ; //花色
int key = value + 9 * rote ; //
if(rote == player.getColor()){
que = true ;
}
if(data.get(key) == null || rote == player.getColor()){
data.put(key , (byte)1) ;
}else{
data.put(key, (byte)(data.get(key)+1)) ;
}
if(data.get(key) == 4 && deal == true){ //自己发牌的时候,需要先判断是否有杠牌
mjCard.setGang(true);
mjCard.setCard(temp);
}
}
/**
* 检查是否有 杠碰
*/
int value = (takecard %36)/4 ;
int key = value + 9*(takecard/36) ;
Byte card = data.get(key) ;
if(card!=null){
if(card ==2 && deal == false){
//碰
mjCard.setPeng(true);
mjCard.setCard(takecard);
}else if(card == 3){
//明杠
mjCard.setGang(true);
mjCard.setCard(takecard);
}
}
/**
* 检查是否有弯杠 , 碰过 AND 自己抓了一张碰过的牌
*/
int rote = takecard / 36 ;
if(deal == true && rote!= player.getColor() ){
for(Action action : player.getActions()){
if(action.getCard() == takecard && action.getAction().equals(BMDataContext.PlayerAction.PENG.toString())){
//
mjCard.setGang(true); break ;
}
}
}
/**
* 后面胡牌判断使用
*/
if(data.get(key) == null){
data.put(key , (byte)1) ;
}else{
data.put(key, (byte)(data.get(key)+1)) ;
}
}
if(que == false){
/**
* 检查是否有 胡 , 胡牌算法,先移除 对子
*/
List<Byte> pairs = new ArrayList<Byte>();
List<Byte> others = new ArrayList<Byte>();
List<Byte> kezi = new ArrayList<Byte>();
/**
* 处理玩家手牌
*/
for(byte temp : cards){
int key = (((temp%36) / 4) + 9 * (int)(temp / 36)) ; //字典编码
if(data.get(key) == 1 ){
others.add(temp) ;
}else if(data.get(key) == 2){
pairs.add(temp) ;
}else if(data.get(key) == 3){
kezi.add(temp) ;
}
}
/**
* 处理一个单张
*/
{
int key = (((takecard%36) / 4) + 9 * (int)(takecard / 36)) ; //字典编码
if(data.get(key) == 1 ){
others.add(takecard) ;
}else if(data.get(key) == 2){
pairs.add(takecard) ;
}else if(data.get(key) == 3){
kezi.add(takecard) ;
}
}
/**
* 是否有胡
*/
processOther(others);
if(others.size() == 0){
if(pairs.size() == 2 || pairs.size() == 14){//有一对,胡
mjCard.setHu(true);
}else{ //然后分别验证 ,只有一种特殊情况,的 3连对,可以组两个顺子,也可以胡 , 其他情况就呵呵了
}
}else if(pairs.size() > 2){ //对子的牌大于>2张,否则肯定是不能胡的
//检查对子里 是否有额外多出来的 牌,如果有,则进行移除
for(int i=0 ; i<pairs.size() ; i++){
if(i%2==0){
others.add(pairs.get(i)) ;
}
}
processOther( others);
for(int i=0 ; i<pairs.size() ; i++){
if(i%2==1){
others.add(pairs.get(i)) ;
}
}
processOther(others);
/**
* 检查 others
*/
/**
* 最后一次,检查所有的值都是 2,就胡了
*/
if(others.size() == 2 && getKey(others.get(0)) == getKey(others.get(1))){
mjCard.setHu(true);
}else{ //还不能胡?
}
}else if(pairs.size() == 0){
for(Byte temp : kezi){
others.add(temp) ;
processOther(others);
if(others.size() == 0){
mjCard.setHu(true);
break ;
}else{
others.remove(temp) ;
}
}
}
}
if(mjCard.isHu()){
mjCard.setCard(takecard);
System.out.println("胡牌了");
for(byte temp : cards){
System.out.print(temp+",");
}
System.out.println(takecard);
}
return mjCard;
}
private static void processOther(List<Byte> others){
Collections.sort(others);
for(int i=0 ; i<others.size() && others.size() >(i+2) ; ){
byte color = (byte) (others.get(i) / 36) ; //花色
byte key = getKey(others.get(i));
byte nextcolor = (byte) (others.get(i) / 36) ; //花色
byte nextkey = getKey(others.get(i+1));
if(color == nextcolor && nextkey == key+1){
nextcolor = (byte) (others.get(i+2) / 36) ; //花色
nextkey = getKey(others.get(i+2));
if(color == nextcolor && nextkey == key+2){ //数字,移除掉
others.remove(i+2) ;
others.remove(i+1) ;
others.remove(i) ;
}else{
i = i+2 ;
}
}else{
i = i+1 ; //下一步
}
}
}
public static byte getKey(byte card){
byte value = (byte) ((card%36) / 4) ; //牌面值
int rate = card / 36 ; //花色
byte key = (byte) (value + 9 * rate) ; //字典编码
return key ;
}
/**
* 麻将的出牌判断,杠碰吃胡
* @param cards
* @param card
* @param deal 是否抓牌
* @return
*/
public static Byte getGangCard(byte[] cards){
Byte card = null ;
Map<Integer, Byte> data = new HashMap<Integer, Byte>();
for(byte temp : cards){
int value = (temp%36) / 4 ; //牌面值
int rote = temp / 36 ; //花色
int key = value + 9 * rote ; //
if(data.get(key) == null){
data.put(key , (byte)1) ;
}else{
data.put(key, (byte)(data.get(key)+1)) ;
}
if(data.get(key) == 4){ //自己发牌的时候,需要先判断是否有杠牌
card = temp ;
break ;
}
}
return card;
}
/**
* 定缺方法,计算最少的牌
* @param cards
* @return
*/
public static int selectColor(byte[] cards){
Map<Integer, Byte> data = new HashMap<Integer, Byte>();
for(byte temp : cards){
int key = temp / 36 ; //花色
if(data.get(key) == null){
data.put(key , (byte)1) ;
}else{
data.put(key, (byte)(data.get(key)+1)) ;
}
}
int color = 0 , cardsNum = 0 ;
if(data.get(0)!=null){
cardsNum = data.get(0) ;
if(data.get(1) == null){
color = 1 ;
}else{
if(data.get(1) < cardsNum){
cardsNum = data.get(1) ;
color = 1 ;
}
if(data.get(2)==null){
color = 2 ;
}else{
if(data.get(2) < cardsNum){
cardsNum = data.get(2) ;
color = 2 ;
}
}
}
}
return color ;
}
}
+43
View File
@@ -0,0 +1,43 @@
package com.beimi.util;
public class IP{
private String country ;
private String province ;
private String city ;
private String isp ;
private String region ;
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getIsp() {
return isp;
}
public void setIsp(String isp) {
this.isp = isp;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public String toString(){
return "0".equals(this.province) || "0".equals(this.city) ? this.country : (this.province+this.city) ;
}
}
+68
View File
@@ -0,0 +1,68 @@
package com.beimi.util;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbMakerConfigException;
import org.lionsoul.ip2region.DbSearcher;
import com.beimi.core.BMDataContext;
public class IPTools {
private String IP_DATA_PATH = "WEB-INF/data/ip/ip.db";
private static IPTools iptools = new IPTools();
private DbSearcher _searcher = null ;
public static IPTools getInstance(){
return iptools ;
}
public IPTools() {
try {
File dbFile = new File(BMDataContext.getContext().getEnvironment().getProperty("web.upload-path"), "ipdata/ipdata.db") ;
if(!dbFile.exists()){
FileUtils.copyInputStreamToFile(IPTools.class.getClassLoader().getResourceAsStream(IP_DATA_PATH),dbFile);
}
_searcher = new DbSearcher(new DbConfig(),dbFile.getAbsolutePath());
} catch (DbMakerConfigException | IOException e) {
e.printStackTrace();
}
}
public IP findGeography(String remote) {
IP ip = new IP();
try{
DataBlock block = _searcher.binarySearch(remote!=null ? remote : "127.0.0.1") ;
if(block!=null && block.getRegion() != null){
String[] region = block.getRegion().split("[\\|]") ;
if(region.length == 5){
ip.setCountry(region[0]);
if(!StringUtils.isBlank(region[1]) && !region[1].equalsIgnoreCase("null")){
ip.setRegion(region[1]);
}else{
ip.setRegion("");
}
if(!StringUtils.isBlank(region[2]) && !region[2].equalsIgnoreCase("null")){
ip.setProvince(region[2]);
}else{
ip.setProvince("");
}
if(!StringUtils.isBlank(region[3]) && !region[3].equalsIgnoreCase("null")){
ip.setCity(region[3]);
}else{
ip.setCity("");
}
if(!StringUtils.isBlank(region[4]) && !region[4].equalsIgnoreCase("null")){
ip.setIsp(region[4]);
}else{
ip.setIsp("");
}
}
}
}catch(Exception ex){}
return ip;
}
}
+263
View File
@@ -0,0 +1,263 @@
package com.beimi.util;
public class MD5 {
public String getMD5ofStr(String inbuf) {
md5Init();
md5Update(inbuf.getBytes(), inbuf.length());
md5Final();
digestHexStr = "";
for (int i = 0; i < 16; i++)
digestHexStr += byteHEX(digest[i]);
return digestHexStr;
}
public String getMD5ofByte(byte[] inbuf) {
md5Init();
md5Update(inbuf, inbuf.length);
md5Final();
digestHexStr = "";
for (int i = 0; i < 16; i++)
digestHexStr += byteHEX(digest[i]);
return digestHexStr;
}
public MD5() {
state = new long[4];
count = new long[2];
buffer = new byte[64];
digest = new byte[16];
md5Init();
}
private void md5Init() {
count[0] = 0L;
count[1] = 0L;
state[0] = 0x67452301L;
state[1] = 0xefcdab89L;
state[2] = 0x98badcfeL;
state[3] = 0x10325476L;
}
private long F(long x, long y, long z) {
return x & y | ~x & z;
}
private long G(long x, long y, long z) {
return x & z | y & ~z;
}
private long H(long x, long y, long z) {
return x ^ y ^ z;
}
private long I(long x, long y, long z) {
return y ^ (x | ~z);
}
private long FF(long a, long b, long c, long d, long x, long s, long ac) {
a += F(b, c, d) + x + ac;
a = (int) a << (int) s | (int) a >>> (int) (32L - s);
a += b;
return a;
}
private long GG(long a, long b, long c, long d, long x, long s, long ac) {
a += G(b, c, d) + x + ac;
a = (int) a << (int) s | (int) a >>> (int) (32L - s);
a += b;
return a;
}
private long HH(long a, long b, long c, long d, long x, long s, long ac) {
a += H(b, c, d) + x + ac;
a = (int) a << (int) s | (int) a >>> (int) (32L - s);
a += b;
return a;
}
private long II(long a, long b, long c, long d, long x, long s, long ac) {
a += I(b, c, d) + x + ac;
a = (int) a << (int) s | (int) a >>> (int) (32L - s);
a += b;
return a;
}
private void md5Update(byte inbuf[], int inputLen) {
byte block[] = new byte[64];
int index = (int) (count[0] >>> 3) & 0x3f;
if ((count[0] += inputLen << 3) < (long) (inputLen << 3))
count[1]++;
count[1] += inputLen >>> 29;
int partLen = 64 - index;
int i;
if (inputLen >= partLen) {
md5Memcpy(buffer, inbuf, index, 0, partLen);
md5Transform(buffer);
for (i = partLen; i + 63 < inputLen; i += 64) {
md5Memcpy(block, inbuf, 0, i, 64);
md5Transform(block);
}
index = 0;
} else {
i = 0;
}
md5Memcpy(buffer, inbuf, index, i, inputLen - i);
}
private void md5Final() {
byte bits[] = new byte[8];
encode(bits, count, 8);
int index = (int) (count[0] >>> 3) & 0x3f;
int padLen = index >= 56 ? 120 - index : 56 - index;
md5Update(PADDING, padLen);
md5Update(bits, 8);
encode(digest, state, 16);
}
private void md5Memcpy(byte output[], byte input[], int outpos, int inpos, int len) {
for (int i = 0; i < len; i++)
output[outpos + i] = input[inpos + i];
}
private void md5Transform(byte block[]) {
long a = state[0];
long b = state[1];
long c = state[2];
long d = state[3];
long x[] = new long[16];
decode(x, block, 64);
a = FF(a, b, c, d, x[0], 7L, 0xd76aa478L);
d = FF(d, a, b, c, x[1], 12L, 0xe8c7b756L);
c = FF(c, d, a, b, x[2], 17L, 0x242070dbL);
b = FF(b, c, d, a, x[3], 22L, 0xc1bdceeeL);
a = FF(a, b, c, d, x[4], 7L, 0xf57c0fafL);
d = FF(d, a, b, c, x[5], 12L, 0x4787c62aL);
c = FF(c, d, a, b, x[6], 17L, 0xa8304613L);
b = FF(b, c, d, a, x[7], 22L, 0xfd469501L);
a = FF(a, b, c, d, x[8], 7L, 0x698098d8L);
d = FF(d, a, b, c, x[9], 12L, 0x8b44f7afL);
c = FF(c, d, a, b, x[10], 17L, 0xffff5bb1L);
b = FF(b, c, d, a, x[11], 22L, 0x895cd7beL);
a = FF(a, b, c, d, x[12], 7L, 0x6b901122L);
d = FF(d, a, b, c, x[13], 12L, 0xfd987193L);
c = FF(c, d, a, b, x[14], 17L, 0xa679438eL);
b = FF(b, c, d, a, x[15], 22L, 0x49b40821L);
a = GG(a, b, c, d, x[1], 5L, 0xf61e2562L);
d = GG(d, a, b, c, x[6], 9L, 0xc040b340L);
c = GG(c, d, a, b, x[11], 14L, 0x265e5a51L);
b = GG(b, c, d, a, x[0], 20L, 0xe9b6c7aaL);
a = GG(a, b, c, d, x[5], 5L, 0xd62f105dL);
d = GG(d, a, b, c, x[10], 9L, 0x2441453L);
c = GG(c, d, a, b, x[15], 14L, 0xd8a1e681L);
b = GG(b, c, d, a, x[4], 20L, 0xe7d3fbc8L);
a = GG(a, b, c, d, x[9], 5L, 0x21e1cde6L);
d = GG(d, a, b, c, x[14], 9L, 0xc33707d6L);
c = GG(c, d, a, b, x[3], 14L, 0xf4d50d87L);
b = GG(b, c, d, a, x[8], 20L, 0x455a14edL);
a = GG(a, b, c, d, x[13], 5L, 0xa9e3e905L);
d = GG(d, a, b, c, x[2], 9L, 0xfcefa3f8L);
c = GG(c, d, a, b, x[7], 14L, 0x676f02d9L);
b = GG(b, c, d, a, x[12], 20L, 0x8d2a4c8aL);
a = HH(a, b, c, d, x[5], 4L, 0xfffa3942L);
d = HH(d, a, b, c, x[8], 11L, 0x8771f681L);
c = HH(c, d, a, b, x[11], 16L, 0x6d9d6122L);
b = HH(b, c, d, a, x[14], 23L, 0xfde5380cL);
a = HH(a, b, c, d, x[1], 4L, 0xa4beea44L);
d = HH(d, a, b, c, x[4], 11L, 0x4bdecfa9L);
c = HH(c, d, a, b, x[7], 16L, 0xf6bb4b60L);
b = HH(b, c, d, a, x[10], 23L, 0xbebfbc70L);
a = HH(a, b, c, d, x[13], 4L, 0x289b7ec6L);
d = HH(d, a, b, c, x[0], 11L, 0xeaa127faL);
c = HH(c, d, a, b, x[3], 16L, 0xd4ef3085L);
b = HH(b, c, d, a, x[6], 23L, 0x4881d05L);
a = HH(a, b, c, d, x[9], 4L, 0xd9d4d039L);
d = HH(d, a, b, c, x[12], 11L, 0xe6db99e5L);
c = HH(c, d, a, b, x[15], 16L, 0x1fa27cf8L);
b = HH(b, c, d, a, x[2], 23L, 0xc4ac5665L);
a = II(a, b, c, d, x[0], 6L, 0xf4292244L);
d = II(d, a, b, c, x[7], 10L, 0x432aff97L);
c = II(c, d, a, b, x[14], 15L, 0xab9423a7L);
b = II(b, c, d, a, x[5], 21L, 0xfc93a039L);
a = II(a, b, c, d, x[12], 6L, 0x655b59c3L);
d = II(d, a, b, c, x[3], 10L, 0x8f0ccc92L);
c = II(c, d, a, b, x[10], 15L, 0xffeff47dL);
b = II(b, c, d, a, x[1], 21L, 0x85845dd1L);
a = II(a, b, c, d, x[8], 6L, 0x6fa87e4fL);
d = II(d, a, b, c, x[15], 10L, 0xfe2ce6e0L);
c = II(c, d, a, b, x[6], 15L, 0xa3014314L);
b = II(b, c, d, a, x[13], 21L, 0x4e0811a1L);
a = II(a, b, c, d, x[4], 6L, 0xf7537e82L);
d = II(d, a, b, c, x[11], 10L, 0xbd3af235L);
c = II(c, d, a, b, x[2], 15L, 0x2ad7d2bbL);
b = II(b, c, d, a, x[9], 21L, 0xeb86d391L);
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}
private void encode(byte output[], long input[], int len) {
int i = 0;
for (int j = 0; j < len; j += 4) {
output[j] = (byte) (int) (input[i] & 255L);
output[j + 1] = (byte) (int) (input[i] >>> 8 & 255L);
output[j + 2] = (byte) (int) (input[i] >>> 16 & 255L);
output[j + 3] = (byte) (int) (input[i] >>> 24 & 255L);
i++;
}
}
private void decode(long output[], byte input[], int len) {
int i = 0;
for (int j = 0; j < len; j += 4) {
output[i] = b2iu(input[j]) | b2iu(input[j + 1]) << 8 | b2iu(input[j + 2]) << 16 | b2iu(input[j + 3]) << 24;
i++;
}
}
private long b2iu(byte b) {
return b >= 0 ? b : b & 0xff;
}
private String byteHEX(byte ib) {
char Digit[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
char ob[] = new char[2];
ob[0] = Digit[ib >>> 4 & 0xf];
ob[1] = Digit[ib & 0xf];
String s = new String(ob);
return s;
}
static final int S11 = 7;
static final int S12 = 12;
static final int S13 = 17;
static final int S14 = 22;
static final int S21 = 5;
static final int S22 = 9;
static final int S23 = 14;
static final int S24 = 20;
static final int S31 = 4;
static final int S32 = 11;
static final int S33 = 16;
static final int S34 = 23;
static final int S41 = 6;
static final int S42 = 10;
static final int S43 = 15;
static final int S44 = 21;
static final byte PADDING[] = { -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0 };
private long state[];
private long count[];
private byte buffer[];
private String digestHexStr;
private byte digest[];
}
+24
View File
@@ -0,0 +1,24 @@
package com.beimi.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Menu {
/**
* 数据表名称注解,默认值为类名称
* @return
*/
public String type() default "className";
public String subtype() default "methodName";
public boolean access() default false;
public boolean admin() default false;
public String name() default "methodName";
}
@@ -0,0 +1,9 @@
package com.beimi.util;
public class MessageEnum {
public static final String USER_REGISTER_SUCCESS = "user_register_success";
public static final String USER_REGISTER_FAILD_USERNAME = "user_register_faild_username";
public static final String USER_NOT_EXIST = "user_not_exist";
public static final String USER_GET_SUCCESS = "user_get_success";
}
@@ -0,0 +1,138 @@
package com.beimi.util;
public class PinYinTools {
private static int[] pyvalue = new int[] {-20319, -20317, -20304, -20295, -20292, -20283, -20265, -20257, -20242, -20230, -20051, -20036, -20032,
-20026, -20002, -19990, -19986, -19982, -19976, -19805, -19784, -19775, -19774, -19763, -19756, -19751, -19746, -19741, -19739, -19728,
-19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479, -19467, -19289, -19288, -19281, -19275, -19270, -19263, -19261,
-19249, -19243, -19242, -19238, -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018, -19006, -19003, -18996, -18977, -18961,
-18952, -18783, -18774, -18773, -18763, -18756, -18741, -18735, -18731, -18722, -18710, -18697, -18696, -18526, -18518, -18501, -18490,
-18478, -18463, -18448, -18447, -18446, -18239, -18237, -18231, -18220, -18211, -18201, -18184, -18183, -18181, -18012, -17997, -17988,
-17970, -17964, -17961, -17950, -17947, -17931, -17928, -17922, -17759, -17752, -17733, -17730, -17721, -17703, -17701, -17697, -17692,
-17683, -17676, -17496, -17487, -17482, -17468, -17454, -17433, -17427, -17417, -17202, -17185, -16983, -16970, -16942, -16915, -16733,
-16708, -16706, -16689, -16664, -16657, -16647, -16474, -16470, -16465, -16459, -16452, -16448, -16433, -16429, -16427, -16423, -16419,
-16412, -16407, -16403, -16401, -16393, -16220, -16216, -16212, -16205, -16202, -16187, -16180, -16171, -16169, -16158, -16155, -15959,
-15958, -15944, -15933, -15920, -15915, -15903, -15889, -15878, -15707, -15701, -15681, -15667, -15661, -15659, -15652, -15640, -15631,
-15625, -15454, -15448, -15436, -15435, -15419, -15416, -15408, -15394, -15385, -15377, -15375, -15369, -15363, -15362, -15183, -15180,
-15165, -15158, -15153, -15150, -15149, -15144, -15143, -15141, -15140, -15139, -15128, -15121, -15119, -15117, -15110, -15109, -14941,
-14937, -14933, -14930, -14929, -14928, -14926, -14922, -14921, -14914, -14908, -14902, -14894, -14889, -14882, -14873, -14871, -14857,
-14678, -14674, -14670, -14668, -14663, -14654, -14645, -14630, -14594, -14429, -14407, -14399, -14384, -14379, -14368, -14355, -14353,
-14345, -14170, -14159, -14151, -14149, -14145, -14140, -14137, -14135, -14125, -14123, -14122, -14112, -14109, -14099, -14097, -14094,
-14092, -14090, -14087, -14083, -13917, -13914, -13910, -13907, -13906, -13905, -13896, -13894, -13878, -13870, -13859, -13847, -13831,
-13658, -13611, -13601, -13406, -13404, -13400, -13398, -13395, -13391, -13387, -13383, -13367, -13359, -13356, -13343, -13340, -13329,
-13326, -13318, -13147, -13138, -13120, -13107, -13096, -13095, -13091, -13076, -13068, -13063, -13060, -12888, -12875, -12871, -12860,
-12858, -12852, -12849, -12838, -12831, -12829, -12812, -12802, -12607, -12597, -12594, -12585, -12556, -12359, -12346, -12320, -12300,
-12120, -12099, -12089, -12074, -12067, -12058, -12039, -11867, -11861, -11847, -11831, -11798, -11781, -11604, -11589, -11536, -11358,
-11340, -11339, -11324, -11303, -11097, -11077, -11067, -11055, -11052, -11045, -11041, -11038, -11024, -11020, -11019, -11018, -11014,
-10838, -10832, -10815, -10800, -10790, -10780, -10764, -10587, -10544, -10533, -10519, -10331, -10329, -10328, -10322, -10315, -10309,
-10307, -10296, -10281, -10274, -10270, -10262, -10260, -10256, -10254};
public static String[] pystr = new String[] {"A", "AI", "AN", "ANG", "AO", "BA", "BAI", "BAN", "BANG", "BAO", "BEI", "BEN", "BENG", "BI", "BIAN",
"BIAO", "BIE", "BIN", "BING", "BO", "BU", "CA", "CAI", "CAN", "CANG", "CAO", "CE", "CENG", "CHA", "CHAI", "CHAN", "CHANG", "CHAO", "CHE",
"CHEN", "CHENG", "CHI", "CHONG", "CHOU", "CHU", "CHUAI", "CHUAN", "CHUANG", "CHUI", "CHUN", "CHUO", "CI", "CONG", "COU", "CU", "CUAN",
"CUI", "CUN", "CUO", "DA", "DAI", "DAN", "DANG", "DAO", "DE", "DENG", "DI", "DIAN", "DIAO", "DIE", "DING", "DIU", "DONG", "DOU", "DU",
"DUAN", "DUI", "DUN", "DUO", "E", "EN", "ER", "FA", "FAN", "FANG", "FEI", "FEN", "FENG", "FO", "FOU", "FU", "GA", "GAI", "GAN", "GANG",
"GAO", "GE", "GEI", "GEN", "GENG", "GONG", "GOU", "GU", "GUA", "GUAI", "GUAN", "GUANG", "GUI", "GUN", "GUO", "HA", "HAI", "HAN", "HANG",
"HAO", "HE", "HEI", "HEN", "HENG", "HONG", "HOU", "HU", "HUA", "HUAI", "HUAN", "HUANG", "HUI", "HUN", "HUO", "JI", "JIA", "JIAN",
"JIANG", "JIAO", "JIE", "JIN", "JING", "JIONG", "JIU", "JU", "JUAN", "JUE", "JUN", "KA", "KAI", "KAN", "KANG", "KAO", "KE", "KEN",
"KENG", "KONG", "KOU", "KU", "KUA", "KUAI", "KUAN", "KUANG", "KUI", "KUN", "KUO", "LA", "LAI", "LAN", "LANG", "LAO", "LE", "LEI", "LENG",
"LI", "LIA", "LIAN", "LIANG", "LIAO", "LIE", "LIN", "LING", "LIU", "LONG", "LOU", "LU", "LV", "LUAN", "LUE", "LUN", "LUO", "MA", "MAI",
"MAN", "MANG", "MAO", "ME", "MEI", "MEN", "MENG", "MI", "MIAN", "MIAO", "MIE", "MIN", "MING", "MIU", "MO", "MOU", "MU", "NA", "NAI",
"NAN", "NANG", "NAO", "NE", "NEI", "NEN", "NENG", "NI", "NIAN", "NIANG", "NIAO", "NIE", "NIN", "NING", "NIU", "NONG", "NU", "NV", "NUAN",
"NUE", "NUO", "O", "OU", "PA", "PAI", "PAN", "PANG", "PAO", "PEI", "PEN", "PENG", "PI", "PIAN", "PIAO", "PIE", "PIN", "PING", "PO", "PU",
"QI", "QIA", "QIAN", "QIANG", "QIAO", "QIE", "QIN", "QING", "QIONG", "QIU", "QU", "QUAN", "QUE", "QUN", "RAN", "RANG", "RAO", "RE",
"REN", "RENG", "RI", "RONG", "ROU", "RU", "RUAN", "RUI", "RUN", "RUO", "SA", "SAI", "SAN", "SANG", "SAO", "SE", "SEN", "SENG", "SHA",
"SHAI", "SHAN", "SHANG", "SHAO", "SHE", "SHEN", "SHENG", "SHI", "SHOU", "SHU", "SHUA", "SHUAI", "SHUAN", "SHUANG", "SHUI", "SHUN",
"SHUO", "SI", "SONG", "SOU", "SU", "SUAN", "SUI", "SUN", "SUO", "TA", "TAI", "TAN", "TANG", "TAO", "TE", "TENG", "TI", "TIAN", "TIAO",
"TIE", "TING", "TONG", "TOU", "TU", "TUAN", "TUI", "TUN", "TUO", "WA", "WAI", "WAN", "WANG", "WEI", "WEN", "WENG", "WO", "WU", "XI",
"XIA", "XIAN", "XIANG", "XIAO", "XIE", "XIN", "XING", "XIONG", "XIU", "XU", "XUAN", "XUE", "XUN", "YA", "YAN", "YANG", "YAO", "YE", "YI",
"YIN", "YING", "YO", "YONG", "YOU", "YU", "YUAN", "YUE", "YUN", "ZA", "ZAI", "ZAN", "ZANG", "ZAO", "ZE", "ZEI", "ZEN", "ZENG", "ZHA",
"ZHAI", "ZHAN", "ZHANG", "ZHAO", "ZHE", "ZHEN", "ZHENG", "ZHI", "ZHONG", "ZHOU", "ZHU", "ZHUA", "ZHUAI", "ZHUAN", "ZHUANG", "ZHUI",
"ZHUN", "ZHUO", "ZI", "ZONG", "ZOU", "ZU", "ZUAN", "ZUI", "ZUN", "ZUO"};
private StringBuilder buffer;
private String resource;
private static PinYinTools characterParser = new PinYinTools();
public static PinYinTools getInstance() {
return characterParser;
}
public String getResource() {
return resource;
}
public void setResource(String resource) {
this.resource = resource;
}
/** * 汉字转成ASCII码 * * @param chs * @return */
private int getChsAscii(String chs) {
int asc = 0;
try {
byte[] bytes = chs.getBytes("gb2312");
if (bytes == null || bytes.length > 2 || bytes.length <= 0) {
throw new RuntimeException("illegal resource string");
}
if (bytes.length == 1) {
asc = bytes[0];
}
if (bytes.length == 2) {
int hightByte = 256 + bytes[0];
int lowByte = 256 + bytes[1];
asc = (256 * hightByte + lowByte) - 256 * 256;
}
} catch (Exception e) {
System.out.println("ERROR:ChineseSpelling.class-getChsAscii(String chs)" + e);
}
return asc;
}
/** * 单字解析 * * @param str * @return */
public String convert(String str) {
String result = null;
int ascii = getChsAscii(str);
if (ascii > 0 && ascii < 160) {
result = String.valueOf((char) ascii);
} else {
for (int i = (pyvalue.length - 1); i >= 0; i--) {
if (pyvalue[i] <= ascii) {
result = pystr[i];
break;
}
}
}
return result;
}
/** * 词组解析 * * @param chs * @return */
public String getSelling(String chs) {
String key, value;
buffer = new StringBuilder();
for (int i = 0; i < chs.length(); i++) {
key = chs.substring(i, i + 1);
if (key.getBytes().length >= 2) {
value = (String) convert(key);
if (value == null) {
value = "unknown";
}
} else {
value = key;
}
buffer.append(value+" ");
}
return buffer.toString();
}
public String getSpelling() {
return this.getSelling(this.getResource());
}
public String getFirstPinYin(String word){
String firstWord = "0";
String pinYin = PinYinTools.getInstance().getSelling(word) ;
if(pinYin.length() > 0){
firstWord = pinYin.substring(0,1) ;
}
return firstWord ;
}
}
@@ -0,0 +1,16 @@
package com.beimi.util;
import com.beimi.core.engine.game.pva.GoldPVAImpl;
import com.beimi.core.engine.game.pva.Pva;
public class PvaTools {
private static Pva goldPvaImpl = new GoldPVAImpl();
/**
*
* @return
*/
public static Pva getGoldCoins(){
return goldPvaImpl;
}
}
@@ -0,0 +1,250 @@
package com.beimi.util;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
public abstract class RSAKeyPairFactory extends RSATool {
public static final String KEY_ALGORITHM = "RSA";
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
private static final String PUBLIC_KEY = "RSAPublicKey";
private static final String PRIVATE_KEY = "RSAPrivateKey";
/**
* 用私钥对信息生成数字签名
*
* @param data
* 加密数据
* @param privateKey
* 私钥
*
* @return
* @throws Exception
*/
public static String sign(byte[] data, String privateKey) throws Exception {
// 解密由base64编码的私钥
byte[] keyBytes = decryptBASE64(privateKey);
// 构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取私钥匙对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 用私钥对信息生成数字签名
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
return encryptBASE64(signature.sign());
}
/**
* 校验数字签名
*
* @param data
* 加密数据
* @param publicKey
* 公钥
* @param sign
* 数字签名
*
* @return 校验成功返回true 失败返回false
* @throws Exception
*
*/
public static boolean verify(byte[] data, String publicKey, String sign)
throws Exception {
// 解密由base64编码的公钥
byte[] keyBytes = decryptBASE64(publicKey);
// 构造X509EncodedKeySpec对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取公钥匙对象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
// 验证签名是否正常
return signature.verify(decryptBASE64(sign));
}
/**
* 解密<br>
* 用私钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data, String key)
throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 解密<br>
* 用私钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] data, String key)
throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 加密<br>
* 用公钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String key)
throws Exception {
// 对公钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 加密<br>
* 用私钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String key)
throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 取得私钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 取得公钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 初始化密钥
*
* @return
* @throws Exception
*/
public static Map<String, Object> initKey() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
}
+143
View File
@@ -0,0 +1,143 @@
package com.beimi.util;
import java.security.MessageDigest;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public abstract class RSATool {
public static final String KEY_SHA = "SHA";
public static final String KEY_MD5 = "MD5";
/**
* MAC算法可选以下多种算法
*
* <pre>
* HmacMD5
* HmacSHA1
* HmacSHA256
* HmacSHA384
* HmacSHA512
* </pre>
*/
public static final String KEY_MAC = "HmacMD5";
/**
* BASE64解密
*
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptBASE64(String key) throws Exception {
return hex2BYTE(key);
}
/**
* BASE64加密
*
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64(byte[] key) throws Exception {
return byteHEX(key);
}
/**
* MD5加密
*
* @param data
* @return
* @throws Exception
*/
public static byte[] encryptMD5(byte[] data) throws Exception {
MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
md5.update(data);
return md5.digest();
}
/**
* SHA加密
*
* @param data
* @return
* @throws Exception
*/
public static byte[] encryptSHA(byte[] data) throws Exception {
MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
sha.update(data);
return sha.digest();
}
/**
* 初始化HMAC密钥
*
* @return
* @throws Exception
*/
public static String initMacKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
SecretKey secretKey = keyGenerator.generateKey();
return encryptBASE64(secretKey.getEncoded());
}
/**
* HMAC加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptHMAC(byte[] data, String key) throws Exception {
SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
return mac.doFinal(data);
}
/**
* 编码byte
* @param ib
* @return
*/
public static String byteHEX(byte[] ib) {
char[] Digit = { '0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F' };
StringBuffer strb = new StringBuffer() ;
for(byte data: ib){
char [] ob = new char[2];
ob[0] = Digit[(data >>> 4) & 0X0F];
ob[1] = Digit[data & 0X0F];
strb.append(ob);
}
return strb.toString();
}
public static byte[] hex2BYTE(String hex) throws IllegalArgumentException {
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException();
}
char[] arr = hex.toCharArray();
byte[] b = new byte[hex.length() / 2];
for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
String swap = "" + arr[i++] + arr[i];
int byteint = Integer.parseInt(swap, 16) & 0xFF;
b[j] = new Integer(byteint).byteValue();
}
return b;
}
}
@@ -0,0 +1,124 @@
package com.beimi.util;
import java.util.Random;
public class RandomCharUtil {
public static final String allChar = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String letterChar = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String upperLetterChar = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String lowerLetterChar = "abcdefghijklmnopqrstuvwxyz";
public static final String numberChar = "0123456789";
public static final String numberLowerLetterChar = "0123456789abcdefghijklmnopqrstuvwxyz";
public static final String numberUpperLetterChar = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static String getRandomALLChar(int n) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for(int i = 0; i < n; i++) {
sb.append( allChar.charAt( random.nextInt( allChar.length() ) ) );
}
return sb.toString();
}
public static String getRandomLetterChar(int n) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for(int i = 0; i < n; i++) {
sb.append( letterChar.charAt( random.nextInt( letterChar.length() ) ) );
}
return sb.toString();
}
public static String getRandomUpperLetterChar(int n) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for(int i = 0; i < n; i++) {
sb.append( upperLetterChar.charAt( random.nextInt( upperLetterChar.length() ) ) );
}
return sb.toString();
}
public static String getRandomLowerLetterChar(int n) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for(int i = 0; i < n; i++) {
sb.append( lowerLetterChar.charAt( random.nextInt( lowerLetterChar.length() ) ) );
}
return sb.toString();
}
public static String getRandomNumberChar(int n) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for(int i = 0; i < n; i++) {
sb.append( numberChar.charAt( random.nextInt( numberChar.length() ) ) );
}
return sb.toString();
}
public static String getRandomNumberLowerLetterChar(int n) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for(int i = 0; i < n; i++) {
sb.append( numberLowerLetterChar.charAt( random.nextInt( numberLowerLetterChar.length() ) ) );
}
return sb.toString();
}
public static String getRandomNumberUpperLetterChar(int n) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for(int i = 0; i < n; i++) {
sb.append( numberUpperLetterChar.charAt( random.nextInt( numberUpperLetterChar.length() ) ) );
}
return sb.toString();
}
public static void main(String[] args) {
int k = 3;
int p = 10;
System.out.println("---------------------------------------------------全部字符------");
for(int i = 0; i < k; i++) {
System.out.println("getRandomAllChar(): " + i + " -------");
System.out.println(getRandomALLChar(p));
}
System.out.println("------------------------------------------------字母字符---------");
for(int i = 0; i < k; i++) {
System.out.println("getRandomLetterChar(): " + i + " -------");
System.out.println(getRandomLetterChar(p));
}
System.out.println("-------------------------------------------------大写字母字符--------");
for(int i = 0; i < k; i++) {
System.out.println("getRandomUpperLetterChar(): " + i + " -------");
System.out.println(getRandomUpperLetterChar(p));
}
System.out.println("-------------------------------------------------小写字母字符--------");
for(int i = 0; i < k; i++) {
System.out.println("getRandomLowerLetterChar(): " + i + " -------");
System.out.println(getRandomLowerLetterChar(p));
}
System.out.println("------------------------------------------------数字字符---------");
for(int i = 0; i < k; i++) {
System.out.println("getRandomNumberChar(): " + i + " -------");
System.out.println(getRandomNumberChar(p));
}
System.out.println("-----------------------------------------------数字加大写字母字符----------");
for(int i = 0; i < k; i++) {
System.out.println("getRandomNumberUpperLetterChar(): " + i + " -------");
System.out.println(getRandomNumberUpperLetterChar(p));
}
System.out.println("------------------------------------------------数字加小写字母字符---------");
for(int i = 0; i < k; i++) {
System.out.println("getRandomNumberLowerLetterChar(): " + i + " -------");
System.out.println(getRandomNumberLowerLetterChar(p));
}
}
}
@@ -0,0 +1,34 @@
package com.beimi.util;
import java.util.Random;
public class RandomKey {
/**
* 生成随机密码
*
* @param pwd_len
* 生成的密码的总长度
* @return 密码的字符串
*/
public static String genRandomNum(int pwd_len) {
int i; // 生成的随机数
int count = 0; // 生成的密码的长度
char[] str = { '0', '1', '2', '3', '4', '5', '6', '7', '8','9'};
final int maxNum = str.length - 1;
StringBuilder pwd = new StringBuilder("");
Random r = new Random();
while (count < pwd_len) {
// 生成随机数,取绝对值,防止生成负数,
i = Math.abs(r.nextInt(maxNum)); // 生成的数最大为36-1
if (i >= 0 && i < str.length) {
pwd.append(str[i]);
count++;
}
}
return pwd.toString();
}
}

Some files were not shown because too many files have changed in this diff Show More