├── .gitignore ├── README.md ├── apps ├── app-allinone │ ├── build.gradle.kts │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── lj │ │ │ └── AppAllInOne.kt │ │ └── resources │ │ ├── conf │ │ ├── application.conf │ │ └── logback.xml │ │ └── fb │ │ ├── heroconfig.bin │ │ ├── skillconfig.bin │ │ └── unitconfig.bin ├── app-api │ ├── build.gradle.kts │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── lj │ │ │ ├── ApiServerVerticle.kt │ │ │ └── AppApiServer.kt │ │ └── resources │ │ └── conf │ │ ├── application.conf │ │ └── logback.xml ├── app-battle │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── lj │ │ │ │ ├── AppBattleServer.kt │ │ │ │ ├── BattleServerServiceVerticle.kt │ │ │ │ └── battle │ │ │ │ ├── Battle.kt │ │ │ │ ├── BattleManager.kt │ │ │ │ ├── event │ │ │ │ ├── EventIdType.kt │ │ │ │ └── handler │ │ │ │ │ ├── AddStatusHandler.kt │ │ │ │ │ └── ChangeAttributeHandler.kt │ │ │ │ ├── msg │ │ │ │ └── handler │ │ │ │ │ └── TestBattleHandler.kt │ │ │ │ ├── passives │ │ │ │ └── StatusTenacity.kt │ │ │ │ ├── skills │ │ │ │ └── Skill1001Ability.kt │ │ │ │ ├── status │ │ │ │ └── StatusScare.kt │ │ │ │ └── updater │ │ │ │ └── IUpdater.kt │ │ └── resources │ │ │ ├── conf │ │ │ ├── application.conf │ │ │ └── logback.xml │ │ │ └── skills │ │ │ ├── SkillConfigs │ │ │ ├── Skill_1001.json │ │ │ ├── Skill_1002.json │ │ │ ├── Skill_1003.json │ │ │ └── Skill_1004.json │ │ │ └── StatusConfigs │ │ │ ├── Status_AttackPowerModify.json │ │ │ ├── Status_AttackPowerPctModify.json │ │ │ ├── Status_Burn.json │ │ │ ├── Status_CauseDamagePctModify.json │ │ │ ├── Status_HealthRecovery.json │ │ │ ├── Status_HellAngel.json │ │ │ ├── Status_MoveSpeedPctModify.json │ │ │ ├── Status_Mute.json │ │ │ ├── Status_Scare.json │ │ │ ├── Status_Shield.json │ │ │ ├── Status_Vertigo.json │ │ │ └── Status_Weak.json │ │ └── test │ │ └── kotlin │ │ ├── BattleConfigTest.kt │ │ ├── CombatConextTest.kt │ │ ├── EventSystemTest.kt │ │ ├── FloatNumbericTest.kt │ │ └── HealthPointTest.kt ├── app-gameserver │ ├── build.gradle.kts │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── lj │ │ │ ├── AppGameServer.kt │ │ │ ├── GameServerServiceVerticle.kt │ │ │ └── msg │ │ │ ├── BenchmarkHandler.kt │ │ │ └── LoginGateHandler.kt │ │ └── resources │ │ ├── conf │ │ ├── application.conf │ │ └── logback.xml │ │ └── fb │ │ ├── heroconfig.bin │ │ ├── skillconfig.bin │ │ └── unitconfig.bin ├── app-gateway │ ├── build.gradle.kts │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── lj │ │ │ ├── AppGateway.kt │ │ │ └── GatewayVerticle.kt │ │ └── resources │ │ └── conf │ │ ├── application.conf │ │ └── logback.xml ├── app-login │ ├── build.gradle.kts │ └── src │ │ └── main │ │ ├── kotlin │ │ └── com │ │ │ └── lj │ │ │ ├── AppLogin.kt │ │ │ ├── LoginVerticle.kt │ │ │ └── msg │ │ │ └── LoginHandler.kt │ │ └── resources │ │ └── conf │ │ ├── application.conf │ │ └── logback.xml └── lib-core │ ├── build.gradle.kts │ └── src │ └── main │ ├── java │ └── com │ │ └── lj │ │ └── core │ │ ├── service │ │ └── package-info.java │ │ └── utils │ │ └── ClassScanner.java │ ├── kotlin │ ├── com │ │ └── lj │ │ │ └── core │ │ │ ├── common │ │ │ ├── CmdExecutor.kt │ │ │ ├── HandlerAnnotation.kt │ │ │ ├── IdGenerater.kt │ │ │ └── ServiceHandlerAnnotation.kt │ │ │ ├── consts │ │ │ ├── EventBusAddress.kt │ │ │ └── GlobalConst.kt │ │ │ ├── ecs │ │ │ ├── Component.kt │ │ │ ├── DBEntityManager.kt │ │ │ ├── Entity.kt │ │ │ ├── EntityFactory.kt │ │ │ ├── EventComponent.kt │ │ │ ├── IdFactory.kt │ │ │ ├── MasterEntity.kt │ │ │ ├── component │ │ │ │ ├── AccountComponent.kt │ │ │ │ ├── BagComponent.kt │ │ │ │ └── TeamComponent.kt │ │ │ └── entity │ │ │ │ └── PlayerEntity.kt │ │ │ ├── event │ │ │ ├── EventAnnotation.kt │ │ │ ├── EventSystem.kt │ │ │ └── IEvent.kt │ │ │ ├── gamePlay │ │ │ ├── combat │ │ │ │ ├── CombatActionManageComponent.kt │ │ │ │ ├── CombatContext.kt │ │ │ │ ├── attribute │ │ │ │ │ ├── AttributeComponent.kt │ │ │ │ │ ├── AttributeType.kt │ │ │ │ │ ├── FloatNumberic.kt │ │ │ │ │ ├── HealthPoint.kt │ │ │ │ │ └── IntNumberic.kt │ │ │ │ ├── entity │ │ │ │ │ ├── CombatEntity.kt │ │ │ │ │ ├── ability │ │ │ │ │ │ ├── AbilityEntity.kt │ │ │ │ │ │ ├── AbilityExecution.kt │ │ │ │ │ │ ├── AbilityItem.kt │ │ │ │ │ │ ├── skill │ │ │ │ │ │ │ ├── SkillAbility.kt │ │ │ │ │ │ │ └── SkillAbilityExecution.kt │ │ │ │ │ │ └── status │ │ │ │ │ │ │ ├── StatusAbility.kt │ │ │ │ │ │ │ ├── StatusAbilityExecution.kt │ │ │ │ │ │ │ └── StatusLifeTimeComponent.kt │ │ │ │ │ ├── action │ │ │ │ │ │ ├── ActionPointManageComponent.kt │ │ │ │ │ │ ├── AssignEffectAction.kt │ │ │ │ │ │ ├── CombatAction.kt │ │ │ │ │ │ ├── CureAction.kt │ │ │ │ │ │ ├── DamageAction.kt │ │ │ │ │ │ ├── MotionAction.kt │ │ │ │ │ │ └── SpellSkillAction.kt │ │ │ │ │ ├── condition │ │ │ │ │ │ ├── ConditionEntity.kt │ │ │ │ │ │ ├── ConditionManageComponent.kt │ │ │ │ │ │ └── WhenInTimeNoDamageCondition.kt │ │ │ │ │ └── logic │ │ │ │ │ │ ├── LogicActionTriggerComponent.kt │ │ │ │ │ │ ├── LogicConditionTriggerComponent.kt │ │ │ │ │ │ ├── LogicEntity.kt │ │ │ │ │ │ └── LogicIntervalTriggerComponent.kt │ │ │ │ └── timer │ │ │ │ │ ├── GameTimer.kt │ │ │ │ │ └── Time.kt │ │ │ ├── config │ │ │ │ ├── BattleConfigManager.kt │ │ │ │ ├── SkillConfigObject.kt │ │ │ │ ├── SkillDefine.kt │ │ │ │ ├── StatusConfigObject.kt │ │ │ │ └── effect │ │ │ │ │ ├── AddShieldEffect.kt │ │ │ │ │ ├── AddStatusEffect.kt │ │ │ │ │ ├── AttributeNumericModifyEffect.kt │ │ │ │ │ ├── ClearAllStatusEffect.kt │ │ │ │ │ ├── CureEffect.kt │ │ │ │ │ ├── CustomEffect.kt │ │ │ │ │ ├── DamageEffect.kt │ │ │ │ │ ├── Effect.kt │ │ │ │ │ ├── RemoveStatusEffect.kt │ │ │ │ │ └── StackTagEffect.kt │ │ │ └── helper │ │ │ │ └── ExpressionHelper.kt │ │ │ ├── net │ │ │ ├── Opcode.kt │ │ │ ├── SocketManager.kt │ │ │ └── msg │ │ │ │ ├── BaseHandler.kt │ │ │ │ ├── MessageDispatcher.kt │ │ │ │ └── MsgMessageCodec.kt │ │ │ └── service │ │ │ ├── GameService.kt │ │ │ ├── Msg.kt │ │ │ ├── handler │ │ │ ├── BaseHandler.kt │ │ │ └── ServiceDispatcher.kt │ │ │ └── impl │ │ │ └── GameServiceImpl.kt │ └── fb │ │ ├── FBManager.kt │ │ ├── heroconfigTB.kt │ │ ├── heroconfigTR.kt │ │ ├── skillconfigTB.kt │ │ ├── skillconfigTR.kt │ │ ├── unitconfigTB.kt │ │ └── unitconfigTR.kt │ └── proto │ ├── benchmark.proto │ ├── login.proto │ └── readme.txt ├── build.gradle.kts ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle.kts └── subProjects ├── nice-crypto ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── kt │ └── crypto │ ├── AesUtil.kt │ ├── Base64.kt │ ├── DESedeUtil.kt │ └── RsaUtil.kt ├── nice-log ├── build.gradle.kts └── src │ └── main │ ├── kotlin │ └── kt │ │ └── scaffold │ │ └── tools │ │ └── logger │ │ ├── AnsiColor.kt │ │ ├── Logger.kt │ │ └── conversions │ │ ├── ColoredLevel.kt │ │ └── ColoredMessage.kt │ └── resources │ └── logback.xml ├── nice-scaffold ├── build.gradle.kts └── src │ └── main │ ├── kotlin │ └── kt │ │ └── scaffold │ │ ├── Application.kt │ │ ├── cache │ │ └── CacheManager.kt │ │ ├── common │ │ └── MicroServiceVerticle.kt │ │ ├── mongo │ │ └── MongoManager.kt │ │ ├── net │ │ └── DiscoveryManager.kt │ │ ├── redis │ │ ├── RedisExt.kt │ │ └── RedisManager.kt │ │ └── tools │ │ └── KtException.kt │ └── resources │ └── reference.conf └── nice-tools ├── build.gradle.kts └── src ├── main ├── java │ └── com │ │ └── badlogic │ │ └── gdx │ │ ├── math │ │ ├── Affine2.java │ │ ├── BSpline.java │ │ ├── Bezier.java │ │ ├── Bresenham2.java │ │ ├── CatmullRomSpline.java │ │ ├── Circle.java │ │ ├── ConvexHull.java │ │ ├── CumulativeDistribution.java │ │ ├── DelaunayTriangulator.java │ │ ├── EarClippingTriangulator.java │ │ ├── Ellipse.java │ │ ├── FloatCounter.java │ │ ├── GeometryUtils.java │ │ ├── GridPoint2.java │ │ ├── GridPoint3.java │ │ ├── Interpolation.java │ │ ├── Intersector.java │ │ ├── MathUtils.java │ │ ├── Matrix3.java │ │ ├── Matrix4.java │ │ ├── Path.java │ │ ├── Plane.java │ │ ├── Polygon.java │ │ ├── Polyline.java │ │ ├── Quaternion.java │ │ ├── RandomXS128.java │ │ ├── Rectangle.java │ │ ├── Shape2D.java │ │ ├── Vector.java │ │ ├── Vector2.java │ │ ├── Vector3.java │ │ ├── WindowedMean.java │ │ └── collision │ │ │ ├── BoundingBox.java │ │ │ ├── Ray.java │ │ │ ├── Segment.java │ │ │ └── Sphere.java │ │ └── utils │ │ ├── Array.java │ │ ├── BooleanArray.java │ │ ├── ByteArray.java │ │ ├── CharArray.java │ │ ├── Collections.java │ │ ├── ComparableTimSort.java │ │ ├── FloatArray.java │ │ ├── GdxRuntimeException.java │ │ ├── IntArray.java │ │ ├── Null.java │ │ ├── NumberUtils.java │ │ ├── ObjectMap.java │ │ ├── ObjectSet.java │ │ ├── Pool.java │ │ ├── PooledLinkedList.java │ │ ├── Pools.java │ │ ├── Predicate.java │ │ ├── QuickSelect.java │ │ ├── ReflectionPool.java │ │ ├── Scaling.java │ │ ├── Select.java │ │ ├── ShortArray.java │ │ ├── Sort.java │ │ ├── TimSort.java │ │ └── reflect │ │ ├── Annotation.java │ │ ├── ArrayReflection.java │ │ ├── ClassReflection.java │ │ ├── Constructor.java │ │ ├── Field.java │ │ ├── Method.java │ │ └── ReflectionException.java └── kotlin │ └── kt │ ├── coroutines │ └── AutoThreadLocalElement.kt │ ├── date │ └── kxdate.kt │ ├── math │ ├── ImmutableVector.kt │ ├── ImmutableVector2.kt │ ├── matrix3.kt │ ├── matrix4.kt │ ├── ranges.kt │ ├── vector2.kt │ └── vector3.kt │ ├── objectPool │ ├── ObjectPool.kt │ ├── PoolConfig.kt │ ├── PooledObject.kt │ └── PooledObjectFactory.kt │ └── scaffold │ ├── ext │ ├── ConfigExt.kt │ ├── ExHelperFun.kt │ └── LoggerExt.kt │ └── tools │ ├── ExpressionParser.kt │ ├── StringChecker.kt │ ├── console │ └── PrettyTree.kt │ ├── csv │ └── CSV.kt │ └── json │ ├── Json.kt │ ├── JsonExt.kt │ └── JsonTypeUtils.kt └── test └── kotlin └── ExpressionParserTest.kt /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .gradle/ 3 | apps/app-allinone/build/ 4 | apps/app-gameserver/build/ 5 | apps/app-gateway/build/ 6 | apps/app-login/build/ 7 | apps/lib-core/build/ 8 | apps/vertxResearch/build/ 9 | subProjects/jodd-dependency/build/ 10 | subProjects/nice-crypto/build/ 11 | subProjects/nice-log/build/ 12 | subProjects/nice-scaffold/build/ 13 | subProjects/nice-tools/build/ 14 | apps/app-api/build/ 15 | apps/app-battle/build/ 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nice-KT 2 | 基于Kotlin + Vert.x 分布式服务端框架 3 | 4 | 5 | 6 | 服务器架构 : 7 | 8 | * 登录服:登录验证 9 | * 网关服:所有消息转发 10 | * 游戏服:游戏逻辑服 11 | * 战斗服:战斗逻辑服 12 | 13 | ## 运行环境 14 | 15 | JDK1.8以上, Idea2020.2 最新版经常有右键失灵的Bug 16 | 17 | 单机运行执行: AppAllInOne.kt 18 | 19 | ## 客户端 20 | https://github.com/Justin-sky/Nice-TS 21 | 22 | #### 文档 23 | 24 | 公式解析器:https://zhuanlan.zhihu.com/p/347753179 25 | 26 | 服务器监控:https://zhuanlan.zhihu.com/p/348812867 27 | 28 | 29 | QQ群:346340389 30 | -------------------------------------------------------------------------------- /apps/app-allinone/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 5 | kotlin("jvm") 6 | 7 | // Apply the application plugin to add support for building a CLI application. 8 | application 9 | } 10 | 11 | 12 | dependencies { 13 | implementation(kotlin("reflect")) 14 | 15 | //api(files("conf")) 16 | api(project(":apps:app-gateway")) 17 | api(project(":apps:app-login")) 18 | api(project(":apps:app-gameserver")) 19 | 20 | 21 | // Use the Kotlin test library. 22 | testImplementation("org.jetbrains.kotlin:kotlin-test") 23 | // Use the Kotlin JUnit integration. 24 | testImplementation("org.jetbrains.kotlin:kotlin-test-junit") 25 | 26 | 27 | configurations.all { 28 | this.exclude(group = "org.slf4j", module = "slf4j-log4j12") 29 | } 30 | 31 | } 32 | 33 | 34 | application { 35 | // Define the main class for the application. 36 | mainClass.set("com.lj.AppAllInOne") 37 | 38 | // 可以在此添加jvm内存参数, eg: '-Xms512m', '-Xmx4096m' 39 | applicationDefaultJvmArgs = listOf("-Xss512K","-Duser.timezone=GMT+8", "-Dfile.encoding=UTF-8", "-Dsun.jnu.encoding=UTF-8") 40 | } 41 | 42 | tasks.withType { 43 | options.encoding = "UTF-8" 44 | } 45 | 46 | val compileKotlin: KotlinCompile by tasks 47 | compileKotlin.kotlinOptions { 48 | jvmTarget = "1.8" 49 | } 50 | val compileTestKotlin: KotlinCompile by tasks 51 | compileTestKotlin.kotlinOptions { 52 | jvmTarget = "1.8" 53 | } 54 | 55 | val distZip: Zip by tasks 56 | distZip.into(project.name) { 57 | from("./src/main/resources") 58 | include("conf/**","fb/**") 59 | } 60 | 61 | val distTar: Tar by tasks 62 | distTar.enabled = false 63 | 64 | val installDist: Sync by tasks 65 | installDist.into("conf") { 66 | from("./src/main/resources/conf") 67 | include("*") 68 | } 69 | installDist.into("fb") { 70 | from("./src/main/resources/fb") 71 | include("**") 72 | } 73 | -------------------------------------------------------------------------------- /apps/app-allinone/src/main/kotlin/com/lj/AppAllInOne.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import com.lj.core.common.IdGenerater 4 | import com.lj.core.consts.EventBusAddress 5 | import com.lj.core.net.SocketManager 6 | import fb.FBManager 7 | import com.lj.core.net.msg.MessageDispatcher 8 | import com.lj.core.net.msg.MsgMessageCodec 9 | import com.lj.core.service.Msg 10 | import com.lj.core.service.handler.ServiceDispatcher 11 | import io.vertx.circuitbreaker.CircuitBreaker 12 | import io.vertx.circuitbreaker.CircuitBreakerOptions 13 | import io.vertx.ext.dropwizard.MetricsService 14 | import kt.scaffold.Application 15 | import kt.scaffold.tools.logger.Logger 16 | 17 | suspend fun main() { 18 | 19 | //注册消息处理器 20 | MessageDispatcher.initialize("com.lj.msg") 21 | //Service消息处理 22 | ServiceDispatcher.initialize("com.lj.msg") 23 | 24 | 25 | //加载静态表数据 26 | FBManager.initialize() 27 | 28 | //初始化Vertx 29 | Application.setupVertx() 30 | 31 | //初始化UUID 32 | IdGenerater.initUUID("niceMongo") 33 | 34 | //启动Login Server 35 | Application.deployVerticle(LoginVerticle::class.java.name,"LoginVerticle") 36 | 37 | 38 | //启动 Gateway Server 39 | Application.deployVerticle(GatewayVerticle::class.java.name,"GatewayVerticle") 40 | 41 | //启动Game Server 42 | Application.deployVerticle(GameServerServiceVerticle::class.java.name,"GameServerVerticle") 43 | 44 | //设置回调 45 | Application.setupOnStartAndOnStop() 46 | 47 | //注册eventbus编码器 48 | val eventBus = Application.vertx.eventBus() 49 | eventBus.registerDefaultCodec(Msg::class.java, MsgMessageCodec()) 50 | 51 | val consumer = eventBus.consumer(EventBusAddress.PUSH2CLIENT_ADDRESS) 52 | consumer.handler { message -> 53 | val msg = message.body() 54 | SocketManager.pushMsg2Client(msg.userId, msg) 55 | } 56 | 57 | //测试 ,查看信息 58 | val metricsService = MetricsService.create(Application.vertx) 59 | Application.vertx.setPeriodic(1800000){ 60 | val tcpMetric = metricsService.getMetricsSnapshot("vertx.eventbus.messages.reply-failures") 61 | Logger.debug(tcpMetric.toString()) 62 | 63 | } 64 | } -------------------------------------------------------------------------------- /apps/app-allinone/src/main/resources/conf/application.conf: -------------------------------------------------------------------------------- 1 | 2 | app { 3 | tcpServer { 4 | port = 9000 5 | host = "0.0.0.0" 6 | productionMode = true 7 | } 8 | loginServer { 9 | port = 9001 10 | host = "0.0.0.0" 11 | } 12 | Verticles{ 13 | GameServerVerticle{ 14 | workerMode = true 15 | instance = 1 16 | serverID = 10 17 | serverType = 1 18 | } 19 | GatewayVerticle{ 20 | workerMode = false 21 | instance = 1 22 | } 23 | LoginVerticle{ 24 | workerMode = false 25 | instance = 1 26 | } 27 | } 28 | } 29 | 30 | mongo{ 31 | niceMongo{ 32 | // Single Cluster Settings 33 | "host" : "60.1.1.22", // string 34 | "port" : 27017, // int 35 | "db_name":"kt", 36 | 37 | // Connection Pool Settings 38 | "maxPoolSize" : 50, // int 39 | "minPoolSize" : 25, // int 40 | "maxIdleTimeMS" : 300000, // long 41 | "maxLifeTimeMS" : 3600000, // long 42 | "waitQueueTimeoutMS" : 10000, // long 43 | "maintenanceFrequencyMS" : 2000, // long 44 | "maintenanceInitialDelayMS" : 500, // long 45 | 46 | // Credentials / Auth 47 | "username" : "zhj", // string 48 | "password" : "zhj666", // string 49 | "authSource" : "admin" // string 50 | 51 | // Auth mechanism 52 | "authMechanism" : "SCRAM-SHA-1", // string 53 | 54 | 55 | // Socket Settings 56 | "connectTimeoutMS" : 300000, // int 57 | "socketTimeoutMS" : 100000, // int 58 | "sendBufferSize" : 8192, // int 59 | "receiveBufferSize" : 8192, // int 60 | } 61 | } 62 | 63 | redis { 64 | // 配置项的 key 为 redis 配置名称 65 | // redis 配置名称不能重复 66 | niceRedis { 67 | options { 68 | // endpoint 格式说明: redis://[:password@]host[:port][/db-number] 69 | endpoints = ["redis://zhj666@60.1.1.22:6379/15"] 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /apps/app-allinone/src/main/resources/conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | logs/application.log 9 | 10 | %date{HH:mm:ss.SSS} [%level] from [%logger] in [%thread] - %coloredMsg{com.api}%n%xException 11 | 12 | 13 | 14 | 15 | 16 | %date{HH:mm:ss.SSS} [%coloredLevel] [%logger] in [%thread] - %coloredMsg{com.api}%n%xException{10} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /apps/app-allinone/src/main/resources/fb/heroconfig.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin-sky/Nice-KT/114d3561067181aa544ad719652dad3e6570d067/apps/app-allinone/src/main/resources/fb/heroconfig.bin -------------------------------------------------------------------------------- /apps/app-allinone/src/main/resources/fb/skillconfig.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin-sky/Nice-KT/114d3561067181aa544ad719652dad3e6570d067/apps/app-allinone/src/main/resources/fb/skillconfig.bin -------------------------------------------------------------------------------- /apps/app-allinone/src/main/resources/fb/unitconfig.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin-sky/Nice-KT/114d3561067181aa544ad719652dad3e6570d067/apps/app-allinone/src/main/resources/fb/unitconfig.bin -------------------------------------------------------------------------------- /apps/app-api/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | import org.jetbrains.kotlin.kapt3.base.Kapt.kapt 3 | 4 | plugins { 5 | java 6 | idea 7 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 8 | kotlin("jvm") 9 | 10 | application 11 | } 12 | 13 | dependencies { 14 | implementation(kotlin("reflect")) 15 | 16 | //api(files("conf")) 17 | api(project(":apps:lib-core")) 18 | 19 | api("io.vertx:vertx-web:4.0.0") 20 | 21 | // Use the Kotlin test library. 22 | testImplementation("org.jetbrains.kotlin:kotlin-test") 23 | // Use the Kotlin JUnit integration. 24 | testImplementation("org.jetbrains.kotlin:kotlin-test-junit") 25 | 26 | 27 | configurations.all { 28 | this.exclude(group = "org.slf4j", module = "slf4j-log4j12") 29 | } 30 | 31 | } 32 | 33 | application { 34 | // Define the main class for the application. 35 | mainClass.set("com.lj.AppApiServer") 36 | 37 | // 可以在此添加jvm内存参数, eg: '-Xms512m', '-Xmx4096m' 38 | applicationDefaultJvmArgs = listOf("-Duser.timezone=GMT+8", "-Dfile.encoding=UTF-8", "-Dsun.jnu.encoding=UTF-8") 39 | } 40 | 41 | tasks.withType { 42 | options.encoding = "UTF-8" 43 | } 44 | 45 | val compileKotlin: KotlinCompile by tasks 46 | compileKotlin.kotlinOptions { 47 | jvmTarget = "1.8" 48 | } 49 | val compileTestKotlin: KotlinCompile by tasks 50 | compileTestKotlin.kotlinOptions { 51 | jvmTarget = "1.8" 52 | } 53 | 54 | val distZip: Zip by tasks 55 | distZip.into(project.name) { 56 | from("./src/main/resources") 57 | include("conf/**") 58 | } 59 | 60 | val distTar: Tar by tasks 61 | distTar.enabled = false 62 | 63 | val installDist: Sync by tasks 64 | installDist.into("conf") { 65 | from("./src/main/resources/conf") 66 | include("*") 67 | } 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /apps/app-api/src/main/kotlin/com/lj/ApiServerVerticle.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import io.vertx.core.AbstractVerticle 4 | import io.vertx.core.buffer.Buffer 5 | import io.vertx.core.http.HttpMethod 6 | import io.vertx.core.http.HttpServerOptions 7 | import io.vertx.ext.dropwizard.MetricsService 8 | import io.vertx.ext.web.Router 9 | import kt.scaffold.Application 10 | import kt.scaffold.tools.logger.Logger 11 | 12 | class ApiServerVerticle : AbstractVerticle() { 13 | override fun start() { 14 | super.start() 15 | 16 | val port =Application.config.getInt("app.httpServer.port") 17 | val host =Application.config.getString("app.httpServer.host") 18 | 19 | val options = HttpServerOptions() 20 | options.host = host 21 | options.port = port 22 | 23 | val server = vertx.createHttpServer(options) 24 | 25 | val router = Router.router(vertx) 26 | 27 | val metricsService = MetricsService.create(vertx) 28 | 29 | 30 | //写法1 http://127.0.0.1/api/ 31 | router.route("/api/*").handler(){ ctx-> 32 | 33 | //测试 Metrics 34 | //Vert.x 35 | val eventLoopSize = metricsService.getMetricsSnapshot("vertx.event-loop-size") 36 | val workerPoolSize = metricsService.getMetricsSnapshot("vertx.worker-pool-size") 37 | val clusterHost = metricsService.getMetricsSnapshot("vertx.cluster-host") 38 | val clusterPort = metricsService.getMetricsSnapshot("vertx.cluster-port") 39 | 40 | Logger.debug(eventLoopSize.toString()) 41 | Logger.debug(workerPoolSize.toString()) 42 | Logger.debug(clusterHost.toString()) 43 | Logger.debug(clusterPort.toString()) 44 | 45 | 46 | //event bus metrics 47 | val eventBus = metricsService.getMetricsSnapshot("vertx.eventbus") 48 | Logger.debug(eventBus.toString()) 49 | 50 | 51 | //http metrics 52 | val httpMetric = metricsService.getMetricsSnapshot("vertx.http.servers.127.0.0.1:80") 53 | Logger.debug(httpMetric.toString()) 54 | 55 | 56 | //net server metrics 57 | val tcpMetric = metricsService.getMetricsSnapshot("vertx.net.servers") 58 | Logger.debug(tcpMetric.toString()) 59 | 60 | 61 | //pool metrics 62 | val poolMetric = metricsService.getMetricsSnapshot("vertx.pools") 63 | Logger.debug(poolMetric.toString()) 64 | 65 | ctx.response().end(eventLoopSize.toString()) 66 | } 67 | 68 | 69 | server.requestHandler(router) 70 | 71 | server.listen(){res-> 72 | if(res.succeeded()){ 73 | Logger.debug("start api server succ, $host : $port") 74 | }else{ 75 | Logger.error("$host : $port ,error:"+res.cause().toString()) 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /apps/app-api/src/main/kotlin/com/lj/AppApiServer.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import io.vertx.core.buffer.Buffer 4 | import io.vertx.core.http.HttpMethod 5 | import io.vertx.core.http.HttpServerOptions 6 | import io.vertx.ext.web.Router 7 | import kt.scaffold.Application 8 | import kt.scaffold.tools.logger.Logger 9 | 10 | suspend fun main() { 11 | 12 | //初始化Vertx 13 | Application.setupVertx() 14 | 15 | //启动Game Server 16 | Application.deployVerticle(ApiServerVerticle::class.java.name,"ApiServerVerticle") 17 | 18 | 19 | } -------------------------------------------------------------------------------- /apps/app-api/src/main/resources/conf/application.conf: -------------------------------------------------------------------------------- 1 | 2 | app { 3 | httpServer{ 4 | host:"127.0.0.1" 5 | port:80 6 | } 7 | 8 | Verticles{ 9 | ApiServerVerticle{ 10 | workerMode = true 11 | instance = 1 12 | } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /apps/app-api/src/main/resources/conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | logs/application.log 9 | 10 | %date{HH:mm:ss.SSS} [%level] from [%logger] in [%thread] - %coloredMsg{com.api}%n%xException 11 | 12 | 13 | 14 | 15 | 16 | %date{HH:mm:ss.SSS} [%coloredLevel] [%logger] in [%thread] - %coloredMsg{com.api}%n%xException{10} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /apps/app-battle/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | import org.jetbrains.kotlin.kapt3.base.Kapt.kapt 3 | 4 | plugins { 5 | idea 6 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 7 | kotlin("jvm") 8 | 9 | application 10 | } 11 | 12 | dependencies { 13 | implementation(kotlin("reflect")) 14 | 15 | //api(files("conf")) 16 | api(project(":apps:lib-core")) 17 | 18 | // Use the Kotlin test library. 19 | testImplementation("org.jetbrains.kotlin:kotlin-test") 20 | // Use the Kotlin JUnit integration. 21 | testImplementation("org.jetbrains.kotlin:kotlin-test-junit") 22 | 23 | configurations.all { 24 | this.exclude(group = "org.slf4j", module = "slf4j-log4j12") 25 | } 26 | 27 | } 28 | 29 | application { 30 | // Define the main class for the application. 31 | mainClass.set("com.lj.AppBattleServer") 32 | 33 | // 可以在此添加jvm内存参数, eg: '-Xms512m', '-Xmx4096m' 34 | applicationDefaultJvmArgs = listOf("-Duser.timezone=GMT+8", "-Dfile.encoding=UTF-8", "-Dsun.jnu.encoding=UTF-8") 35 | } 36 | 37 | tasks.withType { 38 | options.encoding = "UTF-8" 39 | } 40 | 41 | val compileKotlin: KotlinCompile by tasks 42 | compileKotlin.kotlinOptions { 43 | jvmTarget = "1.8" 44 | } 45 | val compileTestKotlin: KotlinCompile by tasks 46 | compileTestKotlin.kotlinOptions { 47 | jvmTarget = "1.8" 48 | } 49 | 50 | val distZip: Zip by tasks 51 | distZip.into(project.name) { 52 | from("./src/main/resources") 53 | include("conf/**") 54 | } 55 | 56 | val distTar: Tar by tasks 57 | distTar.enabled = false 58 | 59 | val installDist: Sync by tasks 60 | installDist.into("conf") { 61 | from("./src/main/resources/conf") 62 | include("*") 63 | } 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/AppBattleServer.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import com.lj.core.ecs.Entity 4 | import com.lj.core.gamePlay.combat.CombatContext 5 | import com.lj.core.gamePlay.combat.entity.logic.LogicEntity 6 | import com.lj.core.net.msg.MsgMessageCodec 7 | import com.lj.core.service.Msg 8 | import fb.FBManager 9 | import kt.scaffold.Application 10 | import kt.scaffold.tools.logger.Logger 11 | import kotlin.system.measureNanoTime 12 | import kotlin.system.measureTimeMillis 13 | 14 | 15 | suspend fun main() { 16 | 17 | //加载静态表数据 18 | FBManager.initialize() 19 | 20 | //初始化Vertx 21 | Application.setupVertx() 22 | 23 | //启动Game Server 24 | Application.deployVerticle(BattleServerServiceVerticle::class.java.name,"BattleServerVerticle") 25 | 26 | //注册eventbus编码器 27 | val eventBus = Application.vertx.eventBus() 28 | eventBus.registerDefaultCodec(Msg::class.java, MsgMessageCodec()) 29 | 30 | 31 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/BattleServerServiceVerticle.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import com.lj.battle.BattleManager 4 | import com.lj.core.consts.EventBusAddress 5 | import com.lj.core.gamePlay.combat.timer.Time 6 | import com.lj.core.service.GameService 7 | import com.lj.core.service.impl.GameServiceImpl 8 | import io.vertx.core.Launcher 9 | import io.vertx.serviceproxy.ServiceBinder 10 | import kotlinx.coroutines.GlobalScope 11 | import kotlinx.coroutines.launch 12 | import kt.scaffold.Application 13 | import kt.scaffold.common.MicroServiceVerticle 14 | import kt.scaffold.net.DiscoveryManager 15 | 16 | class BattleServerServiceVerticle:MicroServiceVerticle() { 17 | 18 | override suspend fun start() { 19 | super.start() 20 | 21 | val serverID = Application.config.getString("app.Verticles.BattleServerVerticle.serverID") 22 | val serverType = Application.config.getInt("app.Verticles.BattleServerVerticle.serverType") 23 | val binder = ServiceBinder(vertx) 24 | //==================此处注册并发布服务 25 | binder.setAddress(EventBusAddress.SERVICE_BATTLESERVER_ADDRESS).register( 26 | GameService::class.java, 27 | GameServiceImpl() 28 | ) 29 | DiscoveryManager.publishEventBusServiceAwait( 30 | EventBusAddress.SERVICE_BATTLESERVER_NAME, 31 | EventBusAddress.SERVICE_BATTLESERVER_ADDRESS, 32 | GameService::class.java, 33 | serverID.toInt(), 34 | serverType.toInt() 35 | ) 36 | 37 | vertx.setPeriodic(Time.deltaTime.toLong()){ 38 | GlobalScope.launch { 39 | BattleManager.update() 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/battle/Battle.kt: -------------------------------------------------------------------------------- 1 | package com.lj.battle 2 | 3 | import com.lj.battle.updater.IUpdater 4 | import com.lj.core.gamePlay.combat.CombatContext 5 | import com.lj.core.gamePlay.combat.timer.Time 6 | 7 | class Battle(var combatContext: CombatContext): IUpdater { 8 | 9 | private var isEnemyTurn:Boolean = false 10 | private var accTime:Float = 0f 11 | private var isEndOfGame:Boolean = false 12 | private val enemyTurnDuration = 3f 13 | 14 | 15 | override suspend fun update(){ 16 | if (isEnemyTurn){ 17 | accTime += Time.deltaTime 18 | if (accTime >= enemyTurnDuration){ 19 | accTime = 0f 20 | endEnemyTurn() 21 | beginPlayerTurn() 22 | } 23 | } 24 | } 25 | 26 | fun beginGame(){ 27 | beginPlayerTurn() 28 | } 29 | 30 | fun beginPlayerTurn(){ 31 | //PlayerTurnBegan.Raise(); 32 | } 33 | 34 | fun endPlayerTurn(){ 35 | //PlayerTurnEnded.Raise(); 36 | beginEnemyTurn() 37 | } 38 | 39 | fun beginEnemyTurn(){ 40 | //EnemyTurnBegan.Raise(); 41 | isEnemyTurn = true 42 | } 43 | 44 | fun endEnemyTurn(){ 45 | //EnemyTurnEnded.Raise(); 46 | isEnemyTurn = false 47 | } 48 | 49 | fun setEndOfGame(value:Boolean){ 50 | isEndOfGame = value 51 | } 52 | 53 | fun isEndOfGame():Boolean{ 54 | return isEndOfGame 55 | } 56 | 57 | 58 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/battle/BattleManager.kt: -------------------------------------------------------------------------------- 1 | package com.lj.battle 2 | 3 | import com.lj.battle.updater.IUpdater 4 | 5 | object BattleManager : IUpdater { 6 | 7 | private val battles = mutableMapOf() 8 | 9 | fun getBattle(id:Long): Battle? { 10 | return battles[id] 11 | } 12 | 13 | fun addBattel(id:Long, battle: Battle){ 14 | this.battles[id] = battle 15 | } 16 | 17 | override suspend fun update(){ 18 | battles.values.forEach{item-> 19 | item.update() 20 | } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/battle/event/EventIdType.kt: -------------------------------------------------------------------------------- 1 | package com.lj.battle.event 2 | 3 | /** 4 | * 服务器向客户端同步的事件 5 | */ 6 | class EventIdType { 7 | companion object { 8 | const val changeAttribute = "ChangeAttribute" 9 | const val addStatus = "AddStatus" 10 | } 11 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/battle/event/handler/AddStatusHandler.kt: -------------------------------------------------------------------------------- 1 | package com.lj.battle.event.handler 2 | 3 | import com.lj.battle.event.EventIdType 4 | import com.lj.core.event.AEvent1 5 | import com.lj.core.event.EventAnnotation 6 | import kt.scaffold.tools.logger.Logger 7 | 8 | @EventAnnotation(EventIdType.addStatus) 9 | class AddStatusHandler : AEvent1() { 10 | 11 | override fun run(a: String) { 12 | Logger.debug("add status ") 13 | } 14 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/battle/event/handler/ChangeAttributeHandler.kt: -------------------------------------------------------------------------------- 1 | package com.lj.battle.event.handler 2 | 3 | import com.lj.battle.event.EventIdType 4 | import com.lj.core.event.AEvent1 5 | import com.lj.core.event.EventAnnotation 6 | import kotlinx.coroutines.GlobalScope 7 | import kotlinx.coroutines.launch 8 | import kt.scaffold.tools.logger.Logger 9 | 10 | @EventAnnotation(EventIdType.changeAttribute) 11 | class ChangeAttributeHandler : AEvent1() { 12 | 13 | override fun run(a: String) { 14 | GlobalScope.launch { 15 | for (i in 0..10000){ 16 | 17 | } 18 | Logger.debug("change attribute...$a") 19 | } 20 | 21 | } 22 | 23 | 24 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/battle/msg/handler/TestBattleHandler.kt: -------------------------------------------------------------------------------- 1 | package com.lj.battle.msg.handler 2 | 3 | import com.lj.core.common.ServiceHandlerAnnotation 4 | import com.lj.core.net.Opcode 5 | import com.lj.core.service.Msg 6 | import com.lj.core.service.handler.BaseHandler 7 | import io.vertx.core.AsyncResult 8 | import io.vertx.core.Handler 9 | 10 | @ServiceHandlerAnnotation(opcode = Opcode.MSG_C2GS_Test) 11 | class TestBattleHandler:BaseHandler() { 12 | override fun process(msg: Msg, handler: Handler>) { 13 | //处理战斗消息 14 | 15 | 16 | 17 | 18 | } 19 | 20 | 21 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/battle/passives/StatusTenacity.kt: -------------------------------------------------------------------------------- 1 | package com.lj.battle.passives 2 | 3 | import com.lj.core.gamePlay.combat.entity.ability.status.StatusAbility 4 | import com.lj.core.gamePlay.combat.timer.GameTimer 5 | 6 | class StatusTenacity:StatusAbility() { 7 | 8 | private val healthReplyTImer = GameTimer(2f) 9 | 10 | override fun activateAbility() { 11 | super.activateAbility() 12 | 13 | 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/battle/skills/Skill1001Ability.kt: -------------------------------------------------------------------------------- 1 | package com.lj.battle.skills 2 | 3 | import com.lj.core.gamePlay.combat.entity.CombatEntity 4 | import com.lj.core.gamePlay.combat.entity.ability.AbilityExecution 5 | import com.lj.core.gamePlay.combat.entity.ability.skill.SkillAbility 6 | import com.lj.core.gamePlay.combat.entity.ability.skill.SkillAbilityExecution 7 | 8 | class Skill1001Ability:SkillAbility() { 9 | 10 | override fun createAbilityExecution(): AbilityExecution? { 11 | return createWithParent(getParentT()) 12 | } 13 | 14 | } 15 | 16 | class Skill1001Execution:SkillAbilityExecution(){ 17 | 18 | override fun beginExecute() { 19 | super.beginExecute() 20 | 21 | 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/battle/status/StatusScare.kt: -------------------------------------------------------------------------------- 1 | package com.lj.battle.status 2 | 3 | import com.lj.core.gamePlay.combat.entity.ability.status.StatusAbility 4 | 5 | class StatusScare : StatusAbility() { 6 | 7 | override fun activateAbility() { 8 | super.activateAbility() 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/kotlin/com/lj/battle/updater/IUpdater.kt: -------------------------------------------------------------------------------- 1 | package com.lj.battle.updater 2 | 3 | interface IUpdater{ 4 | suspend fun update() 5 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/conf/application.conf: -------------------------------------------------------------------------------- 1 | 2 | app { 3 | Verticles{ 4 | BattleServerVerticle{ 5 | workerMode = true 6 | instance = 1 7 | serverID = 10 8 | serverType = 2 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | logs/application.log 9 | 10 | %date{HH:mm:ss.SSS} [%level] from [%logger] in [%thread] - %coloredMsg{com.api}%n%xException 11 | 12 | 13 | 14 | 15 | 16 | %date{HH:mm:ss.SSS} [%coloredLevel] [%logger] in [%thread] - %coloredMsg{com.api}%n%xException{10} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/SkillConfigs/Skill_1001.json: -------------------------------------------------------------------------------- 1 | {"id":1001,"name":"黑火球术","skillSpellType":0,"targetSelectType":1,"affectAreaType":0,"circleAreaRadius":0.0,"affectTargetType":2,"coldTime":0,"effects":[{"damageType":1,"damageValueFormula":"300+自身攻击力*0.4","canCrit":false,"addSkillEffectTargetType":0,"effectTriggerType":0,"conditionType":0,"actionPointType":0,"interval":null,"conditionParam":null,"triggerProbability":"100%","@class":"DamageEffect"},{"addStatus":"Burn","duration":6000,"params":{"伤害值":"100+自身法术强度*0.2","间隔时间":"400-技能等级*50"},"addSkillEffectTargetType":0,"effectTriggerType":0,"conditionType":0,"actionPointType":0,"interval":null,"conditionParam":null,"triggerProbability":"100%","@class":"AddStatusEffect"}]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/SkillConfigs/Skill_1002.json: -------------------------------------------------------------------------------- 1 | {"id":1002,"name":"炎爆","skillSpellType":0,"targetSelectType":3,"affectAreaType":0,"circleAreaRadius":1.0,"affectTargetType":2,"coldTime":0,"effects":[{"damageType":0,"damageValueFormula":"800","canCrit":true,"addSkillEffectTargetType":0,"effectTriggerType":0,"conditionType":0,"actionPointType":0,"interval":null,"conditionParam":null,"triggerProbability":"100%","@class":"DamageEffect"},{"addStatus":null,"duration":50000,"params":{},"addSkillEffectTargetType":0,"effectTriggerType":0,"conditionType":0,"actionPointType":0,"interval":null,"conditionParam":null,"triggerProbability":"100%","@class":"AddStatusEffect"}]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/SkillConfigs/Skill_1003.json: -------------------------------------------------------------------------------- 1 | {"id":1003,"name":"治愈","skillSpellType":0,"targetSelectType":0,"affectAreaType":0,"circleAreaRadius":0.0,"affectTargetType":0,"coldTime":3000,"effects":[{"cureValueFormula":"200","addSkillEffectTargetType":0,"effectTriggerType":0,"conditionType":0,"actionPointType":0,"interval":null,"conditionParam":null,"triggerProbability":"100%","@class":"CureEffect"}]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/SkillConfigs/Skill_1004.json: -------------------------------------------------------------------------------- 1 | {"id":1004,"name":"血红激光炮","skillSpellType":0,"targetSelectType":3,"affectAreaType":1,"circleAreaRadius":0.0,"affectTargetType":2,"coldTime":0,"effects":[{"damageType":1,"damageValueFormula":"10000","canCrit":false,"addSkillEffectTargetType":0,"effectTriggerType":0,"conditionType":0,"actionPointType":0,"interval":null,"conditionParam":null,"triggerProbability":"100%","@class":"DamageEffect"}]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_AttackPowerModify.json: -------------------------------------------------------------------------------- 1 | {"id":"AttackPowerModify","name":"攻击力修饰","statusType":2,"duration":0,"showInStatusSlots":true,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":false,"actionControlType":0,"enabledAttributeModify":true,"attributeType":1001,"numericValue":"变动数值","modifyType":0,"enabledLogicTrigger":false,"effects":[]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_AttackPowerPctModify.json: -------------------------------------------------------------------------------- 1 | {"id":"AttackPowerPctModify","name":"攻击力百分比修饰","statusType":2,"duration":0,"showInStatusSlots":true,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":false,"actionControlType":0,"enabledAttributeModify":true,"attributeType":1001,"numericValue":"变动数值","modifyType":1,"enabledLogicTrigger":false,"effects":[]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_Burn.json: -------------------------------------------------------------------------------- 1 | {"id":"Burn","name":"普通灼烧","statusType":1,"duration":0,"showInStatusSlots":true,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":false,"actionControlType":0,"enabledAttributeModify":false,"attributeType":0,"numericValue":"","modifyType":0,"enabledLogicTrigger":true,"effects":[{"damageType":0,"damageValueFormula":null,"canCrit":false,"addSkillEffectTargetType":0,"effectTriggerType":0,"conditionType":0,"actionPointType":0,"interval":null,"conditionParam":null,"triggerProbability":"100%","@class":"DamageEffect"}]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_CauseDamagePctModify.json: -------------------------------------------------------------------------------- 1 | {"id":"CauseDamagePctModify","name":"造成伤害百分比修饰","statusType":2,"duration":0,"showInStatusSlots":true,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":false,"actionControlType":0,"enabledAttributeModify":true,"attributeType":4001,"numericValue":"变动数值","modifyType":1,"enabledLogicTrigger":false,"effects":[]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_HealthRecovery.json: -------------------------------------------------------------------------------- 1 | {"id":"HealthRecovery","name":"生命回复","statusType":0,"duration":0,"showInStatusSlots":false,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":false,"actionControlType":0,"enabledAttributeModify":false,"attributeType":0,"numericValue":"","modifyType":0,"enabledLogicTrigger":true,"effects":[{"cureValueFormula":"回复量","addSkillEffectTargetType":0,"effectTriggerType":3,"conditionType":0,"actionPointType":0,"interval":"间隔时间","conditionParam":null,"triggerProbability":"100%","@class":"CureEffect"}]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_HellAngel.json: -------------------------------------------------------------------------------- 1 | {"id":"HellAngel","name":"地狱使者","statusType":0,"duration":0,"showInStatusSlots":false,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":false,"actionControlType":0,"enabledAttributeModify":false,"attributeType":0,"numericValue":"","modifyType":0,"enabledLogicTrigger":true,"effects":[{"addStatus":"Mute","duration":0,"params":{},"addSkillEffectTargetType":0,"effectTriggerType":0,"conditionType":0,"actionPointType":0,"interval":null,"conditionParam":null,"triggerProbability":"100%","@class":"AddStatusEffect"}]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_MoveSpeedPctModify.json: -------------------------------------------------------------------------------- 1 | {"id":"MoveSpeedPctModify","name":"移动速度百分比修饰","statusType":2,"duration":0,"showInStatusSlots":true,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":false,"actionControlType":0,"enabledAttributeModify":true,"attributeType":2002,"numericValue":"变动数值","modifyType":1,"enabledLogicTrigger":false,"effects":[]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_Mute.json: -------------------------------------------------------------------------------- 1 | {"id":"Mute","name":"沉默","statusType":1,"duration":0,"showInStatusSlots":true,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":true,"actionControlType":4,"enabledAttributeModify":false,"attributeType":0,"numericValue":"","modifyType":0,"enabledLogicTrigger":false,"effects":[]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_Scare.json: -------------------------------------------------------------------------------- 1 | {"id":"Scare","name":"恐惧","statusType":1,"duration":0,"showInStatusSlots":true,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":true,"actionControlType":28,"enabledAttributeModify":false,"attributeType":0,"numericValue":"","modifyType":0,"enabledLogicTrigger":false,"effects":[]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_Shield.json: -------------------------------------------------------------------------------- 1 | {"id":"Shield","name":"护盾","statusType":0,"duration":0,"showInStatusSlots":false,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":false,"actionControlType":0,"enabledAttributeModify":true,"attributeType":3001,"numericValue":"护盾值","modifyType":0,"enabledLogicTrigger":false,"effects":[]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_Vertigo.json: -------------------------------------------------------------------------------- 1 | {"id":"Vertigo","name":"眩晕","statusType":1,"duration":0,"showInStatusSlots":true,"canStack":false,"maxStack":0,"enableChildrenStatuses":false,"childrenStatuses":[],"enabledStateModify":true,"actionControlType":14,"enabledAttributeModify":false,"attributeType":0,"numericValue":"","modifyType":0,"enabledLogicTrigger":false,"effects":[]} -------------------------------------------------------------------------------- /apps/app-battle/src/main/resources/skills/StatusConfigs/Status_Weak.json: -------------------------------------------------------------------------------- 1 | {"id":"Weak","name":"虚弱","statusType":1,"duration":0,"showInStatusSlots":true,"canStack":false,"maxStack":0,"enableChildrenStatuses":true,"childrenStatuses":[{"statusConfigObject":null,"params":null},{"statusConfigObject":null,"params":null}],"enabledStateModify":false,"actionControlType":0,"enabledAttributeModify":false,"attributeType":0,"numericValue":"","modifyType":0,"enabledLogicTrigger":false,"effects":[]} -------------------------------------------------------------------------------- /apps/app-battle/src/test/kotlin/BattleConfigTest.kt: -------------------------------------------------------------------------------- 1 | import com.lj.core.gamePlay.config.BattleConfigManager 2 | import org.junit.After 3 | import org.junit.Before 4 | import org.junit.Test 5 | 6 | class BattleConfigTest { 7 | 8 | @Before 9 | fun setUp(){ 10 | } 11 | 12 | @After 13 | fun tearDown(){ 14 | } 15 | 16 | @Test 17 | fun testSetBase(){ 18 | BattleConfigManager.getSkillConfig("1001") 19 | BattleConfigManager.getSkillConfig("1002") 20 | BattleConfigManager.getSkillConfig("1003") 21 | BattleConfigManager.getSkillConfig("1004") 22 | 23 | BattleConfigManager.getStatusConfig("AttackPowerModify") 24 | BattleConfigManager.getStatusConfig("AttackPowerPctModify") 25 | BattleConfigManager.getStatusConfig("Burn") 26 | BattleConfigManager.getStatusConfig("CauseDamagePctModify") 27 | BattleConfigManager.getStatusConfig("CauseDamagePctModify") 28 | BattleConfigManager.getStatusConfig("HellAngel") 29 | BattleConfigManager.getStatusConfig("MoveSpeedPctModify") 30 | BattleConfigManager.getStatusConfig("Mute") 31 | BattleConfigManager.getStatusConfig("Scare") 32 | BattleConfigManager.getStatusConfig("Shield") 33 | BattleConfigManager.getStatusConfig("Vertigo") 34 | BattleConfigManager.getStatusConfig("Weak") 35 | } 36 | } -------------------------------------------------------------------------------- /apps/app-battle/src/test/kotlin/CombatConextTest.kt: -------------------------------------------------------------------------------- 1 | import com.lj.core.ecs.Entity 2 | import com.lj.core.gamePlay.combat.CombatContext 3 | import com.lj.core.gamePlay.combat.entity.CombatEntity 4 | import com.lj.battle.skills.Skill1001Ability 5 | import com.lj.battle.status.StatusScare 6 | import com.lj.core.gamePlay.combat.entity.action.ActionPointType 7 | import com.lj.core.gamePlay.combat.entity.action.DamageAction 8 | import com.lj.core.gamePlay.combat.entity.logic.LogicEntity 9 | import com.lj.core.gamePlay.config.BattleConfigManager 10 | import kt.scaffold.ext.debug 11 | import kt.scaffold.tools.logger.Logger 12 | import org.junit.After 13 | import org.junit.Before 14 | import org.junit.Test 15 | import kotlin.system.measureTimeMillis 16 | 17 | class CombatConextTest { 18 | @Before 19 | fun setUp(){ 20 | 21 | var time = measureTimeMillis { 22 | //Your code... 23 | } 24 | } 25 | 26 | @After 27 | fun tearDown(){ 28 | 29 | } 30 | 31 | @Test 32 | fun testCombatContext(){ 33 | 34 | 35 | //战斗上下文 ,自动添加 CombatActionManageComponent 组件 36 | var context1 = Entity.create() 37 | 38 | 39 | //monster,战斗实体,监听ActionPoint事件 40 | val monster = Entity.createWithParent(context1) 41 | monster.listenActionPoint(ActionPointType.PostReceiveDamage){combatAction-> 42 | Logger.debug(combatAction.actionType) 43 | } 44 | monster.listenActionPoint(ActionPointType.PostReceiveCure){combatAction-> 45 | Logger.debug(combatAction.actionType) 46 | } 47 | 48 | //给Monster添加状态 49 | val statusConfig = BattleConfigManager.getStatusConfig("Scare") 50 | val status = monster.attachStatus(statusConfig!!) 51 | status.caster = monster 52 | status.tryActivateAbility() 53 | 54 | 55 | //hero 战斗实体 56 | val hero1 = Entity.createWithParent(context1) 57 | 58 | //添加技能 59 | val skillConfig = BattleConfigManager.getSkillConfig("1001") 60 | val skillAbility = hero1.attachSkill(skillConfig!!) 61 | skillAbility.applyAbilityEffectsTo(monster) 62 | 63 | val action = hero1.createCombatAction()!! 64 | action.target = monster 65 | action.damageSource = DamageAction.DamageSource.Attack 66 | action.applyAction() 67 | 68 | 69 | 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /apps/app-battle/src/test/kotlin/EventSystemTest.kt: -------------------------------------------------------------------------------- 1 | import com.lj.battle.event.EventIdType 2 | import com.lj.core.event.EventSystem 3 | import kt.scaffold.tools.logger.Logger 4 | import org.junit.After 5 | import org.junit.Before 6 | import org.junit.Test 7 | import kotlin.system.measureTimeMillis 8 | 9 | class EventSystemTest { 10 | 11 | @Before 12 | fun setUp(){ 13 | 14 | var time = measureTimeMillis { 15 | //Your code... 16 | } 17 | } 18 | 19 | @After 20 | fun tearDown(){ 21 | 22 | } 23 | 24 | @Test 25 | fun testCombatContext(){ 26 | 27 | EventSystem.initialize("com.lj.battle.event.handler") 28 | var time = measureTimeMillis { 29 | EventSystem.run(EventIdType.changeAttribute,"10001") 30 | EventSystem.run(EventIdType.changeAttribute,"10001") 31 | } 32 | Logger.debug(time.toString()) 33 | 34 | } 35 | } -------------------------------------------------------------------------------- /apps/app-battle/src/test/kotlin/FloatNumbericTest.kt: -------------------------------------------------------------------------------- 1 | import com.lj.core.gamePlay.combat.attribute.FloatModifier 2 | import com.lj.core.gamePlay.combat.attribute.FloatNumberic 3 | import org.junit.After 4 | import org.junit.Before 5 | import org.junit.Test 6 | import kotlin.test.assertEquals 7 | import kotlin.test.assertTrue 8 | 9 | class FloatNumbericTest { 10 | 11 | lateinit var floatNumber: FloatNumberic 12 | 13 | @Before 14 | fun setUp(){ 15 | 16 | floatNumber = FloatNumberic() 17 | floatNumber.initialize() 18 | } 19 | 20 | @After 21 | fun tearDown(){ 22 | 23 | } 24 | 25 | @Test 26 | fun testSetBase(){ 27 | val baseV = floatNumber.setBase(10f) 28 | assertTrue("testSetBase") { 29 | baseV == 10f 30 | } 31 | } 32 | 33 | @Test 34 | fun testAdd(){ 35 | // 10 + 10 36 | floatNumber.setBase(10f) 37 | val modifier = FloatModifier(10f) 38 | 39 | floatNumber.addAddModifier(modifier) 40 | assertEquals(20f, floatNumber.value, "add") 41 | 42 | floatNumber.removeAddModifier(modifier) 43 | assertEquals(10f, floatNumber.value, "add") 44 | } 45 | 46 | @Test 47 | fun testAddPct(){ 48 | //(10 + 10) * (100+10)/100 49 | floatNumber.setBase(10f) 50 | val addModifier = FloatModifier(10f) 51 | val pctModifier = FloatModifier(10f) 52 | floatNumber.addAddModifier(addModifier) 53 | floatNumber.addPctAddModifier(pctModifier) 54 | 55 | assertEquals(22f,floatNumber.value,"addpct") 56 | 57 | floatNumber.removeAddModifier(addModifier) 58 | floatNumber.removePctAddModifier(pctModifier) 59 | 60 | assertEquals(10f,floatNumber.value,"addpct") 61 | 62 | } 63 | 64 | @Test 65 | fun testAddFinal(){ 66 | //( ( (10 + 10) * (100 +10)/100) + 10 ) * (100 + 10)/100 67 | floatNumber.setBase(10f) 68 | val addModifier = FloatModifier(10f) 69 | val pctModifier = FloatModifier(10f) 70 | val addFinalModifier = FloatModifier(10f) 71 | val addFinalPctModifier = FloatModifier(10f) 72 | 73 | floatNumber.addAddModifier(addModifier) 74 | floatNumber.addPctAddModifier(pctModifier) 75 | floatNumber.addFinalAddModifier(addFinalModifier) 76 | floatNumber.addFinalPctAddModifier(addFinalPctModifier) 77 | 78 | assertEquals(35.2f, floatNumber.value, "addfinal") 79 | 80 | floatNumber.removeAddModifier(addModifier) 81 | floatNumber.removePctAddModifier(pctModifier) 82 | floatNumber.removeFinalAddModifier(addFinalModifier) 83 | floatNumber.removeFinalPctAddModifier(addFinalPctModifier) 84 | 85 | assertEquals(10f,floatNumber.value,"addfinal") 86 | } 87 | } -------------------------------------------------------------------------------- /apps/app-battle/src/test/kotlin/HealthPointTest.kt: -------------------------------------------------------------------------------- 1 | import com.lj.core.gamePlay.combat.attribute.HealthPoint 2 | import org.junit.After 3 | import org.junit.Before 4 | import org.junit.Test 5 | import kotlin.test.assertEquals 6 | 7 | class HealthPointTest { 8 | 9 | @Before 10 | fun setUp(){ 11 | 12 | } 13 | 14 | @After 15 | fun tearDown(){ 16 | 17 | } 18 | 19 | @Test 20 | fun testHealPoint(){ 21 | val point = HealthPoint(0, 10) 22 | point.maxValue = 20 23 | 24 | point.add(10) 25 | point.minus(5) 26 | 27 | assertEquals(5, point.value) 28 | 29 | } 30 | 31 | 32 | } -------------------------------------------------------------------------------- /apps/app-gameserver/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | import org.jetbrains.kotlin.kapt3.base.Kapt.kapt 3 | 4 | plugins { 5 | java 6 | idea 7 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 8 | kotlin("jvm") 9 | 10 | application 11 | } 12 | 13 | dependencies { 14 | implementation(kotlin("reflect")) 15 | 16 | //api(files("conf")) 17 | api(project(":apps:lib-core")) 18 | 19 | 20 | // Use the Kotlin test library. 21 | testImplementation("org.jetbrains.kotlin:kotlin-test") 22 | // Use the Kotlin JUnit integration. 23 | testImplementation("org.jetbrains.kotlin:kotlin-test-junit") 24 | 25 | 26 | configurations.all { 27 | this.exclude(group = "org.slf4j", module = "slf4j-log4j12") 28 | } 29 | 30 | } 31 | 32 | application { 33 | // Define the main class for the application. 34 | mainClass.set("com.lj.AppGameServer") 35 | 36 | // 可以在此添加jvm内存参数, eg: '-Xms512m', '-Xmx4096m' 37 | applicationDefaultJvmArgs = listOf("-Duser.timezone=GMT+8", "-Dfile.encoding=UTF-8", "-Dsun.jnu.encoding=UTF-8") 38 | } 39 | 40 | // clean 时删除生成的文件 41 | tasks.withType { 42 | doFirst { 43 | delete(File("$projectDir/src/main/generated")) 44 | } 45 | } 46 | 47 | tasks.withType { 48 | options.encoding = "UTF-8" 49 | } 50 | 51 | val compileKotlin: KotlinCompile by tasks 52 | compileKotlin.kotlinOptions { 53 | jvmTarget = "1.8" 54 | } 55 | val compileTestKotlin: KotlinCompile by tasks 56 | compileTestKotlin.kotlinOptions { 57 | jvmTarget = "1.8" 58 | } 59 | 60 | val distZip: Zip by tasks 61 | distZip.into(project.name) { 62 | from("./src/main/resources") 63 | include("conf/**") 64 | } 65 | 66 | val distTar: Tar by tasks 67 | distTar.enabled = false 68 | 69 | val installDist: Sync by tasks 70 | installDist.into("conf") { 71 | from("./src/main/resources/conf") 72 | include("*") 73 | } 74 | installDist.into("fb") { 75 | from("./src/main/resources/fb") 76 | include("**") 77 | } 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /apps/app-gameserver/src/main/kotlin/com/lj/AppGameServer.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import com.lj.core.common.IdGenerater 4 | import com.lj.core.net.msg.MsgMessageCodec 5 | import com.lj.core.service.Msg 6 | import fb.FBManager 7 | import com.lj.core.service.handler.ServiceDispatcher 8 | import kt.scaffold.Application 9 | 10 | suspend fun main() { 11 | 12 | //Service消息处理 13 | ServiceDispatcher.initialize("com.lj.msg") 14 | 15 | //加载静态表数据 16 | FBManager.initialize() 17 | 18 | //初始化Vertx 19 | Application.setupVertx() 20 | 21 | //初始化UUID 22 | IdGenerater.initUUID("niceMongo") 23 | 24 | //启动Game Server 25 | Application.deployVerticle(GameServerServiceVerticle::class.java.name,"GameServerVerticle") 26 | 27 | //注册eventbus编码器 28 | val eventBus = Application.vertx.eventBus() 29 | eventBus.registerDefaultCodec(Msg::class.java, MsgMessageCodec()) 30 | 31 | } -------------------------------------------------------------------------------- /apps/app-gameserver/src/main/kotlin/com/lj/GameServerServiceVerticle.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import com.lj.core.consts.EventBusAddress 4 | import com.lj.core.ecs.DBEntityManager 5 | import com.lj.core.ecs.component.AccountComponent 6 | import com.lj.core.ecs.component.BagComponent 7 | import com.lj.core.ecs.entity.PlayerEntity 8 | import com.lj.core.service.GameService 9 | import com.lj.core.service.impl.GameServiceImpl 10 | import io.vertx.serviceproxy.ServiceBinder 11 | import kt.scaffold.Application 12 | import kt.scaffold.common.MicroServiceVerticle 13 | import kt.scaffold.net.DiscoveryManager 14 | import kt.scaffold.tools.logger.Logger 15 | 16 | class GameServerServiceVerticle : MicroServiceVerticle() { 17 | override suspend fun start() { 18 | super.start() 19 | 20 | val serverID = Application.config.getString("app.Verticles.GameServerVerticle.serverID") 21 | val serverType = Application.config.getInt("app.Verticles.GameServerVerticle.serverType") 22 | val binder = ServiceBinder(vertx) 23 | //==================此处注册并发布服务 24 | binder.setAddress(EventBusAddress.SERVICE_GAMESERVER_ADDRESS).register(GameService::class.java, 25 | GameServiceImpl() 26 | ) 27 | DiscoveryManager.publishEventBusServiceAwait( 28 | EventBusAddress.SERVICE_GAMESERVER_NAME, 29 | EventBusAddress.SERVICE_GAMESERVER_ADDRESS, 30 | GameService::class.java, 31 | serverID.toInt(), 32 | serverType.toInt() 33 | ) 34 | 35 | } 36 | } -------------------------------------------------------------------------------- /apps/app-gameserver/src/main/kotlin/com/lj/msg/BenchmarkHandler.kt: -------------------------------------------------------------------------------- 1 | package com.lj.msg 2 | 3 | import com.lj.core.common.ServiceHandlerAnnotation 4 | import com.lj.core.consts.EventBusAddress 5 | import com.lj.core.net.Opcode 6 | import com.lj.core.net.SocketManager 7 | import com.lj.core.service.Msg 8 | import com.lj.core.service.handler.BaseHandler 9 | import com.lj.proto.Benchmark 10 | import io.vertx.core.AsyncResult 11 | import io.vertx.core.Future 12 | import io.vertx.core.Handler 13 | import kt.crypto.decodeBase64 14 | import kt.crypto.encodeBase64 15 | import kt.scaffold.tools.logger.Logger 16 | 17 | @ServiceHandlerAnnotation(opcode = Opcode.MSG_C2GS_Test) 18 | class BenchmarkHandler: BaseHandler() { 19 | override fun process(msg: Msg,handler: Handler>) { 20 | //收到的消息 21 | val c2gs = Benchmark.C2GS_Test.parseFrom(msg.base64Msg.decodeBase64()) 22 | Logger.debug("benchark recv: ${c2gs.testID} - ${c2gs.testName} - ${msg.seq}") 23 | 24 | 25 | //发出的消息 26 | val builder = Benchmark.GS2C_Test.newBuilder() 27 | builder.setError(0) 28 | builder.setMessage("success") 29 | builder.setTestResponse("I am back...") 30 | 31 | val gs2c = builder.build().toByteArray().encodeBase64() 32 | msg.base64Msg = gs2c 33 | msg.msgId = Opcode.MSG_GS2C_Test 34 | 35 | msg.userId = 991 36 | 37 | //推送消息 38 | SocketManager.sendMsg2Gateway(EventBusAddress.PUSH2CLIENT_ADDRESS,msg) 39 | 40 | 41 | 42 | handler.handle(Future.succeededFuture(msg)) 43 | } 44 | } -------------------------------------------------------------------------------- /apps/app-gameserver/src/main/resources/conf/application.conf: -------------------------------------------------------------------------------- 1 | 2 | app { 3 | Verticles{ 4 | GameServerVerticle{ 5 | workerMode = true 6 | instance = 5 7 | serverID = 10 8 | serverType = 1 9 | } 10 | } 11 | } 12 | 13 | 14 | mongo{ 15 | niceMongo{ 16 | // Single Cluster Settings 17 | "host" : "60.1.1.22", // string 18 | "port" : 27017, // int 19 | "db_name":"kt", 20 | 21 | // Connection Pool Settings 22 | "maxPoolSize" : 50, // int 23 | "minPoolSize" : 25, // int 24 | "maxIdleTimeMS" : 300000, // long 25 | "maxLifeTimeMS" : 3600000, // long 26 | "waitQueueTimeoutMS" : 10000, // long 27 | "maintenanceFrequencyMS" : 2000, // long 28 | "maintenanceInitialDelayMS" : 500, // long 29 | 30 | // Credentials / Auth 31 | "username" : "zhj", // string 32 | "password" : "zhj666", // string 33 | "authSource" : "admin" // string 34 | 35 | // Auth mechanism 36 | "authMechanism" : "SCRAM-SHA-1", // string 37 | 38 | 39 | // Socket Settings 40 | "connectTimeoutMS" : 300000, // int 41 | "socketTimeoutMS" : 100000, // int 42 | "sendBufferSize" : 8192, // int 43 | "receiveBufferSize" : 8192, // int 44 | } 45 | } 46 | 47 | redis { 48 | // 配置项的 key 为 redis 配置名称 49 | // redis 配置名称不能重复 50 | niceRedis { 51 | options { 52 | // endpoint 格式说明: redis://[:password@]host[:port][/db-number] 53 | endpoints = ["redis://zhj666@60.1.1.22:6379/15"] 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /apps/app-gameserver/src/main/resources/conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | logs/application.log 9 | 10 | %date{HH:mm:ss.SSS} [%level] from [%logger] in [%thread] - %coloredMsg{com.api}%n%xException 11 | 12 | 13 | 14 | 15 | 16 | %date{HH:mm:ss.SSS} [%coloredLevel] [%logger] in [%thread] - %coloredMsg{com.api}%n%xException{10} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /apps/app-gameserver/src/main/resources/fb/heroconfig.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin-sky/Nice-KT/114d3561067181aa544ad719652dad3e6570d067/apps/app-gameserver/src/main/resources/fb/heroconfig.bin -------------------------------------------------------------------------------- /apps/app-gameserver/src/main/resources/fb/skillconfig.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin-sky/Nice-KT/114d3561067181aa544ad719652dad3e6570d067/apps/app-gameserver/src/main/resources/fb/skillconfig.bin -------------------------------------------------------------------------------- /apps/app-gameserver/src/main/resources/fb/unitconfig.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin-sky/Nice-KT/114d3561067181aa544ad719652dad3e6570d067/apps/app-gameserver/src/main/resources/fb/unitconfig.bin -------------------------------------------------------------------------------- /apps/app-gateway/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 5 | kotlin("jvm") 6 | 7 | // Apply the application plugin to add support for building a CLI application. 8 | application 9 | } 10 | 11 | 12 | repositories { 13 | // Use jcenter for resolving your dependencies. 14 | // You can declare any Maven/Ivy/file repository here. 15 | mavenLocal() 16 | mavenCentral() 17 | jcenter() 18 | } 19 | 20 | dependencies { 21 | implementation(kotlin("reflect")) 22 | 23 | //api(files("conf")) 24 | api(project(":apps:app-gameserver")) 25 | 26 | // Use the Kotlin test library. 27 | testImplementation("org.jetbrains.kotlin:kotlin-test") 28 | // Use the Kotlin JUnit integration. 29 | testImplementation("org.jetbrains.kotlin:kotlin-test-junit") 30 | 31 | 32 | configurations.all { 33 | this.exclude(group = "org.slf4j", module = "slf4j-log4j12") 34 | } 35 | 36 | } 37 | 38 | 39 | application { 40 | // Define the main class for the application. 41 | mainClass.set("com.lj.AppGateway") 42 | 43 | // 可以在此添加jvm内存参数, eg: '-Xms512m', '-Xmx4096m' 44 | applicationDefaultJvmArgs = listOf("-Duser.timezone=GMT+8", "-Dfile.encoding=UTF-8", "-Dsun.jnu.encoding=UTF-8") 45 | } 46 | 47 | tasks.withType { 48 | options.encoding = "UTF-8" 49 | } 50 | 51 | val compileKotlin: KotlinCompile by tasks 52 | compileKotlin.kotlinOptions { 53 | jvmTarget = "1.8" 54 | } 55 | val compileTestKotlin: KotlinCompile by tasks 56 | compileTestKotlin.kotlinOptions { 57 | jvmTarget = "1.8" 58 | } 59 | 60 | val distZip: Zip by tasks 61 | distZip.into(project.name) { 62 | from("./src/main/resources") 63 | include("conf/**") 64 | } 65 | 66 | val distTar: Tar by tasks 67 | distTar.enabled = false 68 | 69 | val installDist: Sync by tasks 70 | installDist.into("conf") { 71 | from("./src/main/resources/conf") 72 | include("*") 73 | } 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /apps/app-gateway/src/main/kotlin/com/lj/AppGateway.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import com.lj.core.consts.EventBusAddress 4 | import com.lj.core.net.SocketManager 5 | import com.lj.core.net.msg.MsgMessageCodec 6 | import com.lj.core.service.Msg 7 | import kt.scaffold.Application 8 | 9 | suspend fun main(args:Array){ 10 | 11 | //初始化Vertx 12 | Application.setupVertx() 13 | 14 | //启动Gateway Server 15 | Application.deployVerticle(GatewayVerticle::class.java.name,"GatewayVerticle") 16 | 17 | //设置回调 18 | Application.setupOnStartAndOnStop() 19 | 20 | //心跳检查 21 | Application.vertx.setPeriodic(1000*30){ 22 | SocketManager.checkTimeout(1000*60) 23 | } 24 | 25 | //网关服监听推送消息 26 | val eventBus = Application.vertx.eventBus().apply { 27 | registerDefaultCodec(Msg::class.java, MsgMessageCodec()) 28 | } 29 | 30 | val consumer = eventBus.consumer(EventBusAddress.PUSH2CLIENT_ADDRESS) 31 | consumer.handler { message -> 32 | val msg = message.body() 33 | SocketManager.pushMsg2Client(msg.userId, msg) 34 | } 35 | 36 | 37 | } -------------------------------------------------------------------------------- /apps/app-gateway/src/main/kotlin/com/lj/GatewayVerticle.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import com.lj.core.net.SocketManager 4 | import kt.scaffold.Application 5 | import kt.scaffold.common.MicroServiceVerticle 6 | import kt.scaffold.tools.logger.Logger 7 | 8 | 9 | class GatewayVerticle :MicroServiceVerticle(){ 10 | 11 | override suspend fun start() { 12 | super.start() 13 | 14 | val tcpServerOptions = Application.tcpServerOptions() 15 | val tcpServer = this.vertx.createNetServer(tcpServerOptions) 16 | 17 | tcpServer.connectHandler(){ socket -> 18 | Logger.debug("Connect ... ${socket.remoteAddress()} ") 19 | 20 | val socketId = socket.writeHandlerID() 21 | Logger.debug("Socket ID: $socketId") 22 | 23 | //保存Socket 24 | SocketManager.activeSocket(socketId, socket) 25 | 26 | //网关消息处理 27 | socket.handler(SocketManager.socketHandler(socketId, true)) 28 | 29 | socket.closeHandler(){ 30 | Logger.debug("socket close: $socketId") 31 | 32 | SocketManager.inactiveSocket(socketId) 33 | SocketManager.unbindUserid2Socket(socketId) 34 | } 35 | } 36 | 37 | tcpServer.exceptionHandler(){ 38 | Logger.debug("exception ${it.message}") 39 | } 40 | 41 | val host = Application.config.getString("app.tcpServer.host") 42 | val port = Application.config.getInt("app.tcpServer.port") 43 | tcpServer.listen(port,host) 44 | Logger.info("GateWay Server listen: $host: $port") 45 | 46 | } 47 | } -------------------------------------------------------------------------------- /apps/app-gateway/src/main/resources/conf/application.conf: -------------------------------------------------------------------------------- 1 | 2 | app { 3 | tcpServer { 4 | port = 9000 5 | host = "0.0.0.0" 6 | productionMode = true 7 | } 8 | 9 | Verticles{ 10 | GatewayVerticle{ 11 | workerMode = false 12 | instance = 5 13 | } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /apps/app-gateway/src/main/resources/conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | logs/application.log 9 | 10 | %date{HH:mm:ss.SSS} [%level] from [%logger] in [%thread] - %coloredMsg{com.api}%n%xException 11 | 12 | 13 | 14 | 15 | 16 | %date{HH:mm:ss.SSS} [%coloredLevel] [%logger] in [%thread] - %coloredMsg{com.api}%n%xException{10} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /apps/app-login/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 5 | kotlin("jvm") 6 | 7 | // Apply the application plugin to add support for building a CLI application. 8 | application 9 | } 10 | 11 | 12 | repositories { 13 | // Use jcenter for resolving your dependencies. 14 | // You can declare any Maven/Ivy/file repository here. 15 | mavenLocal() 16 | mavenCentral() 17 | jcenter() 18 | } 19 | 20 | dependencies { 21 | implementation(kotlin("reflect")) 22 | 23 | //api(files("conf")) 24 | api(project(":apps:lib-core")) 25 | 26 | 27 | // Use the Kotlin test library. 28 | testImplementation("org.jetbrains.kotlin:kotlin-test") 29 | // Use the Kotlin JUnit integration. 30 | testImplementation("org.jetbrains.kotlin:kotlin-test-junit") 31 | 32 | 33 | configurations.all { 34 | this.exclude(group = "org.slf4j", module = "slf4j-log4j12") 35 | } 36 | 37 | } 38 | 39 | application { 40 | // Define the main class for the application. 41 | mainClass.set("com.lj.AppLogin") 42 | 43 | // 可以在此添加jvm内存参数, eg: '-Xms512m', '-Xmx4096m' 44 | applicationDefaultJvmArgs = listOf("-Duser.timezone=GMT+8", "-Dfile.encoding=UTF-8", "-Dsun.jnu.encoding=UTF-8") 45 | } 46 | 47 | tasks.withType { 48 | options.encoding = "UTF-8" 49 | } 50 | 51 | val compileKotlin: KotlinCompile by tasks 52 | compileKotlin.kotlinOptions { 53 | jvmTarget = "1.8" 54 | } 55 | val compileTestKotlin: KotlinCompile by tasks 56 | compileTestKotlin.kotlinOptions { 57 | jvmTarget = "1.8" 58 | } 59 | 60 | val distZip: Zip by tasks 61 | distZip.into(project.name) { 62 | from("./src/main/resources") 63 | include("conf/**") 64 | } 65 | 66 | val distTar: Tar by tasks 67 | distTar.enabled = false 68 | 69 | val installDist: Sync by tasks 70 | installDist.into("conf") { 71 | from("./src/main/resources/conf") 72 | include("*") 73 | } 74 | 75 | 76 | -------------------------------------------------------------------------------- /apps/app-login/src/main/kotlin/com/lj/AppLogin.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import com.lj.core.net.SocketManager 4 | import com.lj.core.net.msg.MessageDispatcher 5 | import kt.scaffold.Application 6 | 7 | suspend fun main() { 8 | 9 | //注册消息处理器 10 | MessageDispatcher.initialize("com.lj.msg") 11 | 12 | //初始化Vertx 13 | Application.setupVertx() 14 | 15 | //启动Login Server 16 | Application.deployVerticle(LoginVerticle::class.java.name,"LoginVerticle") 17 | 18 | //设置回调 19 | Application.setupOnStartAndOnStop() 20 | 21 | //心跳检查 22 | Application.vertx.setPeriodic(1000*30){ 23 | SocketManager.checkTimeout(1000*60) 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /apps/app-login/src/main/kotlin/com/lj/LoginVerticle.kt: -------------------------------------------------------------------------------- 1 | package com.lj 2 | 3 | import com.lj.core.net.SocketManager 4 | import com.lj.core.net.msg.MessageDispatcher 5 | import kt.scaffold.Application 6 | import kt.scaffold.common.MicroServiceVerticle 7 | import kt.scaffold.tools.logger.Logger 8 | 9 | class LoginVerticle:MicroServiceVerticle(){ 10 | 11 | override suspend fun start() { 12 | super.start() 13 | 14 | val tcpServerOptions = Application.tcpServerOptions() 15 | val tcpServer = this.vertx.createNetServer(tcpServerOptions) 16 | 17 | tcpServer.connectHandler(){ socket -> 18 | Logger.debug("Connect , ${socket.writeHandlerID()}... ${socket.remoteAddress()} ") 19 | val socketId = socket.writeHandlerID() 20 | Logger.debug("Socket ID: $socketId") 21 | 22 | //保存Socket 23 | SocketManager.activeSocket(socketId, socket) 24 | 25 | socket.handler(SocketManager.socketHandler(socketId)) 26 | 27 | socket.closeHandler(){ 28 | Logger.debug("socket close: $socketId") 29 | SocketManager.inactiveSocket(socketId) 30 | SocketManager.unbindUserid2Socket(socketId) 31 | } 32 | } 33 | 34 | tcpServer.exceptionHandler(){ 35 | Logger.debug("exception ${it.message}") 36 | } 37 | 38 | val host = Application.config.getString("app.loginServer.host") 39 | val port = Application.config.getInt("app.loginServer.port") 40 | tcpServer.listen(port,host) 41 | Logger.info("Login Server listen: $host: $port") 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /apps/app-login/src/main/kotlin/com/lj/msg/LoginHandler.kt: -------------------------------------------------------------------------------- 1 | package com.lj.msg 2 | 3 | import com.lj.core.common.HandlerAnnotation 4 | import com.lj.core.net.SocketManager 5 | import com.lj.core.net.msg.BaseHandler 6 | import com.lj.core.service.Msg 7 | import com.lj.core.net.Opcode 8 | import com.lj.proto.Login 9 | import kotlinx.coroutines.GlobalScope 10 | import kotlinx.coroutines.launch 11 | import kt.crypto.decodeBase64 12 | import kt.scaffold.tools.logger.Logger 13 | 14 | @HandlerAnnotation(opcode = Opcode.MSG_C2R_Login) 15 | class LoginHandler: BaseHandler() { 16 | 17 | override fun process(socketId:String, msg: Msg) { 18 | 19 | GlobalScope.launch { 20 | //解析消息 21 | var rev = msg.base64Msg.decodeBase64() 22 | var c2r = Login.C2R_Login.parseFrom(rev) 23 | Logger.debug("account: ${c2r.account}, passwd: ${c2r.password}") 24 | 25 | //返回消息 26 | var builder = Login.R2C_Login.newBuilder() 27 | builder.address = "127.0.0.1:9000" 28 | builder.key = 123456 29 | builder.gateId = 100 30 | 31 | var buf = builder.build().toByteArray() 32 | 33 | SocketManager.sendMsg( 34 | socketId, 35 | msg.seq, 36 | Opcode.MSG_R2C_Login, 37 | msg.serverId, 38 | msg.serverType, 39 | buf) 40 | 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /apps/app-login/src/main/resources/conf/application.conf: -------------------------------------------------------------------------------- 1 | 2 | app { 3 | tcpServer { 4 | port = 9000 5 | host = "0.0.0.0" 6 | productionMode = true 7 | } 8 | loginServer { 9 | port = 9001 10 | host = "0.0.0.0" 11 | } 12 | 13 | Verticles{ 14 | LoginVerticle{ 15 | workerMode = false 16 | instance = 1 17 | } 18 | } 19 | 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /apps/app-login/src/main/resources/conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | logs/application.log 9 | 10 | %date{HH:mm:ss.SSS} [%level] from [%logger] in [%thread] - %coloredMsg{com.api}%n%xException 11 | 12 | 13 | 14 | 15 | 16 | %date{HH:mm:ss.SSS} [%coloredLevel] [%logger] in [%thread] - %coloredMsg{com.api}%n%xException{10} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /apps/lib-core/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.google.protobuf.gradle.* 2 | import org.jetbrains.kotlin.kapt3.base.Kapt.kapt 3 | 4 | plugins { 5 | java 6 | idea 7 | id("com.google.protobuf") version "0.8.8" 8 | kotlin("jvm") 9 | kotlin("kapt") 10 | } 11 | 12 | repositories { 13 | maven("https://plugins.gradle.org/m2/") 14 | } 15 | 16 | val protobufVersion = "3.11.3" 17 | val vertxVersion = "4.0.0" 18 | 19 | dependencies { 20 | 21 | 22 | api(project(":subProjects:nice-scaffold")) 23 | api("io.vertx:vertx-codegen:$vertxVersion") 24 | api("io.vertx:vertx-lang-kotlin-gen:$vertxVersion") 25 | api("io.vertx:vertx-service-proxy:$vertxVersion") 26 | 27 | api("com.google.protobuf:protobuf-java:$protobufVersion") 28 | api("com.google.flatbuffers:flatbuffers-java:1.12.0") 29 | 30 | api("org.jetbrains.kotlin:kotlin-reflect:1.4.20") 31 | // android gradle依赖:implementation 和compile的区别 32 | // 参考: https://www.jianshu.com/p/f34c179bc9d0 根据需要选择使用不同的依赖设定方式 33 | 34 | kapt("io.vertx:vertx-codegen:$vertxVersion:processor") 35 | compileOnly("io.vertx:vertx-codegen:$vertxVersion") 36 | 37 | 38 | configurations.all { 39 | this.exclude(group = "org.slf4j", module = "slf4j-log4j12") 40 | } 41 | 42 | api("com.google.protobuf:protobuf-gradle-plugin:0.8.14") 43 | } 44 | 45 | //中文乱码 46 | tasks.withType { 47 | options.encoding = "UTF-8" 48 | } 49 | 50 | tasks.register("sourcesJar") { 51 | from(sourceSets.main.get().allSource) 52 | archiveClassifier.set("sources") 53 | } 54 | 55 | val compileKotlin: org.jetbrains.kotlin.gradle.tasks.KotlinCompile by tasks 56 | compileKotlin.kotlinOptions { 57 | jvmTarget = "1.8" 58 | } 59 | 60 | val compileTestKotlin: org.jetbrains.kotlin.gradle.tasks.KotlinCompile by tasks 61 | compileTestKotlin.kotlinOptions { 62 | jvmTarget = "1.8" 63 | } 64 | 65 | 66 | protobuf{ 67 | protoc { 68 | // The artifact spec for the Protobuf Compiler 69 | artifact = "com.google.protobuf:protoc:3.6.1" 70 | } 71 | } 72 | 73 | sourceSets{ 74 | main{ 75 | java.srcDirs("${buildDir.absolutePath}/generated/source/proto/main/java") 76 | println("${buildDir.absolutePath}/generated/source/proto/main") 77 | } 78 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/java/com/lj/core/service/package-info.java: -------------------------------------------------------------------------------- 1 | @ModuleGen(name = "server-service", groupPackage = "com.lj.core.service") 2 | package com.lj.core.service; 3 | 4 | import io.vertx.codegen.annotations.ModuleGen; -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/common/CmdExecutor.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.common 2 | 3 | import java.lang.reflect.Method 4 | 5 | class CmdExecutor(val method: Method, val handler:Any) -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/common/HandlerAnnotation.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.common 2 | @Target(AnnotationTarget.CLASS) 3 | @Retention(AnnotationRetention.RUNTIME) 4 | annotation class HandlerAnnotation(val opcode:Short) -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/common/IdGenerater.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.common 2 | 3 | import io.vertx.core.json.JsonObject 4 | import io.vertx.ext.mongo.MongoClient 5 | import io.vertx.kotlin.ext.mongo.findOneAndUpdateAwait 6 | import kt.scaffold.mongo.MongoManager 7 | import kt.scaffold.tools.logger.Logger 8 | 9 | object IdGenerater { 10 | lateinit var mongo: MongoClient 11 | 12 | fun initUUID(mongoName:String){ 13 | mongo = MongoManager.mongoOf(mongoName) 14 | 15 | val q = JsonObject().put("type","uid") 16 | mongo.find("UUID",q){res-> 17 | if (res.succeeded()){ 18 | if (res.result().isNullOrEmpty()){ 19 | val uuid = JsonObject() 20 | uuid.put("type", "uid") 21 | uuid.put("_id", 1) 22 | mongo.createIndex("UUID",JsonObject().put("type",1)){ 23 | 24 | } 25 | mongo.save("UUID", uuid){res-> 26 | if (res.succeeded()){ 27 | Logger.debug("init uuid success") 28 | }else{ 29 | Logger.debug("init uuid failed") 30 | } 31 | } 32 | } 33 | 34 | } 35 | } 36 | } 37 | 38 | 39 | suspend fun generatedUidAwait():Long?{ 40 | val q = JsonObject().put("type","uid") 41 | 42 | val m = JsonObject() 43 | m.put("\$inc",JsonObject().put("uid",1)) 44 | 45 | val res = mongo.findOneAndUpdateAwait("UUID",q, m) 46 | 47 | return res?.getLong("_id") 48 | } 49 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/common/ServiceHandlerAnnotation.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.common 2 | 3 | @Target(AnnotationTarget.CLASS) 4 | @Retention(AnnotationRetention.RUNTIME) 5 | annotation class ServiceHandlerAnnotation(val opcode:Short) -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/consts/EventBusAddress.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.consts 2 | 3 | class EventBusAddress { 4 | companion object{ 5 | val SERVICE_GAMESERVER_ADDRESS = "com.lj.service.gameserver" 6 | val SERVICE_BATTLESERVER_ADDRESS = "com.lj.service.battleserver" 7 | val SERVICE_GAMESERVER_NAME = "game-service" 8 | val SERVICE_BATTLESERVER_NAME = "battle-service" 9 | val PUSH2CLIENT_ADDRESS = "com.lj.service.push2client" 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/consts/GlobalConst.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.consts 2 | 3 | object GlobalConst { 4 | var GAMESERVER_MONGO = "niceMongo" 5 | var GAMESERVER_REDIS = "niceRedis" 6 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/ecs/EntityFactory.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.ecs 2 | 3 | object EntityFactory { 4 | 5 | 6 | inline fun create(id:Long):T where T:Entity{ 7 | 8 | val clz = T::class.java 9 | var mCreate = clz.getDeclaredConstructor() 10 | mCreate.isAccessible = true 11 | 12 | val c = mCreate.newInstance() 13 | c._id = id 14 | 15 | return c 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/ecs/EventComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.ecs 2 | 3 | import kotlin.reflect.KClass 4 | 5 | 6 | class EventSubscribeCollection{ 7 | val subscribes = mutableListOf>() 8 | private val action2Subscribes = mutableMapOf<(t:T)->Unit, EventSubscribe>() 9 | 10 | fun add(action: (t:T) -> Unit): EventSubscribe{ 11 | val eventSubscribe = EventSubscribe() 12 | eventSubscribe.eventAction = action 13 | 14 | subscribes.add(eventSubscribe) 15 | action2Subscribes[action] = eventSubscribe 16 | 17 | return eventSubscribe 18 | } 19 | 20 | fun remove(action: (t:T) -> Unit){ 21 | subscribes.remove(action2Subscribes[action]) 22 | action2Subscribes.remove(action) 23 | } 24 | } 25 | 26 | class EventSubscribe{ 27 | lateinit var eventAction:(t:T)->Unit 28 | } 29 | 30 | class EventComponent :Component() { 31 | override var enable: Boolean = true 32 | val eventSubscribeCollections = mutableMapOf, Any>() 33 | 34 | inline fun publish(tEvent:T):T{ 35 | val collection = this.eventSubscribeCollections[T::class] 36 | val eventSubscribeCollection = collection as? EventSubscribeCollection 37 | if (eventSubscribeCollection != null){ 38 | if (eventSubscribeCollection.subscribes.size == 0) return tEvent 39 | 40 | eventSubscribeCollection.subscribes.forEach { item-> 41 | item.eventAction.invoke(tEvent) 42 | } 43 | } 44 | return tEvent 45 | } 46 | 47 | inline fun subscribe(noinline action:(t:T)->Unit): EventSubscribe { 48 | val collection = eventSubscribeCollections[T::class] 49 | var eventSubscribeCollection = collection as? EventSubscribeCollection 50 | if (eventSubscribeCollection == null) { 51 | eventSubscribeCollection = EventSubscribeCollection() 52 | eventSubscribeCollections[T::class] = eventSubscribeCollection 53 | } 54 | return eventSubscribeCollection.add(action) 55 | } 56 | 57 | inline fun > unSubscribe(noinline action:(t:T)->Unit){ 58 | val collection = eventSubscribeCollections[T::class] 59 | var eventSubscribeCollection = collection as? EventSubscribeCollection 60 | eventSubscribeCollection?.remove(action) 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/ecs/IdFactory.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.ecs 2 | 3 | object IdFactory { 4 | 5 | private var baseTicks:Long = 0 6 | 7 | fun newInstanceId():Long{ 8 | return ++baseTicks 9 | } 10 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/ecs/MasterEntity.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.ecs 2 | 3 | object MasterEntity :Entity(){ 4 | 5 | val entities = mutableMapOf>() 6 | 7 | val allComponents = mutableListOf() 8 | 9 | fun update(){ 10 | 11 | if (allComponents.size == 0 ) return 12 | 13 | for (i in allComponents.size-1 downTo 0){ 14 | val it = allComponents[i] 15 | if(it.isDisposed){ 16 | allComponents.remove(it) 17 | continue 18 | } 19 | 20 | if (it.disable) continue 21 | 22 | it.update() 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/ecs/component/AccountComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.ecs.component 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore 4 | import com.fasterxml.jackson.annotation.JsonTypeName 5 | import com.lj.core.ecs.Component 6 | 7 | @JsonTypeName("account") 8 | class AccountComponent : Component() { 9 | var name:String = "ab" 10 | var money:Int = 100 11 | 12 | fun changeName(name:String){ 13 | this.name = name 14 | this.addUpdateJson("components.AccountComponent.name",name) 15 | } 16 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/ecs/component/BagComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.ecs.component 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore 4 | import com.fasterxml.jackson.annotation.JsonTypeName 5 | import com.lj.core.ecs.Component 6 | import io.vertx.core.json.JsonObject 7 | 8 | data class Card( 9 | var _id:Long = 0, 10 | var name:String = "", 11 | var star:Int = 1, 12 | var level: Int = 1 13 | ) 14 | 15 | @JsonTypeName("bag") 16 | class BagComponent: Component() { 17 | 18 | var capacity:Int = 10 19 | val cardList:MutableList = mutableListOf() 20 | 21 | 22 | fun changeCapacity(capacity:Int) { 23 | this.capacity = capacity 24 | this.addUpdateJson("components.BagComponent.capacity",capacity) 25 | } 26 | 27 | fun addCard(card: Card){ 28 | this.cardList.add(card) 29 | this.addPushJson("components.BagComponent.cardList",JsonObject.mapFrom(card)) 30 | } 31 | 32 | fun removeCard(card: Card){ 33 | this.cardList.remove(card) 34 | this.addPullJson("components.BagComponent.cardList",JsonObject().put("_id",card._id)) 35 | } 36 | 37 | @JsonIgnore 38 | fun copyAllCards():List{ 39 | return this.cardList.toList() 40 | } 41 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/ecs/component/TeamComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.ecs.component 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | import com.lj.core.ecs.Component 5 | 6 | @JsonTypeName("team") 7 | class TeamComponent: Component() { 8 | var name:String = "team1" 9 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/ecs/entity/PlayerEntity.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.ecs.entity 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | import com.lj.core.ecs.Entity 5 | 6 | @JsonTypeName("player") 7 | class PlayerEntity: Entity() { 8 | 9 | 10 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/event/EventAnnotation.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.event 2 | 3 | @Target(AnnotationTarget.CLASS) 4 | @Retention(AnnotationRetention.RUNTIME) 5 | annotation class EventAnnotation(val eventID:String) -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/event/EventSystem.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.event 2 | 3 | import com.lj.core.common.CmdExecutor 4 | import com.lj.core.common.HandlerAnnotation 5 | import com.lj.core.net.msg.MessageDispatcher 6 | import com.lj.core.service.Msg 7 | import com.lj.core.utils.ClassScanner 8 | import kt.scaffold.tools.logger.Logger 9 | import java.lang.Exception 10 | import java.lang.RuntimeException 11 | 12 | object EventSystem { 13 | 14 | private val allEvents = mutableMapOf>() 15 | 16 | fun initialize(packageName:String){ 17 | val messageCommandClasses = ClassScanner.listClassesWithAnnotation(packageName, EventAnnotation::class.java) 18 | for(cls in messageCommandClasses){ 19 | try{ 20 | val handler = cls.getDeclaredConstructor().newInstance() 21 | val eventID = cls.getAnnotation(EventAnnotation::class.java).eventID 22 | 23 | this.registerEvent(eventID, handler as IEvent) 24 | 25 | }catch (e: Exception){ 26 | Logger.error("initialize error: ${e.cause}") 27 | } 28 | } 29 | } 30 | 31 | private fun registerEvent(eventID:String, e:IEvent){ 32 | if (!this.allEvents.containsKey(eventID)){ 33 | this.allEvents[eventID] = mutableListOf() 34 | } 35 | this.allEvents[eventID]!!.add(e) 36 | } 37 | 38 | fun run(eventID:String){ 39 | this.allEvents[eventID]?.forEach{e -> 40 | e.handle() 41 | } 42 | } 43 | 44 | fun run(eventID:String, a:A){ 45 | this.allEvents[eventID]?.forEach{ e -> 46 | e.handle(a!!) 47 | } 48 | } 49 | 50 | fun run(eventID:String, a:A, b:B){ 51 | this.allEvents[eventID]?.forEach{ e -> 52 | e.handle(a!!, b!!) 53 | } 54 | } 55 | 56 | fun run(eventID:String, a:A, b:B, c:C){ 57 | this.allEvents[eventID]?.forEach{ e -> 58 | e.handle(a!!, b!!, c!!) 59 | } 60 | } 61 | 62 | fun run(eventID:String, a:A, b:B, c:C, d:D){ 63 | this.allEvents[eventID]?.forEach{ e -> 64 | e.handle(a!!, b!!, c!!, d!!) 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/CombatActionManageComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat 2 | 3 | import com.lj.core.ecs.Component 4 | import com.lj.core.ecs.Entity 5 | import com.lj.core.gamePlay.combat.entity.action.CombatAction 6 | import com.lj.core.gamePlay.combat.entity.CombatEntity 7 | 8 | /** 9 | * 战斗行动管理组件 10 | */ 11 | class CombatActionManageComponent:Component() { 12 | 13 | val combatActions = mutableListOf() 14 | 15 | inline fun createAction(combatEntity: CombatEntity) :T where T:CombatAction{ 16 | val action = Entity.createWithParent(getEntityT()) 17 | action.creator = combatEntity 18 | 19 | combatActions.add(action) 20 | return action 21 | } 22 | 23 | 24 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/CombatContext.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat 2 | 3 | import com.lj.core.ecs.Entity 4 | 5 | /** 6 | * 战局上下文 7 | * 像回合制、moba这种战斗按局来分的,可以创建这个战局上下文,如果是mmo,那么战局上下文应该是在角色进入战斗才会创建,离开战斗就销毁 8 | */ 9 | class CombatContext : Entity() { 10 | 11 | override fun awake() { 12 | super.awake() 13 | 14 | addComponent() 15 | } 16 | 17 | 18 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/attribute/AttributeComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.attribute 2 | 3 | import com.lj.core.ecs.Component 4 | 5 | /** 6 | * 战斗属性数值组件,在这里管理所有角色战斗属性数值的存储、变更、刷新等 7 | */ 8 | class AttributeComponent: Component() { 9 | 10 | private val attributeNumerics = mutableMapOf() 11 | 12 | val moveSpeed:FloatNumberic 13 | get() { 14 | return attributeNumerics[AttributeType.MoveSpeed.name]!! 15 | } 16 | val causeDamage:FloatNumberic 17 | get() { 18 | return attributeNumerics[AttributeType.CauseDamage.name]!! 19 | } 20 | val healthPoint:FloatNumberic 21 | get() { 22 | return attributeNumerics[AttributeType.HealthPoint.name]!! 23 | } 24 | val attackPower:FloatNumberic 25 | get() { 26 | return attributeNumerics[AttributeType.AttackPower.name]!! 27 | } 28 | val attackDefense:FloatNumberic 29 | get() { 30 | return attributeNumerics[AttributeType.AttackDefense.name]!! 31 | } 32 | val criticalProbability:FloatNumberic 33 | get() { 34 | return attributeNumerics[AttributeType.CriticalProbability.name]!! 35 | } 36 | 37 | override fun setup(){ 38 | this.initialize() 39 | } 40 | 41 | private fun initialize(){ 42 | this.addNumeric(AttributeType.HealthPoint, 99_999f) 43 | this.addNumeric(AttributeType.MoveSpeed, 1f) 44 | this.addNumeric(AttributeType.CauseDamage, 1f) 45 | this.addNumeric(AttributeType.AttackPower, 1000f) 46 | this.addNumeric(AttributeType.AttackDefense, 300f) 47 | this.addNumeric(AttributeType.CriticalProbability, .5f) 48 | 49 | } 50 | 51 | fun addNumeric(attributeType: AttributeType, baseValue:Float): FloatNumberic { 52 | val numeric = FloatNumberic() 53 | numeric.baseValue = baseValue 54 | this.attributeNumerics[attributeType.name] = numeric 55 | return numeric 56 | } 57 | 58 | fun getNumeric(attributeName:String):FloatNumberic{ 59 | return attributeNumerics[attributeName]!! 60 | } 61 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/attribute/AttributeType.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.attribute 2 | 3 | enum class AttributeType(att: Int) { 4 | None(0), 5 | HealthPoint(1000), //生命值 6 | AttackPower(1001), //攻击力 7 | AttackDefense(1002), //护甲值 8 | SpellPower(1003), //法术强度 9 | MagicDefense(1004), //魔法抗性 10 | 11 | CriticalProbability(2001), //暴击概率 12 | MoveSpeed(2002), //移动速度 13 | AttackSpeed(2003), //攻击速度 14 | 15 | ShieldValue(3001), //护盾值 16 | 17 | CauseDamage(4001), //造成伤害 18 | 19 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/attribute/HealthPoint.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.attribute 2 | 3 | data class HealthPoint(var value:Int = 0, var maxValue:Int = 0) { 4 | 5 | fun reset(){ 6 | this.value = this.maxValue 7 | } 8 | 9 | fun minus(v:Int){ 10 | this.value = Math.max(0, this.value - v) 11 | } 12 | 13 | fun add(v:Int){ 14 | this.value = Math.min(this.maxValue, this.value+ v) 15 | } 16 | 17 | fun percent():Float{ 18 | return (this.value/this.maxValue).toFloat() 19 | } 20 | 21 | fun percentHealth(pct:Int):Int{ 22 | return (this.maxValue*pct/100) 23 | } 24 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/ability/AbilityEntity.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.ability 2 | 3 | import com.lj.core.ecs.Entity 4 | import com.lj.core.gamePlay.combat.entity.CombatEntity 5 | import com.lj.core.gamePlay.config.SkillConfigObject 6 | import com.lj.core.gamePlay.config.StatusConfigObject 7 | import com.lj.core.gamePlay.config.effect.Effect 8 | 9 | /** 10 | * 能力实体,存储着某个英雄某个能力的数据和状态 11 | */ 12 | abstract class AbilityEntity :Entity(){ 13 | 14 | val ownerEntity: CombatEntity 15 | get() { 16 | return this.parent as CombatEntity 17 | } 18 | 19 | lateinit var configObject:Any 20 | 21 | var level:Int = 1 22 | 23 | override fun awake(initData: Any) { 24 | this.configObject = initData 25 | } 26 | 27 | //尝试激活能力 28 | open fun tryActivateAbility(){ 29 | activateAbility() 30 | } 31 | 32 | //激活能力 33 | open fun activateAbility(){ 34 | 35 | } 36 | 37 | //结束能力 38 | open fun endAbility(){ 39 | destroy(this) 40 | } 41 | 42 | //创建能力执行体 43 | open fun createAbilityExecution():AbilityExecution?{ 44 | return null 45 | } 46 | 47 | //应用效果 48 | fun applyEffectTo(targetEntity:CombatEntity, effectItem:Effect){ 49 | 50 | } 51 | 52 | //应用能力效果 53 | open fun applyAbilityEffectsTo(targetEntity: CombatEntity){ 54 | 55 | var effects: List? = null 56 | 57 | if (configObject is SkillConfigObject){ 58 | effects = (configObject as SkillConfigObject).effects 59 | }else if (configObject is StatusConfigObject){ 60 | effects = (configObject as StatusConfigObject).effects 61 | } 62 | if (effects.isNullOrEmpty()) return 63 | 64 | for (effectItem in effects){ 65 | applyEffectTo(targetEntity, effectItem) 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/ability/AbilityExecution.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.ability 2 | 3 | import com.lj.core.ecs.Entity 4 | import com.lj.core.gamePlay.combat.entity.CombatEntity 5 | 6 | /** 7 | * 能力执行体,能力执行体是实际创建执行能力表现,触发应用能力效果的地方 8 | * 这里可以存一些表现执行相关的临时的状态数据 9 | */ 10 | abstract class AbilityExecution :Entity(){ 11 | 12 | lateinit var abilityEntity:AbilityEntity 13 | 14 | val owenEntity: CombatEntity 15 | get() { 16 | return (this.parent as CombatEntity) 17 | } 18 | 19 | override fun awake(initData:Any) { 20 | this.abilityEntity = initData as AbilityEntity 21 | } 22 | 23 | //开始执行 24 | open fun beginExecute(){} 25 | 26 | //结束执行 27 | open fun endExecute(){ 28 | destroy(this) 29 | } 30 | 31 | fun getAbility():T where T:AbilityEntity{ 32 | return this.abilityEntity as T 33 | } 34 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/ability/AbilityItem.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.ability 2 | 3 | /** 4 | * 能力单元体 5 | */ 6 | class AbilityItem:AbilityEntity() { 7 | 8 | lateinit var unitInitData:Any 9 | 10 | override fun awake(initData:Any) { 11 | this.unitInitData = initData 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/ability/skill/SkillAbility.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.ability.skill 2 | 3 | import com.lj.core.gamePlay.combat.entity.ability.AbilityEntity 4 | import com.lj.core.gamePlay.config.SkillConfigObject 5 | import com.lj.core.gamePlay.config.SkillSpellType 6 | import com.lj.core.gamePlay.combat.timer.GameTimer 7 | 8 | abstract class SkillAbility:AbilityEntity() { 9 | 10 | lateinit var skillConfigObject: SkillConfigObject 11 | var spelling:Boolean = false 12 | val cooldownTimer: GameTimer = 13 | GameTimer(1f) 14 | 15 | override fun awake(initData: Any) { 16 | super.awake(initData) 17 | 18 | skillConfigObject = initData as SkillConfigObject 19 | if (skillConfigObject.skillSpellType == SkillSpellType.Passive){ 20 | tryActivateAbility() 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/ability/skill/SkillAbilityExecution.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.ability.skill 2 | 3 | import com.badlogic.gdx.math.Vector3 4 | import com.lj.core.gamePlay.combat.entity.ability.AbilityExecution 5 | import com.lj.core.gamePlay.combat.entity.CombatEntity 6 | 7 | abstract class SkillAbilityExecution:AbilityExecution() { 8 | 9 | lateinit var inputCombatEntity:CombatEntity 10 | lateinit var inputPoint:Vector3 11 | var inputDirection:Float = 0f 12 | 13 | override fun beginExecute() { 14 | super.beginExecute() 15 | getAbility().spelling = true 16 | } 17 | 18 | override fun endExecute() { 19 | getAbility().spelling = false 20 | super.endExecute() 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/ability/status/StatusAbilityExecution.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.ability.status 2 | 3 | import com.badlogic.gdx.math.Vector3 4 | import com.lj.core.gamePlay.combat.entity.ability.AbilityExecution 5 | import com.lj.core.gamePlay.combat.entity.CombatEntity 6 | 7 | abstract class StatusAbilityExecution:AbilityExecution() { 8 | 9 | lateinit var inputCombatEntity: CombatEntity 10 | lateinit var inputPoint:Vector3 11 | var inputDirection:Float = 0f 12 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/ability/status/StatusLifeTimeComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.ability.status 2 | 3 | import com.lj.core.ecs.Component 4 | import com.lj.core.gamePlay.combat.timer.GameTimer 5 | 6 | /** 7 | * 状态的生命周期组件 8 | */ 9 | class StatusLifeTimeComponent:Component() { 10 | 11 | override var enable: Boolean= true 12 | lateinit var lifeTimer: GameTimer 13 | 14 | override fun setup() { 15 | val status = entity as StatusAbility 16 | val timer = status.statusConfigObject.duration/1000f 17 | lifeTimer = GameTimer(timer) 18 | } 19 | 20 | override fun update() { 21 | if (lifeTimer.isRunning){ 22 | val deltaTime = 0.1f 23 | lifeTimer.updateAsFinish(deltaTime){ 24 | getEntityT().endAbility() 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/action/ActionPointManageComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.action 2 | 3 | import com.lj.core.ecs.Component 4 | 5 | /** 6 | * 行动点,一次战斗行动会触发战斗实体一系列的行动点 7 | */ 8 | class ActionPoint{ 9 | var listeners = mutableListOf<(combatAction:CombatAction)->Unit>() 10 | } 11 | 12 | enum class ActionPointType{ 13 | PreCauseDamage, //造成伤害前 14 | PreReceiveDamage, //承受伤害前 15 | PostCauseDamage, //造成伤害后 16 | PostReceiveDamage, //承受伤害后 17 | 18 | PostGiveCure, //给予治疗后 19 | PostReceiveCure, //接受治疗后 20 | 21 | AssignEffect, //赋给效果 22 | ReceiveEffect, //接受效果 23 | 24 | PostGiveStatus, //赋加状态后 25 | PostReceiveStatus, //承受状态后 26 | 27 | Max, 28 | } 29 | 30 | /** 31 | * 行动点管理器,在这里管理一个战斗实体所有行动点的添加监听、移除监听、触发流程 32 | */ 33 | class ActionPointManageComponent: Component() { 34 | 35 | private var actionPoints = mutableMapOf() 36 | 37 | override fun setup() { 38 | super.setup() 39 | } 40 | 41 | fun addListener(actionPointType: ActionPointType, action:(combatAction:CombatAction)->Unit){ 42 | if(!this.actionPoints.containsKey(actionPointType)){ 43 | this.actionPoints[actionPointType] = ActionPoint() 44 | } 45 | actionPoints[actionPointType]?.listeners?.add(action) 46 | } 47 | 48 | fun removeListener(actionPointType: ActionPointType, action:(combatAction:CombatAction)->Unit){ 49 | actionPoints[actionPointType]?.listeners?.remove(action) 50 | } 51 | 52 | fun triggerActionPoint(actionPointType: ActionPointType, action:CombatAction){ 53 | actionPoints[actionPointType]?.listeners?.forEach { it-> 54 | it(action) 55 | } 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/action/AssignEffectAction.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.action 2 | 3 | import com.lj.core.gamePlay.combat.entity.ability.AbilityEntity 4 | import com.lj.core.gamePlay.combat.entity.ability.status.StatusAbility 5 | import com.lj.core.gamePlay.combat.entity.ability.status.StatusLifeTimeComponent 6 | import com.lj.core.gamePlay.config.BattleConfigManager 7 | import com.lj.core.gamePlay.config.effect.AddStatusEffect 8 | import com.lj.core.gamePlay.config.effect.DamageEffect 9 | import com.lj.core.gamePlay.config.effect.Effect 10 | 11 | /** 12 | * 赋给效果行动 13 | */ 14 | class AssignEffectAction:CombatAction() { 15 | override var actionType = ActionType.AssignEffect 16 | 17 | ////创建这个赋给效果行动的源能力 18 | lateinit var sourceAbility:AbilityEntity 19 | lateinit var effect:Effect 20 | lateinit var status:StatusAbility 21 | 22 | 23 | override fun process() { 24 | 25 | if (effect is DamageEffect){ 26 | 27 | } 28 | 29 | if (effect is AddStatusEffect){ 30 | val addStatusEffect = effect as AddStatusEffect 31 | val addStatus = addStatusEffect.addStatus 32 | 33 | val statusConfig = BattleConfigManager.getStatusConfig(addStatus!!) 34 | if (statusConfig!!.canStack){ 35 | if (target.hasStatus(status._id.toString())){ 36 | val status = target.getStatus(statusConfig.id.toString()) 37 | val statusLifeTimer = status?.getComponent()?.lifeTimer 38 | statusLifeTimer!!.maxTime = addStatusEffect.duration/1000f 39 | statusLifeTimer.reset() 40 | return 41 | } 42 | } 43 | status = target.attachStatus(statusConfig) 44 | status.caster = creator 45 | status.level = sourceAbility.level 46 | status.addComponent() 47 | status.tryActivateAbility() 48 | } 49 | 50 | } 51 | 52 | 53 | ////后置处理 54 | override fun postProcess(){ 55 | if (effect is AddStatusEffect){ 56 | creator.triggerActionPoint(ActionPointType.PostGiveStatus, this) 57 | target.triggerActionPoint(ActionPointType.PostReceiveStatus, this) 58 | } 59 | } 60 | 61 | enum class EffectType{ 62 | DamageAffect, 63 | NumericModify, 64 | StatusAttach, 65 | BuffAttach 66 | } 67 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/action/CombatAction.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.action 2 | 3 | import com.lj.core.ecs.Entity 4 | import com.lj.core.gamePlay.combat.entity.CombatEntity 5 | 6 | /** 7 | * 动作作用目标 8 | */ 9 | enum class ActionTargetType { 10 | Instigator, 11 | Target 12 | } 13 | 14 | enum class ActionType{ 15 | SpellSkill, //施放技能 16 | CauseDamage, //造成伤害 17 | GiveCure, //给予治疗 18 | AssignEffect, //赋给效果 19 | Motion //动作行动 20 | } 21 | 22 | /** 23 | * 战斗行动概念,造成伤害、治疗英雄、赋给效果等属于战斗行动,需要继承自CombatAction 24 | * 战斗行动由战斗实体主动发起,包含本次行动所需要用到的所有数据,并且会触发一系列行动点事件 25 | */ 26 | abstract class CombatAction : Entity() { 27 | 28 | abstract var actionType: ActionType 29 | 30 | lateinit var creator: CombatEntity 31 | lateinit var target: CombatEntity 32 | 33 | protected open fun preProcess() { 34 | 35 | } 36 | 37 | protected open fun process(){ 38 | 39 | } 40 | 41 | protected open fun postProcess() { 42 | 43 | } 44 | 45 | fun applyAction() { 46 | this.preProcess() 47 | this.process() 48 | this.postProcess() 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/action/CureAction.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.action 2 | 3 | import com.lj.core.gamePlay.config.effect.CureEffect 4 | 5 | /** 6 | * 治疗行动 7 | */ 8 | class CureAction :CombatAction() { 9 | override var actionType = ActionType.GiveCure 10 | 11 | var cureEffect:CureEffect?=null 12 | var cureValue:Int = 0 //治疗数值 13 | 14 | override fun preProcess() { 15 | cureValue = cureEffect?.cureValueFormula?.toInt() ?: 0 16 | } 17 | 18 | override fun process() { 19 | target.receiveCure(this) 20 | } 21 | 22 | override fun postProcess() { 23 | creator.triggerActionPoint(ActionPointType.PostGiveCure, this) 24 | target.triggerActionPoint(ActionPointType.PostGiveCure, this) 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/action/DamageAction.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.action 2 | 3 | import com.lj.core.gamePlay.combat.attribute.AttributeComponent 4 | import com.lj.core.gamePlay.config.effect.DamageEffect 5 | import com.lj.core.gamePlay.helper.ExpressionHelper 6 | import kotlin.math.max 7 | import kotlin.random.Random 8 | 9 | /** 10 | * 伤害行动 11 | */ 12 | class DamageAction:CombatAction() { 13 | override var actionType = ActionType.CauseDamage 14 | 15 | lateinit var damageEffect:DamageEffect 16 | lateinit var damageSource:DamageSource //伤害来源 17 | var damageValue:Int = 0 //伤害数值 18 | var isCritical:Boolean = false //是否是暴击 19 | 20 | private fun parseDamage():Int{ 21 | val express = ExpressionHelper.expressionParser.evaluteExpression(damageEffect.damageValueFormula!!) 22 | 23 | val power = creator.getComponent()?.attackPower?.value 24 | express.parameters["自身攻击力"]?.value = power!!.toDouble() 25 | 26 | return express.value.toInt() 27 | } 28 | 29 | ////前置处理 30 | override fun preProcess(){ 31 | if (damageSource == DamageSource.Attack){ 32 | var prob = creator.getComponent()?.criticalProbability?.value 33 | isCritical = Random(100).nextInt()/100f < prob!! 34 | 35 | val attack:Float = creator.getComponent()?.attackPower?.value?:0.0f 36 | val defence:Float = target.getComponent()?.attackDefense?.value?:0.0f 37 | damageValue = max(1, (attack-defence).toInt()) 38 | if (isCritical){ 39 | damageValue = (damageValue * 1.5).toInt() 40 | } 41 | } 42 | 43 | if (damageSource == DamageSource.Skill){ 44 | if (damageEffect.canCrit){ 45 | var prob = creator.getComponent()?.criticalProbability?.value 46 | isCritical = Random(100).nextInt()/100f < prob!! 47 | } 48 | damageValue = parseDamage() 49 | if (isCritical){ 50 | damageValue = (damageValue * 1.5).toInt() 51 | } 52 | } 53 | 54 | if (damageSource == DamageSource.Buff){ 55 | if (damageEffect.canCrit){ 56 | var prob = creator.getComponent()?.criticalProbability?.value 57 | isCritical = Random(100).nextInt()/100f < prob!! 58 | } 59 | damageValue = parseDamage() 60 | } 61 | } 62 | 63 | override fun process() { 64 | target.receiveDamage(this) 65 | 66 | } 67 | 68 | //后置处理 69 | override fun postProcess(){ 70 | //触发 造成伤害后 行动点 71 | creator.triggerActionPoint(ActionPointType.PostCauseDamage, this) 72 | target.triggerActionPoint(ActionPointType.PostReceiveDamage, this) 73 | } 74 | 75 | enum class DamageSource{ 76 | Attack,//普攻 77 | Skill,//技能 78 | Buff,//Buff 79 | } 80 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/action/MotionAction.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.action 2 | 3 | /** 4 | * 动作行动 5 | */ 6 | class MotionAction:CombatAction() { 7 | override var actionType = ActionType.Motion 8 | 9 | var motionType:Int = 0 10 | 11 | ////前置处理 12 | override fun preProcess() { 13 | 14 | } 15 | 16 | override fun process() { 17 | 18 | } 19 | 20 | //后置处理 21 | override fun postProcess() { 22 | 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/action/SpellSkillAction.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.action 2 | 3 | import com.lj.core.gamePlay.combat.entity.ability.skill.SkillAbility 4 | import com.lj.core.gamePlay.combat.entity.ability.skill.SkillAbilityExecution 5 | 6 | /** 7 | * 施放技能行动 8 | */ 9 | class SpellSkillAction:CombatAction() { 10 | override var actionType = ActionType.SpellSkill 11 | 12 | var skillID:Int = 0 13 | lateinit var skillAbility: SkillAbility 14 | var skillAbilityExecution: SkillAbilityExecution?=null 15 | 16 | //前置处理 17 | override fun preProcess(){ 18 | 19 | } 20 | 21 | override fun process(){ 22 | 23 | if (skillAbilityExecution == null){ 24 | skillAbility.applyAbilityEffectsTo(target) 25 | }else{ 26 | skillAbilityExecution?.beginExecute() 27 | } 28 | 29 | } 30 | 31 | ////后置处理 32 | override fun postProcess(){ 33 | 34 | } 35 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/condition/ConditionEntity.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.condition 2 | 3 | import com.lj.core.ecs.Entity 4 | 5 | abstract class ConditionEntity:Entity() -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/condition/ConditionManageComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.condition 2 | 3 | import com.lj.core.ecs.Component 4 | import com.lj.core.ecs.Entity 5 | import com.lj.core.gamePlay.config.ConditionType 6 | 7 | /** 8 | * 条件管理组件,在这里管理一个战斗实体所有条件达成事件的添加监听、移除监听、触发流程 9 | */ 10 | class ConditionManageComponent: Component() { 11 | 12 | private val conditions = mutableMapOf<()->Unit, ConditionEntity>() 13 | 14 | override fun setup(){ 15 | super.setup() 16 | } 17 | 18 | fun addListener(conditionType: ConditionType, action:()->Unit, paramObj:Any? = null){ 19 | when(conditionType){ 20 | ConditionType.WhenInTimeNoDamage ->{ 21 | val time = paramObj as Float 22 | val condition = Entity.createWithParent(entity, time) 23 | conditions[action] = condition 24 | } 25 | ConditionType.WhenHPLower ->{ 26 | 27 | } 28 | ConditionType.WhenHPPctLower ->{ 29 | 30 | }else ->{ 31 | 32 | } 33 | } 34 | } 35 | 36 | fun removeListener(conditionType: ConditionType, action:()->Unit){ 37 | if (conditions.containsKey(action)){ 38 | conditions[action]?.let { Entity.destroy(it) } 39 | conditions.remove(action) 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/condition/WhenInTimeNoDamageCondition.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.condition 2 | 3 | import com.lj.core.gamePlay.combat.entity.action.ActionPointType 4 | import com.lj.core.gamePlay.combat.entity.action.CombatAction 5 | import com.lj.core.gamePlay.combat.entity.CombatEntity 6 | import com.lj.core.gamePlay.combat.timer.GameTimer 7 | 8 | class WhenInTimeNoDamageCondition : ConditionEntity() { 9 | private lateinit var noDamageTimer: GameTimer 10 | 11 | override fun awake(initData: Any) { 12 | val time = initData.toString().toFloat() 13 | noDamageTimer = GameTimer(time) 14 | getParentT().listenActionPoint(ActionPointType.PostReceiveDamage){combatAction-> 15 | whenReceiveDamage(combatAction) 16 | } 17 | } 18 | 19 | suspend fun startListen(whenNoDamageInTimeCallback:()->Unit){ 20 | while (true){ 21 | if (isDisposed){ 22 | break 23 | } 24 | // await ET.TimerComponent.Instance.WaitAsync(100); 25 | noDamageTimer.updateAsFinish(0.1f,whenNoDamageInTimeCallback) 26 | } 27 | } 28 | 29 | private fun whenReceiveDamage(combatAction: CombatAction){ 30 | noDamageTimer.reset() 31 | } 32 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/logic/LogicActionTriggerComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.logic 2 | 3 | import com.lj.core.ecs.Component 4 | import com.lj.core.gamePlay.combat.entity.action.CombatAction 5 | import com.lj.core.gamePlay.combat.entity.ability.status.StatusAbility 6 | 7 | /** 8 | * 逻辑行动点触发组件 9 | */ 10 | class LogicActionTriggerComponent:Component() { 11 | 12 | override fun setup() { 13 | val actionPointType = getEntityT().effect.actionPointType 14 | getEntityT().getParentT().ownerEntity.listenActionPoint(actionPointType!!){ combatAction -> 15 | this.onActionPointTrigger(combatAction) 16 | } 17 | } 18 | 19 | private fun onActionPointTrigger(combatAction: CombatAction):Unit{ 20 | getEntityT().applyEffect() 21 | } 22 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/logic/LogicConditionTriggerComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.logic 2 | 3 | import com.lj.core.ecs.Component 4 | import com.lj.core.gamePlay.combat.entity.ability.status.StatusAbility 5 | 6 | /** 7 | * 逻辑条件触发组件 8 | */ 9 | class LogicConditionTriggerComponent :Component(){ 10 | 11 | override fun setup() { 12 | val conditionType = getEntityT().effect.conditionType 13 | val conditionParam = getEntityT().effect.conditionParam 14 | 15 | entity.getParentT().ownerEntity.listenerCondition( 16 | conditionType!!, 17 | { this.onConditionTrigger() }, 18 | conditionParam) 19 | 20 | } 21 | 22 | private fun onConditionTrigger(){ 23 | getEntityT().applyEffect() 24 | } 25 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/logic/LogicEntity.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.logic 2 | 3 | import com.lj.core.ecs.Entity 4 | import com.lj.core.gamePlay.combat.entity.action.DamageAction 5 | import com.lj.core.gamePlay.combat.entity.CombatEntity 6 | import com.lj.core.gamePlay.combat.entity.ability.status.StatusAbility 7 | import com.lj.core.gamePlay.config.effect.DamageEffect 8 | import com.lj.core.gamePlay.config.effect.Effect 9 | 10 | class LogicEntity :Entity() { 11 | lateinit var effect:Effect 12 | 13 | override fun awake(initData: Any) { 14 | effect = initData as Effect 15 | } 16 | 17 | fun applyEffect(){ 18 | if (effect is DamageEffect){ 19 | val damageEffect = effect as DamageEffect 20 | val damageAction = getParentT().caster?.createCombatAction() 21 | damageAction?.target = getParentT().getParentT() 22 | damageAction?.damageSource = DamageAction.DamageSource.Buff 23 | damageAction?.applyAction() 24 | }else{ 25 | getParentT().applyEffectTo(getParentT().ownerEntity, effect) 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/entity/logic/LogicIntervalTriggerComponent.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.entity.logic 2 | 3 | import com.lj.core.ecs.Component 4 | import com.lj.core.gamePlay.combat.entity.ability.status.StatusAbility 5 | import com.lj.core.gamePlay.helper.ExpressionHelper 6 | import com.lj.core.gamePlay.combat.timer.GameTimer 7 | 8 | /** 9 | * 逻辑间隔触发组件 10 | */ 11 | class LogicIntervalTriggerComponent :Component(){ 12 | 13 | override var enable:Boolean = true 14 | lateinit var intervalTimer: GameTimer 15 | 16 | override fun setup() { 17 | val intervalStr = getEntityT().effect.interval 18 | val expression = ExpressionHelper.expressionParser.evaluteExpression(intervalStr!!) 19 | if (expression.parameters.containsKey("技能等级")){ 20 | val level = getEntityT().getParentT().level 21 | expression.parameters["技能等级"]?.value = level.toDouble() 22 | } 23 | val interval = expression.value/1000f 24 | intervalTimer = GameTimer(interval.toFloat()) 25 | } 26 | 27 | override fun update() { 28 | val deltaTime = 0.1f 29 | intervalTimer.updateAsRepeat(deltaTime){ 30 | getEntityT().applyEffect() 31 | } 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/timer/GameTimer.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.timer 2 | 3 | 4 | class GameTimer(maxTime: Float) { 5 | private var _maxTime:Float = maxTime 6 | private var _time:Float = 0f 7 | private var _onFinish: (() -> Unit)? = null 8 | 9 | var maxTime:Float 10 | get() { 11 | return _maxTime 12 | } 13 | set(value) { 14 | _maxTime = value 15 | } 16 | 17 | val isFinished:Boolean 18 | get() = this._time >= this._maxTime 19 | 20 | val isRunning:Boolean 21 | get() = this._time < this._maxTime 22 | 23 | val time:Float 24 | get() = this._time 25 | 26 | 27 | fun reset(){ 28 | this._time = 0f 29 | } 30 | 31 | fun updateAsFinish(delta:Float, onFinish:(() -> Unit)? = null): GameTimer { 32 | if(!isFinished){ 33 | this._time += delta 34 | if (onFinish != null) _onFinish = onFinish 35 | if (isFinished) _onFinish?.invoke() 36 | } 37 | return this 38 | } 39 | 40 | fun updateAsRepeat(delta:Float, onRepeat:(() -> Unit)? = null){ 41 | this._time += delta 42 | if (onRepeat != _onFinish) _onFinish = onRepeat 43 | while (_time >= _maxTime){ 44 | _time -= _maxTime 45 | _onFinish?.invoke() 46 | } 47 | } 48 | 49 | fun onFinish(onFinish:(() -> Unit)? = null){ 50 | _onFinish = onFinish 51 | } 52 | 53 | fun onRepeat(onRepeat: (() -> Unit)? = null){ 54 | _onFinish = onRepeat 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/combat/timer/Time.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.combat.timer 2 | 3 | object Time { 4 | val deltaTime:Float = 0.02f 5 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/BattleConfigManager.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config 2 | 3 | import io.vertx.core.json.JsonObject 4 | import jodd.util.ClassLoaderUtil 5 | import kt.scaffold.Application 6 | import kt.scaffold.ext.filePathJoin 7 | import java.io.File 8 | 9 | enum class BattleConfigType{ 10 | SkillConfigs, 11 | StatusConfigs 12 | } 13 | 14 | object BattleConfigManager { 15 | 16 | 17 | fun initialize(){ 18 | 19 | 20 | } 21 | 22 | 23 | 24 | fun getSkillConfig(id:String): SkillConfigObject? { 25 | val path = this.getPath(BattleConfigType.SkillConfigs,id) 26 | 27 | val file = File(path) 28 | if(!file.exists()) return null 29 | 30 | var text = file.readText() 31 | 32 | var json = JsonObject(text) 33 | var configObject = json.mapTo(SkillConfigObject::class.java) 34 | 35 | return configObject 36 | } 37 | 38 | fun getStatusConfig(name:String): StatusConfigObject? { 39 | val path = this.getPath(BattleConfigType.StatusConfigs,name) 40 | 41 | val file = File(path) 42 | if(!file.exists()) return null 43 | 44 | var text = file.readText() 45 | 46 | var json = JsonObject(text) 47 | var configObject = json.mapTo(StatusConfigObject::class.java) 48 | 49 | return configObject 50 | } 51 | 52 | private fun getPath(type:BattleConfigType, id:String):String{ 53 | var prefix = "Skill_" 54 | if (type == BattleConfigType.StatusConfigs) prefix = "Status_" 55 | 56 | val fileName = "${prefix}${id}.json" 57 | 58 | var fbPath = filePathJoin(Application.appHome, "skills/${type.name}",fileName) 59 | if (File(fbPath).exists().not()){ 60 | fbPath = ClassLoaderUtil.getDefaultClassLoader().getResource("skills/${type.name}/$fileName")!!.path 61 | } 62 | return fbPath 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/SkillConfigObject.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config 2 | 3 | import com.lj.core.gamePlay.config.effect.Effect 4 | 5 | class SkillConfigObject { 6 | 7 | var id:Int = 0 8 | lateinit var name:String 9 | lateinit var skillSpellType:SkillSpellType 10 | lateinit var targetSelectType:SkillTargetSelectType 11 | lateinit var affectAreaType:SkillAffectAreaType 12 | 13 | var circleAreaRadius:Float = 0f 14 | 15 | lateinit var affectTargetType:SkillAffectTargetType 16 | 17 | var coldTime:Int = 0 18 | 19 | var effects = mutableListOf() 20 | 21 | 22 | } 23 | 24 | enum class ShieldType{ 25 | Shield, 26 | PhysicShield, 27 | MagicShield, 28 | SkillShield 29 | } 30 | 31 | enum class TagType{ 32 | Power 33 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/StatusConfigObject.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config 2 | 3 | import com.lj.core.gamePlay.config.effect.Effect 4 | 5 | class StatusConfigObject { 6 | var id:String ?= null 7 | var name:String ?= null 8 | var statusType:StatusType ?= null 9 | var duration:Int = 0 10 | var showInStatusSlots:Boolean = false 11 | var canStack:Boolean = false 12 | var maxStack:Int = 0 13 | 14 | var enableChildrenStatuses:Boolean = false 15 | var childrenStatuses = mutableListOf() 16 | 17 | var enabledStateModify:Boolean = false 18 | var actionControlType:ActionControlType ?= null 19 | 20 | val enabledAttributeModify:Boolean = false 21 | var attributeType:AttributeType ?= null 22 | var numericValue:String ?= null 23 | var modifyType:ModifyType ?= null 24 | 25 | var enabledLogicTrigger:Boolean = false 26 | 27 | var effects = mutableListOf() 28 | 29 | } 30 | 31 | class ChildStatus{ 32 | var statusConfigObject:StatusConfigObject?=null //状态效果 33 | var params:MutableMap?= mutableMapOf() //参数列表 34 | } 35 | 36 | enum class StatusType{ 37 | Buff, 38 | Debuff, 39 | Other 40 | } 41 | 42 | enum class EffectTriggerType(var p: Int){ 43 | Instant(0), 44 | Condition(1), 45 | Action(2), 46 | Interval(3) 47 | } 48 | 49 | enum class ConditionType(var p:Int){ 50 | WhenInTimeNoDamage(0), 51 | WhenHPLower(1), 52 | WhenHPPctLower(2) 53 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/effect/AddShieldEffect.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config.effect 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | import com.lj.core.gamePlay.config.ShieldType 5 | 6 | @JsonTypeName("AddShieldEffect") 7 | class AddShieldEffect:Effect() { 8 | 9 | var shieldType: ShieldType?=null 10 | var shieldValue:Int = 0 11 | var shieldDuration:Int = 0 12 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/effect/AddStatusEffect.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config.effect 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | 5 | @JsonTypeName("AddStatusEffect") 6 | class AddStatusEffect:Effect() { 7 | var addStatus:String?="" 8 | var duration:Int = 0 9 | var params = mutableMapOf() 10 | 11 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/effect/AttributeNumericModifyEffect.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config.effect 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | import com.lj.core.gamePlay.combat.attribute.AttributeType 5 | 6 | @JsonTypeName("AttributeNumericModifyEffect") 7 | class AttributeNumericModifyEffect:Effect() { 8 | 9 | var numericType:AttributeType?=null 10 | var numericValue:String?=null 11 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/effect/ClearAllStatusEffect.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config.effect 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | 5 | @JsonTypeName("ClearAllStatusEffect") 6 | class ClearAllStatusEffect:Effect() { 7 | 8 | 9 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/effect/CureEffect.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config.effect 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | 5 | @JsonTypeName("CureEffect") 6 | class CureEffect:Effect() { 7 | var cureValueFormula:String?=null 8 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/effect/CustomEffect.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config.effect 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | 5 | @JsonTypeName("CustomEffect") 6 | class CustomEffect:Effect() { 7 | var customEffectDescription:String?=null 8 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/effect/DamageEffect.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config.effect 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | import com.lj.core.gamePlay.config.DamageType 5 | 6 | @JsonTypeName("DamageEffect") 7 | class DamageEffect:Effect() { 8 | var damageType: DamageType?=null 9 | var damageValueFormula:String?=null 10 | var canCrit:Boolean = false 11 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/effect/Effect.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config.effect 2 | 3 | import com.fasterxml.jackson.annotation.JsonSubTypes 4 | import com.fasterxml.jackson.annotation.JsonTypeInfo 5 | import com.lj.core.gamePlay.combat.entity.action.ActionPointType 6 | import com.lj.core.gamePlay.config.* 7 | 8 | 9 | @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,property = "@class") 10 | @JsonSubTypes( 11 | JsonSubTypes.Type(value = AddShieldEffect::class, name = "AddShieldEffect"), 12 | JsonSubTypes.Type(value = AddStatusEffect::class, name = "AddStatusEffect"), 13 | JsonSubTypes.Type(value = AttributeNumericModifyEffect::class, name = "AttributeNumericModifyEffect"), 14 | JsonSubTypes.Type(value = ClearAllStatusEffect::class, name = "ClearAllStatusEffect"), 15 | JsonSubTypes.Type(value = CureEffect::class, name = "CureEffect"), 16 | JsonSubTypes.Type(value = CustomEffect::class, name = "CustomEffect"), 17 | JsonSubTypes.Type(value = DamageEffect::class, name = "DamageEffect"), 18 | JsonSubTypes.Type(value = RemoveStatusEffect::class, name = "RemoveStatusEffect"), 19 | JsonSubTypes.Type(value = StackTagEffect::class, name = "StackTagEffect") 20 | ) 21 | abstract class Effect { 22 | 23 | var isSkillEffect:Boolean = true 24 | var addSkillEffectTargetType: AddSkillEffetTargetType?=null 25 | var effectTriggerType: EffectTriggerType?=null 26 | var conditionType:ConditionType?=null 27 | var actionPointType: ActionPointType?=null 28 | var interval:String?=null 29 | var conditionParam:String?=null 30 | var triggerProbability:String?=null 31 | } 32 | 33 | /** 34 | * 效果作用目标 35 | */ 36 | enum class EffectTargetType { 37 | Self, 38 | TargetEnemy, 39 | AllEnemies, 40 | All 41 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/effect/RemoveStatusEffect.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config.effect 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | 5 | @JsonTypeName("RemoveStatusEffect") 6 | class RemoveStatusEffect:Effect() { 7 | var removeStatus:String?=null 8 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/config/effect/StackTagEffect.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.config.effect 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName 4 | import com.lj.core.gamePlay.config.TagType 5 | 6 | @JsonTypeName("StackTagEffect") 7 | class StackTagEffect :Effect(){ 8 | var tagType:TagType?=null 9 | var tagCount:Int = 1 10 | var tagDuration:Int = 0 11 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/gamePlay/helper/ExpressionHelper.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.gamePlay.helper 2 | 3 | import kt.scaffold.tools.ExpressionParser 4 | 5 | object ExpressionHelper { 6 | val expressionParser = ExpressionParser() 7 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/net/Opcode.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.net 2 | 3 | object Opcode { 4 | 5 | const val MSG_C2R_Login:Short = 1000; 6 | const val MSG_R2C_Login:Short = 1001; 7 | const val MSG_C2G_LoginGate:Short = 1002; 8 | const val MSG_G2C_LoginGate:Short = 1003; 9 | 10 | 11 | 12 | 13 | const val MSG_C2GS_Test:Short = 2001; 14 | const val MSG_GS2C_Test:Short = 2002; 15 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/net/msg/BaseHandler.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.net.msg 2 | 3 | import com.lj.core.service.Msg 4 | 5 | abstract class BaseHandler{ 6 | abstract fun process(socketId:String, msg: Msg); 7 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/net/msg/MsgMessageCodec.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.net.msg 2 | 3 | import com.lj.core.service.Msg 4 | import io.vertx.core.buffer.Buffer 5 | import io.vertx.core.eventbus.MessageCodec 6 | import java.io.* 7 | 8 | 9 | class MsgMessageCodec : MessageCodec { 10 | 11 | override fun decodeFromWire(pos: Int, buffer: Buffer): Msg? { 12 | val b = ByteArrayInputStream(buffer.bytes) 13 | var msg: Msg? = null 14 | try { 15 | ObjectInputStream(b).use { o -> msg = o.readObject() as Msg } 16 | } catch (e: IOException) { 17 | e.printStackTrace() 18 | } catch (e: ClassNotFoundException) { 19 | e.printStackTrace() 20 | } 21 | return msg 22 | } 23 | 24 | override fun encodeToWire(buffer: Buffer, s: Msg) { 25 | val b = ByteArrayOutputStream() 26 | try { 27 | ObjectOutputStream(b).use { o -> 28 | o.writeObject(b) 29 | o.close() 30 | buffer.appendBytes(b.toByteArray()) 31 | } 32 | } catch (e: IOException) { 33 | e.printStackTrace() 34 | } 35 | } 36 | 37 | override fun transform(s: Msg): Msg { 38 | return s; 39 | } 40 | 41 | override fun name(): String { 42 | return "msgCodec" 43 | } 44 | 45 | override fun systemCodecID(): Byte { 46 | return -1 47 | } 48 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/service/GameService.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.service 2 | 3 | import io.vertx.codegen.annotations.ProxyGen 4 | import io.vertx.codegen.annotations.VertxGen 5 | import io.vertx.core.AsyncResult 6 | import io.vertx.core.Handler 7 | 8 | @VertxGen 9 | @ProxyGen 10 | interface GameService{ 11 | 12 | fun dispatch( 13 | msg: Msg, 14 | handler: Handler> 15 | ) 16 | 17 | 18 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/service/Msg.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.service 2 | 3 | import io.vertx.codegen.annotations.DataObject 4 | import io.vertx.core.json.JsonObject 5 | 6 | /** 7 | * @DataObject 注解用于服务器生成Rpc用 8 | */ 9 | @DataObject 10 | data class Msg( 11 | var seq:Int, 12 | var msgId:Short, 13 | var serverType:Byte, 14 | var serverId:Short, 15 | var userId:Long, 16 | var base64Msg:String){ 17 | 18 | constructor(json: JsonObject): 19 | this(json.getInteger("seq"), 20 | json.getInteger("msgId").toShort(), 21 | json.getInteger("serverType").toByte(), 22 | json.getInteger("serverId").toShort(), 23 | json.getLong("userId"), 24 | json.getString("base64Msg")) 25 | 26 | fun toJson():JsonObject = JsonObject.mapFrom(this) 27 | 28 | fun copy():Msg{ 29 | return Msg(seq,msgId,serverType,serverId,userId,base64Msg) 30 | } 31 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/service/handler/BaseHandler.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.service.handler 2 | 3 | import com.lj.core.service.Msg 4 | import io.vertx.core.AsyncResult 5 | import io.vertx.core.Handler 6 | 7 | abstract class BaseHandler{ 8 | abstract fun process(msg: Msg,handler: Handler>); 9 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/service/handler/ServiceDispatcher.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.service.handler 2 | 3 | import com.lj.core.common.CmdExecutor 4 | import com.lj.core.common.ServiceHandlerAnnotation 5 | import com.lj.core.service.Msg 6 | import com.lj.core.utils.ClassScanner 7 | import io.vertx.core.AsyncResult 8 | import io.vertx.core.Handler 9 | import kt.scaffold.tools.logger.Logger 10 | 11 | object ServiceDispatcher { 12 | 13 | private val cmdHandlers = mutableMapOf() 14 | 15 | fun initialize(packageName:String){ 16 | val messageCommandClasses = ClassScanner.listClassesWithAnnotation(packageName, 17 | ServiceHandlerAnnotation::class.java) 18 | for(cls in messageCommandClasses){ 19 | try{ 20 | val handler = cls.getDeclaredConstructor().newInstance() 21 | val method = cls.getMethod("process", Msg::class.java, Handler::class.java) 22 | val msgId = cls.getAnnotation(ServiceHandlerAnnotation::class.java).opcode 23 | 24 | var cmdExecutor = cmdHandlers.get(msgId) 25 | if (cmdExecutor!=null) throw RuntimeException("cmd[$msgId] duplicated") 26 | 27 | cmdExecutor = CmdExecutor(method, handler as Object) 28 | cmdHandlers.put(msgId, cmdExecutor) 29 | 30 | }catch (e:Exception){ 31 | Logger.error("initialize error: ${e.cause}") 32 | } 33 | } 34 | } 35 | 36 | fun dispatch(msg: Msg, handler:Handler>){ 37 | val cmdExecutor: CmdExecutor? = cmdHandlers.get(msg.msgId) 38 | if(cmdExecutor == null){ 39 | Logger.error("message executor missed, cmd=${msg.msgId}") 40 | return 41 | } 42 | 43 | try { 44 | cmdExecutor.method.invoke(cmdExecutor.handler,msg,handler) 45 | }catch (e:Exception){ 46 | Logger.error("dispatch error: ${msg.msgId}, ${e.cause}") 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/com/lj/core/service/impl/GameServiceImpl.kt: -------------------------------------------------------------------------------- 1 | package com.lj.core.service.impl 2 | 3 | import com.lj.core.service.GameService 4 | import com.lj.core.service.Msg 5 | import com.lj.core.service.handler.ServiceDispatcher 6 | import io.vertx.core.AsyncResult 7 | import io.vertx.core.Handler 8 | import kotlinx.coroutines.GlobalScope 9 | import kotlinx.coroutines.async 10 | import kotlinx.coroutines.launch 11 | 12 | 13 | class GameServiceImpl: GameService { 14 | 15 | override fun dispatch(msg: Msg, handler:Handler>) { 16 | //开协成进行异步处理 17 | GlobalScope.launch { 18 | ServiceDispatcher.dispatch(msg,handler); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/kotlin/fb/FBManager.kt: -------------------------------------------------------------------------------- 1 | package fb 2 | import jodd.util.ClassLoaderUtil 3 | import kt.scaffold.Application 4 | import kt.scaffold.ext.filePathJoin 5 | import java.io.File 6 | import java.nio.ByteBuffer 7 | object FBManager { 8 | lateinit var heroconfig:heroconfigTB 9 | lateinit var skillconfig:skillconfigTB 10 | lateinit var unitconfig:unitconfigTB 11 | fun initialize(){ 12 | heroconfig = heroconfigTB.getRootAsheroconfigTB(ByteBuffer.wrap(File(getPath("heroconfig.bin")).readBytes())) 13 | skillconfig = skillconfigTB.getRootAsskillconfigTB(ByteBuffer.wrap(File(getPath("skillconfig.bin")).readBytes())) 14 | unitconfig = unitconfigTB.getRootAsunitconfigTB(ByteBuffer.wrap(File(getPath("unitconfig.bin")).readBytes())) 15 | } 16 | private fun getPath(name:String):String{ 17 | var fbPath = filePathJoin(Application.appHome, "fb",name) 18 | if (File(fbPath).exists().not()){ 19 | fbPath = ClassLoaderUtil.getDefaultClassLoader().getResource("fb/$name")!!.path 20 | } 21 | return fbPath 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /apps/lib-core/src/main/proto/benchmark.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | package nice_ts; 4 | option java_package = "com.lj.proto"; 5 | 6 | //游戏服基准测试协议 7 | message C2GS_Test // IRequest 8 | { 9 | int32 testID = 1; 10 | string testName = 2; 11 | } 12 | 13 | message GS2C_Test // IResponse 14 | { 15 | int32 Error = 91; 16 | string Message = 92; 17 | string testResponse = 1; 18 | } 19 | -------------------------------------------------------------------------------- /apps/lib-core/src/main/proto/login.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package nice_ts; 3 | option java_package = "com.lj.proto"; 4 | 5 | message C2R_Login // IRequest 6 | { 7 | string Account = 1; // 帐号 8 | string Password = 2; // 密码 9 | } 10 | 11 | message R2C_Login // IResponse 12 | { 13 | int32 Error = 91; 14 | string Message = 92; 15 | string Address = 1; 16 | int64 Key = 2; 17 | int64 GateId = 3; 18 | } 19 | 20 | 21 | message C2G_LoginGate // IRequest 22 | { 23 | int64 Key = 1; // 帐号 24 | int64 GateId = 2; 25 | } 26 | 27 | message G2C_LoginGate // IResponse 28 | { 29 | int32 Error = 91; 30 | string Message = 92; 31 | int64 PlayerId = 1; 32 | } -------------------------------------------------------------------------------- /apps/lib-core/src/main/proto/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | //生成js 3 | pbjs -t static-module -w commonjs -o pb.js login.proto benchmark.proto 4 | 5 | //生成d.ts 6 | pbts -o pb.d.ts pb.js -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * This is a general purpose Gradle build. 5 | * Learn how to create Gradle builds at https://guides.gradle.org/creating-new-gradle-builds/ 6 | */ 7 | 8 | plugins { 9 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 10 | kotlin("jvm").version("1.4.21").apply(false) 11 | } 12 | 13 | allprojects { 14 | group = "com.nice.kt" 15 | version = "1.0.0-dev" 16 | 17 | System.getProperty("version")?.apply { 18 | version = this 19 | } 20 | 21 | repositories { 22 | mavenLocal() 23 | maven(url="https://maven.aliyun.com/repository/public/") 24 | mavenCentral() 25 | jcenter() 26 | } 27 | 28 | } 29 | 30 | tasks.register("removeLocalSzJarsCache") { 31 | val localMaven = this.project.repositories.mavenLocal() 32 | val path = localMaven.url.path + listOf("com", "nice", "kt").joinToString(separator = File.separator) 33 | this.delete(path) 34 | println("remove Local Maven Cache For KT Framework: $path") 35 | val gradleJsrCachePath = listOf(this.project.gradle.gradleUserHomeDir.path, "caches", "modules-2", "files-2.1", "com.nice.kt").joinToString(separator = File.separator) 36 | val gradleMetaCachePath1 = listOf(this.project.gradle.gradleUserHomeDir.path, "caches", "modules-2", "metadata-2.23", "descriptors", "com.nice.kt").joinToString(separator = File.separator) 37 | val gradleMetaCachePath2 = listOf(this.project.gradle.gradleUserHomeDir.path, "caches", "modules-2", "metadata-2.71", "descriptors", "com.nice.kt").joinToString(separator = File.separator) 38 | this.delete(gradleJsrCachePath, gradleMetaCachePath1, gradleMetaCachePath2) 39 | println("remove Local Gradle Cache For KT Framework: $gradleJsrCachePath") 40 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Justin-sky/Nice-KT/114d3561067181aa544ad719652dad3e6570d067/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | pluginManagement { 5 | repositories { 6 | maven(url = "https://maven.aliyun.com/repository/gradle-plugin") 7 | maven(url = "https://plugins.gradle.org/m2/") 8 | gradlePluginPortal() 9 | } 10 | } 11 | 12 | include("subProjects:nice-log") 13 | findProject(":subProjects:nice-log")?.name = "nice-log" 14 | include("subProjects:nice-tools") 15 | findProject(":subProjects:nice-tools")?.name = "nice-tools" 16 | include("subProjects:nice-crypto") 17 | findProject(":subProjects:nice-crypto")?.name = "nice-crypto" 18 | include("subProjects:nice-scaffold") 19 | findProject(":subProjects:nice-scaffold")?.name = "nice-scaffold" 20 | include("apps:app-gateway") 21 | findProject(":apps:app-gateway")?.name = "app-gateway" 22 | include("apps:app-login") 23 | findProject(":apps:app-login")?.name = "app-login" 24 | include("apps:app-gameserver") 25 | findProject(":apps:app-gameserver")?.name = "app-gameserver" 26 | include("lib-core") 27 | include("apps:lib-core") 28 | findProject(":apps:lib-core")?.name = "lib-core" 29 | include("apps:app-allinone") 30 | findProject(":apps:app-allinone")?.name = "app-allinone" 31 | include("apps:app-api") 32 | findProject(":apps:app-api")?.name = "app-api" 33 | include("apps:app-battle") 34 | findProject(":apps:app-battle")?.name = "app-battle" 35 | -------------------------------------------------------------------------------- /subProjects/nice-crypto/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | /* 4 | * This file was generated by the Gradle 'init' task. 5 | * 6 | * This generated file contains a sample Kotlin library project to get you started. 7 | */ 8 | 9 | plugins { 10 | kotlin("jvm") 11 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 12 | id("maven-publish") 13 | } 14 | 15 | dependencies { 16 | // Use the Kotlin JDK 8 standard library. 17 | implementation(kotlin("stdlib-jdk8")) 18 | api("org.bouncycastle:bcprov-jdk15on:1.58") 19 | 20 | // Use the Kotlin test library. 21 | testImplementation("org.jetbrains.kotlin:kotlin-test") 22 | 23 | // Use the Kotlin JUnit integration. 24 | testImplementation("org.jetbrains.kotlin:kotlin-test-junit") 25 | } 26 | 27 | tasks.register("sourcesJar") { 28 | from(sourceSets.main.get().allSource) 29 | archiveClassifier.set("sources") 30 | } 31 | 32 | publishing { 33 | publications { 34 | create("maven") { 35 | from(components["java"]) 36 | artifact(tasks["sourcesJar"]) 37 | } 38 | } 39 | 40 | val userHome = System.getProperty("user.home") 41 | 42 | repositories { 43 | var myRepo = "$userHome\\Documents\\u3dWorkspace\\NICE_Framework\\Nice-KT-Repository" 44 | System.getProperty("myRepo")?.apply { 45 | myRepo = this 46 | } 47 | maven { 48 | name = "myRepo" 49 | url = uri("file://$myRepo") 50 | } 51 | } 52 | } 53 | 54 | val compileKotlin: KotlinCompile by tasks 55 | compileKotlin.kotlinOptions { 56 | jvmTarget = "1.8" 57 | } 58 | 59 | val compileTestKotlin: KotlinCompile by tasks 60 | compileTestKotlin.kotlinOptions { 61 | jvmTarget = "1.8" 62 | } 63 | -------------------------------------------------------------------------------- /subProjects/nice-crypto/src/main/kotlin/kt/crypto/AesUtil.kt: -------------------------------------------------------------------------------- 1 | package kt.crypto 2 | 3 | import org.bouncycastle.util.encoders.Base64 4 | import java.nio.charset.Charset 5 | import java.security.SecureRandom 6 | import javax.crypto.Cipher 7 | import javax.crypto.KeyGenerator 8 | import javax.crypto.spec.SecretKeySpec 9 | 10 | /** 11 | * @param keysize: 密钥长度, 可选值(128, 192, 256), 默认128 12 | * @param cipherTransformation the standard name of the requested key algorithm. 13 | * See the KeyGenerator section in the 15 | * Java Cryptography Architecture Standard Algorithm Name Documentation 16 | * for information about standard algorithm names. 17 | */ 18 | @Suppress("MemberVisibilityCanBePrivate", "DuplicatedCode") 19 | class AesUtil(val keysize: Int = 128, 20 | val cipherTransformation: String = "AES/ECB/PKCS5Padding") { 21 | 22 | private val algorithm = "AES" 23 | 24 | private fun buildKey(pwd: String, charset: Charset = Charsets.UTF_8): SecretKeySpec { 25 | val kgen = KeyGenerator.getInstance(algorithm) 26 | val random = SecureRandom.getInstance("SHA1PRNG", "SUN") 27 | random.setSeed(pwd.toByteArray(charset)) 28 | kgen.init(keysize, random) 29 | val secretKey = kgen.generateKey() 30 | return SecretKeySpec(secretKey.encoded, algorithm) 31 | } 32 | 33 | fun encrypt(plainBytes: ByteArray, pwd: String, charset: Charset = Charsets.UTF_8): ByteArray { 34 | val cipher = Cipher.getInstance(cipherTransformation) 35 | val key = buildKey(pwd, charset) 36 | cipher.init(Cipher.ENCRYPT_MODE, key) 37 | return cipher.doFinal(plainBytes) 38 | } 39 | 40 | fun encrypt(plainTxt: String, pwd: String, charset: Charset = Charsets.UTF_8): String { 41 | val encryptedBytes = encrypt( 42 | plainBytes = plainTxt.toByteArray(charset), 43 | pwd = pwd, 44 | charset = charset) 45 | return Base64.toBase64String(encryptedBytes) 46 | } 47 | 48 | fun decrypt(encryptedBytes: ByteArray, pwd: String, charset: Charset = Charsets.UTF_8): ByteArray { 49 | val cipher = Cipher.getInstance(cipherTransformation) 50 | val key = buildKey(pwd, charset) 51 | cipher.init(Cipher.DECRYPT_MODE, key) 52 | 53 | return cipher.doFinal(encryptedBytes) 54 | } 55 | 56 | fun decrypt(encryptedTxt: String, pwd: String, charset: Charset = Charsets.UTF_8): String { 57 | val encryptedBytes = Base64.decode(encryptedTxt) 58 | val plainBytes = decrypt(encryptedBytes, pwd, charset) 59 | return plainBytes.toString(charset) 60 | } 61 | 62 | companion object { 63 | 64 | val Aes128 = AesUtil(128) 65 | val Aes192 = AesUtil(192) 66 | val Aes256 = AesUtil(256) 67 | } 68 | } -------------------------------------------------------------------------------- /subProjects/nice-crypto/src/main/kotlin/kt/crypto/Base64.kt: -------------------------------------------------------------------------------- 1 | package kt.crypto 2 | 3 | import java.util.* 4 | 5 | fun ByteArray.encodeBase64():String{ 6 | return Base64.getEncoder().encodeToString(this) 7 | } 8 | 9 | fun String.decodeBase64():ByteArray{ 10 | return Base64.getDecoder().decode(this) 11 | } 12 | -------------------------------------------------------------------------------- /subProjects/nice-crypto/src/main/kotlin/kt/crypto/DESedeUtil.kt: -------------------------------------------------------------------------------- 1 | package kt.crypto 2 | 3 | import org.bouncycastle.util.encoders.Base64 4 | import java.nio.charset.Charset 5 | import java.security.SecureRandom 6 | import javax.crypto.Cipher 7 | import javax.crypto.KeyGenerator 8 | import javax.crypto.spec.SecretKeySpec 9 | 10 | @Suppress("DuplicatedCode", "MemberVisibilityCanBePrivate") 11 | object DESedeUtil { 12 | 13 | private const val algorithm = "DESede" 14 | private const val cipherTransformation = "DESede/ECB/PKCS5Padding" 15 | private const val keysize = 168 16 | 17 | private fun buildKey(pwd: String, charset: Charset = Charsets.UTF_8): SecretKeySpec { 18 | val kgen = KeyGenerator.getInstance(algorithm) 19 | val random = SecureRandom.getInstance("SHA1PRNG", "SUN") 20 | random.setSeed(pwd.toByteArray(charset)) 21 | kgen.init(keysize, random) 22 | val secretKey = kgen.generateKey() 23 | return SecretKeySpec(secretKey.encoded, algorithm) 24 | } 25 | 26 | fun encrypt(plainBytes: ByteArray, pwd: String, charset: Charset = Charsets.UTF_8): ByteArray { 27 | val cipher = Cipher.getInstance(cipherTransformation) 28 | val key = buildKey(pwd, charset) 29 | cipher.init(Cipher.ENCRYPT_MODE, key) 30 | return cipher.doFinal(plainBytes) 31 | } 32 | 33 | fun encrypt(plainTxt: String, pwd: String, charset: Charset = Charsets.UTF_8): String { 34 | val encryptedBytes = encrypt( 35 | plainBytes = plainTxt.toByteArray(charset), 36 | pwd = pwd, 37 | charset = charset) 38 | return Base64.toBase64String(encryptedBytes) 39 | } 40 | 41 | fun decrypt(encryptedBytes: ByteArray, pwd: String, charset: Charset = Charsets.UTF_8): ByteArray { 42 | val cipher = Cipher.getInstance(cipherTransformation) 43 | val key = buildKey(pwd, charset) 44 | cipher.init(Cipher.DECRYPT_MODE, key) 45 | 46 | return cipher.doFinal(encryptedBytes) 47 | } 48 | 49 | fun decrypt(encryptedTxt: String, pwd: String, charset: Charset = Charsets.UTF_8): String { 50 | val encryptedBytes = Base64.decode(encryptedTxt) 51 | val plainBytes = decrypt(encryptedBytes, pwd, charset) 52 | return plainBytes.toString(charset) 53 | } 54 | } -------------------------------------------------------------------------------- /subProjects/nice-log/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | kotlin("jvm") 5 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 6 | id("maven-publish") 7 | } 8 | 9 | dependencies { 10 | implementation(kotlin("stdlib-jdk8")) 11 | 12 | // android gradle依赖:implementation 和compile的区别 13 | // 参考: https://www.jianshu.com/p/f34c179bc9d0 根据需要选择使用不同的依赖设定方式 14 | api("ch.qos.logback:logback-classic:1.2.3") 15 | } 16 | 17 | tasks.register("sourcesJar") { 18 | from(sourceSets.main.get().allSource) 19 | archiveClassifier.set("sources") 20 | } 21 | 22 | publishing { 23 | publications { 24 | create("maven") { 25 | from(components["java"]) 26 | artifact(tasks["sourcesJar"]) 27 | } 28 | } 29 | 30 | val userHome = System.getProperty("user.home") 31 | 32 | repositories { 33 | var myRepo = "$userHome\\Documents\\u3dWorkspace\\NICE_Framework\\Nice-KT-Repository" 34 | System.getProperty("myRepo")?.apply { 35 | myRepo = this 36 | } 37 | maven { 38 | name = "myRepo" 39 | url = uri("file://$myRepo") 40 | } 41 | } 42 | } 43 | 44 | val compileKotlin: KotlinCompile by tasks 45 | compileKotlin.kotlinOptions { 46 | jvmTarget = "1.8" 47 | } 48 | 49 | val compileTestKotlin: KotlinCompile by tasks 50 | compileTestKotlin.kotlinOptions { 51 | jvmTarget = "1.8" 52 | } 53 | -------------------------------------------------------------------------------- /subProjects/nice-log/src/main/kotlin/kt/scaffold/tools/logger/Logger.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.tools.logger 2 | 3 | import org.slf4j.LoggerFactory 4 | 5 | @Suppress("MemberVisibilityCanBePrivate") 6 | object Logger { 7 | 8 | val appLogger = LoggerFactory.getLogger("App")!! 9 | 10 | fun trace(msg: String){ 11 | appLogger.trace(msg) 12 | } 13 | 14 | fun debug(msg: String){ 15 | appLogger.debug(msg) 16 | } 17 | 18 | fun info(msg: String){ 19 | appLogger.info(msg) 20 | } 21 | 22 | fun warn(msg: String){ 23 | appLogger.warn(msg) 24 | } 25 | 26 | fun error(msg: String){ 27 | appLogger.error(msg) 28 | } 29 | 30 | fun of(loggerName:String):org.slf4j.Logger{ 31 | return LoggerFactory.getLogger(loggerName) 32 | } 33 | 34 | fun of(clazz:Class<*>):org.slf4j.Logger{ 35 | return LoggerFactory.getLogger(clazz) 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /subProjects/nice-log/src/main/kotlin/kt/scaffold/tools/logger/conversions/ColoredLevel.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.tools.logger.conversions 2 | 3 | import ch.qos.logback.classic.Level 4 | import ch.qos.logback.classic.pattern.ClassicConverter 5 | import ch.qos.logback.classic.spi.ILoggingEvent 6 | import kt.scaffold.tools.logger.AnsiColor 7 | 8 | class ColoredLevel: ClassicConverter() { 9 | override fun convert(event: ILoggingEvent): String { 10 | return when(event.level){ 11 | Level.DEBUG -> AnsiColor.blue("debug") 12 | Level.INFO -> AnsiColor.green("info") 13 | Level.WARN -> AnsiColor.yellow("warn") 14 | Level.ERROR -> AnsiColor.red("error") 15 | else -> "" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /subProjects/nice-log/src/main/kotlin/kt/scaffold/tools/logger/conversions/ColoredMessage.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.tools.logger.conversions 2 | 3 | import ch.qos.logback.classic.Level 4 | import ch.qos.logback.classic.pattern.ClassicConverter 5 | import ch.qos.logback.classic.spi.ILoggingEvent 6 | import kt.scaffold.tools.logger.AnsiColor 7 | 8 | class ColoredMessage :ClassicConverter(){ 9 | override fun convert(event: ILoggingEvent): String { 10 | return if (useColor(event.loggerName)) { 11 | when (event.level) { 12 | Level.DEBUG -> AnsiColor.blue(event.message) 13 | Level.INFO -> AnsiColor.green(event.message) 14 | Level.WARN -> AnsiColor.yellow(event.message) 15 | Level.ERROR -> AnsiColor.red(event.message) 16 | else -> event.message 17 | } 18 | } else { 19 | event.message 20 | } 21 | } 22 | 23 | private fun useColor(loggerName:String):Boolean{ 24 | if (loggerName == "App") return true 25 | 26 | return if (this.optionList.isNullOrEmpty()){ 27 | false 28 | }else{ 29 | this.optionList.find { 30 | loggerName.startsWith("${it}.") 31 | }!=null 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /subProjects/nice-log/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | %date{HH:mm:ss.SSS} %coloredLevel [%logger] in [%thread] - %coloredMsg{com.sample}%n%xException{10} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /subProjects/nice-scaffold/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | kotlin("jvm") 5 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 6 | id("maven-publish") 7 | } 8 | 9 | val vertxVersion = "4.0.0" 10 | 11 | dependencies { 12 | api(project(":subProjects:nice-tools")) 13 | api(project(":subProjects:nice-crypto")) 14 | 15 | // android gradle依赖:implementation 和compile的区别 16 | // 参考: https://www.jianshu.com/p/f34c179bc9d0 根据需要选择使用不同的依赖设定方式 17 | 18 | api("io.vertx:vertx-core:$vertxVersion") 19 | api("io.vertx:vertx-unit:$vertxVersion") 20 | api("io.vertx:vertx-zookeeper:$vertxVersion") 21 | api("io.vertx:vertx-service-discovery:$vertxVersion") 22 | api("io.vertx:vertx-circuit-breaker:$vertxVersion") 23 | api("io.vertx:vertx-redis-client:$vertxVersion") 24 | api("io.vertx:vertx-mongo-client:$vertxVersion") 25 | api("io.vertx:vertx-dropwizard-metrics:$vertxVersion") 26 | 27 | api("io.vertx:vertx-lang-kotlin:$vertxVersion") { 28 | this.exclude(group = "org.jetbrains.kotlin") 29 | } 30 | api("io.vertx:vertx-lang-kotlin-coroutines:$vertxVersion") { 31 | this.exclude(group = "org.jetbrains.kotlin") 32 | } 33 | 34 | // 参考: https://vertx.io/docs/vertx-core/kotlin/#_native_transports 35 | // 注意, 要保持版本号和vertx依赖的 netty 的版本号一致 36 | api(group = "io.netty", name = "netty-transport-native-epoll", version = "4.1.49.Final", classifier = "linux-x86_64") 37 | api(group = "io.netty", name = "netty-transport-native-kqueue", version = "4.1.49.Final", classifier = "osx-x86_64") 38 | 39 | api("com.github.ben-manes.caffeine:caffeine:2.8.8") 40 | api("org.apache.commons:commons-pool2:2.6.2") 41 | api("com.google.guava:guava:28.2-jre") 42 | api("org.kodein.di:kodein-di-generic-jvm:6.5.1") 43 | 44 | api("com.google.protobuf:protobuf-java:3.11.3") 45 | 46 | configurations.all { 47 | this.exclude(group = "org.slf4j", module = "slf4j-log4j12") 48 | } 49 | } 50 | 51 | tasks.register("sourcesJar") { 52 | from(sourceSets.main.get().allSource) 53 | archiveClassifier.set("sources") 54 | } 55 | 56 | publishing { 57 | publications { 58 | create("maven") { 59 | from(components["java"]) 60 | artifact(tasks["sourcesJar"]) 61 | } 62 | } 63 | 64 | val userHome = System.getProperty("user.home") 65 | 66 | repositories { 67 | var myRepo = "$userHome\\Documents\\u3dWorkspace\\NICE_Framework\\Nice-KT-Repository" 68 | System.getProperty("myRepo")?.apply { 69 | myRepo = this 70 | } 71 | maven { 72 | name = "myRepo" 73 | url = uri("file://$myRepo") 74 | } 75 | } 76 | } 77 | 78 | val compileKotlin: KotlinCompile by tasks 79 | compileKotlin.kotlinOptions { 80 | jvmTarget = "1.8" 81 | } 82 | 83 | val compileTestKotlin: KotlinCompile by tasks 84 | compileTestKotlin.kotlinOptions { 85 | jvmTarget = "1.8" 86 | } 87 | 88 | -------------------------------------------------------------------------------- /subProjects/nice-scaffold/src/main/kotlin/kt/scaffold/cache/CacheManager.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.cache 2 | 3 | import com.github.benmanes.caffeine.cache.Cache 4 | import com.github.benmanes.caffeine.cache.CacheLoader 5 | import com.github.benmanes.caffeine.cache.Caffeine 6 | import com.google.common.graph.Graph 7 | import io.vertx.redis.client.Redis 8 | import io.vertx.redis.client.RedisOptions 9 | import kt.scaffold.Application 10 | import kt.scaffold.redis.RedisManager 11 | import java.util.concurrent.TimeUnit 12 | 13 | /** 14 | * 基于Caffeine 缓存管理 15 | */ 16 | object CacheManager { 17 | 18 | 19 | fun createCache(name: Key):Cache{ 20 | 21 | val cache = Caffeine.newBuilder() 22 | .maximumSize(1000) 23 | .expireAfterAccess(10,TimeUnit.SECONDS) 24 | .build(); 25 | return cache 26 | } 27 | 28 | 29 | 30 | 31 | } -------------------------------------------------------------------------------- /subProjects/nice-scaffold/src/main/kotlin/kt/scaffold/common/MicroServiceVerticle.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.common 2 | 3 | import io.vertx.circuitbreaker.CircuitBreaker 4 | import io.vertx.circuitbreaker.CircuitBreakerOptions 5 | import io.vertx.kotlin.coroutines.CoroutineVerticle 6 | import kt.scaffold.Application 7 | import kt.scaffold.net.DiscoveryManager 8 | 9 | 10 | open class MicroServiceVerticle :CoroutineVerticle(){ 11 | 12 | override suspend fun start() { 13 | 14 | } 15 | 16 | override suspend fun stop() { 17 | DiscoveryManager.unPublishAll() 18 | DiscoveryManager.close() 19 | } 20 | } -------------------------------------------------------------------------------- /subProjects/nice-scaffold/src/main/kotlin/kt/scaffold/mongo/MongoManager.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.mongo 2 | 3 | import io.vertx.core.json.JsonObject 4 | import io.vertx.ext.mongo.MongoClient 5 | import kt.scaffold.Application 6 | import kt.scaffold.tools.KtException 7 | import kt.scaffold.tools.json.toShortJson 8 | 9 | object MongoManager { 10 | 11 | private val instances = mutableMapOf() 12 | 13 | fun mongoOf(name:String):MongoClient{ 14 | return instances[name]?:createMongo(name) 15 | } 16 | 17 | private fun createMongo(name:String,shared:Boolean = true):MongoClient{ 18 | 19 | return instances.getOrPut(name){ 20 | var client: MongoClient? 21 | if(shared){ 22 | client = MongoClient.createShared( 23 | Application.vertx, 24 | optionsOf(name) 25 | ) 26 | }else{ 27 | client = MongoClient.create( 28 | Application.vertx, 29 | optionsOf(name) 30 | ) 31 | } 32 | return client 33 | } 34 | } 35 | 36 | private fun optionsOf(name:String):JsonObject{ 37 | var cfgPath = "mongo.$name" 38 | if (Application.config.hasPath(cfgPath)){ 39 | return JsonObject(Application.config.getConfig(cfgPath).root().unwrapped().toShortJson()) 40 | }else{ 41 | throw KtException("Please check application.conf, the name of mongo: [$name] does not exists.") 42 | } 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /subProjects/nice-scaffold/src/main/kotlin/kt/scaffold/redis/RedisExt.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.redis 2 | 3 | import io.vertx.kotlin.redis.client.sendAwait 4 | import io.vertx.redis.client.* 5 | 6 | suspend fun Redis.setAwait(key: String, value: ByteArray): Response? { 7 | val req = Request.cmd(Command.SET).arg(key).arg(value) 8 | return this.sendAwait(req) 9 | } 10 | 11 | suspend fun Redis.psetexAwait(key: String, value: ByteArray, expirationInMs: Long): Response? { 12 | val req = Request.cmd(Command.PSETEX).arg(key).arg(expirationInMs).arg(value) 13 | return this.sendAwait(req) 14 | } 15 | 16 | fun Redis.api(): RedisAPI { 17 | return RedisAPI.api(this) 18 | } -------------------------------------------------------------------------------- /subProjects/nice-scaffold/src/main/kotlin/kt/scaffold/redis/RedisManager.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.redis 2 | 3 | import io.vertx.core.json.JsonObject 4 | import io.vertx.kotlin.core.file.openOptionsOf 5 | import io.vertx.redis.client.Redis 6 | import io.vertx.redis.client.RedisAPI 7 | import io.vertx.redis.client.RedisOptions 8 | import kt.scaffold.Application 9 | import kt.scaffold.tools.KtException 10 | import kt.scaffold.tools.json.toShortJson 11 | 12 | object RedisManager { 13 | 14 | private val instances = mutableMapOf() 15 | 16 | fun redisOf(name: String):RedisAPI{ 17 | val redis = instances[name]?:createRedis(name) 18 | 19 | return RedisAPI.api(redis) 20 | } 21 | 22 | @Synchronized 23 | private fun createRedis(name: String):Redis{ 24 | return instances.getOrPut(name){ 25 | Redis.createClient( 26 | Application.vertx, 27 | RedisOptions(optionsOf(name))) 28 | } 29 | } 30 | 31 | private fun optionsOf(name: String):JsonObject{ 32 | var cfgPath = "redis.$name" 33 | if (Application.config.hasPath(cfgPath)){ 34 | return JsonObject(Application.config.getConfig(cfgPath).root().unwrapped().toShortJson()) 35 | }else{ 36 | throw KtException("Please check application.conf, the name of redis: [$name] does not exists.") 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /subProjects/nice-scaffold/src/main/kotlin/kt/scaffold/tools/KtException.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.tools 2 | 3 | class KtException(msg: String, cause: Throwable?) : RuntimeException(msg, cause) { 4 | 5 | constructor(ex: Exception) : this(ex.message ?: "", ex) 6 | 7 | constructor(msg: String) : this(msg, null) 8 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | kotlin("jvm") 5 | // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM. 6 | id("maven-publish") 7 | } 8 | 9 | dependencies { 10 | // api(kotlin("stdlib-jdk8")) 11 | api(kotlin("reflect")) 12 | api("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.3.9") 13 | 14 | // android gradle依赖:implementation 和compile的区别 15 | // 参考: https://www.jianshu.com/p/f34c179bc9d0 根据需要选择使用不同的依赖设定方式 16 | api(project(":subProjects:nice-log")) 17 | 18 | api("com.fasterxml.jackson.module:jackson-module-jsonSchema:2.10.2") 19 | api("com.fasterxml.jackson.module:jackson-module-kotlin:2.10.2") { 20 | this.exclude(group = "org.jetbrains.kotlin") 21 | } 22 | api("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.10.2") 23 | api("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.2") 24 | api("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.10.2") 25 | api("com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.10.2") 26 | 27 | api("com.typesafe:config:1.3.4") 28 | api("org.apache.commons:commons-lang3:3.9") 29 | api("org.jodd:jodd-util:6.0.0") 30 | 31 | // Use the Kotlin test library. 32 | testImplementation("org.jetbrains.kotlin:kotlin-test") 33 | // Use the Kotlin JUnit integration. 34 | testImplementation("org.jetbrains.kotlin:kotlin-test-junit") 35 | } 36 | 37 | tasks.register("sourcesJar") { 38 | from(sourceSets.main.get().allSource) 39 | archiveClassifier.set("sources") 40 | } 41 | 42 | publishing { 43 | publications { 44 | create("maven") { 45 | from(components["java"]) 46 | artifact(tasks["sourcesJar"]) 47 | } 48 | } 49 | 50 | val userHome = System.getProperty("user.home") 51 | 52 | repositories { 53 | var myRepo = "$userHome\\Documents\\u3dWorkspace\\NICE_Framework\\Nice-KT-Repository" 54 | System.getProperty("myRepo")?.apply { 55 | myRepo = this 56 | } 57 | maven { 58 | name = "myRepo" 59 | url = uri("file://$myRepo") 60 | } 61 | } 62 | } 63 | 64 | val compileKotlin: KotlinCompile by tasks 65 | compileKotlin.kotlinOptions { 66 | jvmTarget = "1.8" 67 | } 68 | 69 | val compileTestKotlin: KotlinCompile by tasks 70 | compileTestKotlin.kotlinOptions { 71 | jvmTarget = "1.8" 72 | } 73 | -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/math/FloatCounter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | ******************************************************************************/ 16 | 17 | package com.badlogic.gdx.math; 18 | 19 | /** Track properties of a stream of float values. The properties (total value, minimum, etc) are updated as values are 20 | * {@link #put(float)} into the stream. 21 | * 22 | * @author xoppa */ 23 | public class FloatCounter { 24 | /** The amount of values added */ 25 | public int count; 26 | /** The sum of all values */ 27 | public float total; 28 | /** The smallest value */ 29 | public float min; 30 | /** The largest value */ 31 | public float max; 32 | /** The average value (total / count) */ 33 | public float average; 34 | /** The latest raw value */ 35 | public float latest; 36 | /** The current windowed mean value */ 37 | public float value; 38 | /** Provides access to the WindowedMean if any (can be null) */ 39 | public final WindowedMean mean; 40 | 41 | /** Construct a new FloatCounter 42 | * @param windowSize The size of the mean window or 1 or below to not use a windowed mean. */ 43 | public FloatCounter (int windowSize) { 44 | mean = (windowSize > 1) ? new WindowedMean(windowSize) : null; 45 | reset(); 46 | } 47 | 48 | /** Add a value and update all fields. 49 | * @param value The value to add */ 50 | public void put (float value) { 51 | latest = value; 52 | total += value; 53 | count++; 54 | average = total / count; 55 | 56 | if (mean != null) { 57 | mean.addValue(value); 58 | this.value = mean.getMean(); 59 | } else 60 | this.value = latest; 61 | 62 | if (mean == null || mean.hasEnoughData()) { 63 | if (this.value < min) min = this.value; 64 | if (this.value > max) max = this.value; 65 | } 66 | } 67 | 68 | /** Reset all values to their default value. */ 69 | public void reset () { 70 | count = 0; 71 | total = 0f; 72 | min = Float.MAX_VALUE; 73 | max = -Float.MAX_VALUE; 74 | average = 0f; 75 | latest = 0f; 76 | value = 0f; 77 | if (mean != null) mean.clear(); 78 | } 79 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/math/Path.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | ******************************************************************************/ 16 | 17 | package com.badlogic.gdx.math; 18 | 19 | /** Interface that specifies a path of type T within the window 0.0<=t<=1.0. 20 | * @author Xoppa */ 21 | public interface Path { 22 | T derivativeAt (T out, float t); 23 | 24 | /** @return The value of the path at t where 0<=t<=1 */ 25 | T valueAt (T out, float t); 26 | 27 | /** @return The approximated value (between 0 and 1) on the path which is closest to the specified value. Note that the 28 | * implementation of this method might be optimized for speed against precision, see {@link #locate(Object)} for a more 29 | * precise (but more intensive) method. */ 30 | float approximate (T v); 31 | 32 | /** @return The precise location (between 0 and 1) on the path which is closest to the specified value. Note that the 33 | * implementation of this method might be CPU intensive, see {@link #approximate(Object)} for a faster (but less 34 | * precise) method. */ 35 | float locate (T v); 36 | 37 | 38 | /** 39 | * @param samples The amount of divisions used to approximate length. Higher values will produce more precise results, 40 | * but will be more CPU intensive. 41 | * @return An approximated length of the spline through sampling the curve and accumulating the euclidean distances between 42 | * the sample points. 43 | */ 44 | float approxLength(int samples); 45 | 46 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/math/Shape2D.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | ******************************************************************************/ 16 | 17 | package com.badlogic.gdx.math; 18 | 19 | public interface Shape2D { 20 | 21 | /** Returns whether the given point is contained within the shape. */ 22 | boolean contains (Vector2 point); 23 | 24 | /** Returns whether a point with the given coordinates is contained within the shape. */ 25 | boolean contains (float x, float y); 26 | 27 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/math/collision/Segment.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | ******************************************************************************/ 16 | 17 | package com.badlogic.gdx.math.collision; 18 | 19 | import java.io.Serializable; 20 | 21 | import com.badlogic.gdx.math.Vector3; 22 | 23 | /** A Segment is a line in 3-space having a starting and an ending position. 24 | * 25 | * @author mzechner */ 26 | public class Segment implements Serializable { 27 | private static final long serialVersionUID = 2739667069736519602L; 28 | 29 | /** the starting position **/ 30 | public final Vector3 a = new Vector3(); 31 | 32 | /** the ending position **/ 33 | public final Vector3 b = new Vector3(); 34 | 35 | /** Constructs a new Segment from the two points given. 36 | * 37 | * @param a the first point 38 | * @param b the second point */ 39 | public Segment (Vector3 a, Vector3 b) { 40 | this.a.set(a); 41 | this.b.set(b); 42 | } 43 | 44 | /** Constructs a new Segment from the two points given. 45 | * @param aX the x-coordinate of the first point 46 | * @param aY the y-coordinate of the first point 47 | * @param aZ the z-coordinate of the first point 48 | * @param bX the x-coordinate of the second point 49 | * @param bY the y-coordinate of the second point 50 | * @param bZ the z-coordinate of the second point */ 51 | public Segment (float aX, float aY, float aZ, float bX, float bY, float bZ) { 52 | this.a.set(aX, aY, aZ); 53 | this.b.set(bX, bY, bZ); 54 | } 55 | 56 | public float len () { 57 | return a.dst(b); 58 | } 59 | 60 | public float len2 () { 61 | return a.dst2(b); 62 | } 63 | 64 | @Override 65 | public boolean equals (Object o) { 66 | if (o == this) return true; 67 | if (o == null || o.getClass() != this.getClass()) return false; 68 | Segment s = (Segment)o; 69 | return this.a.equals(s.a) && this.b.equals(s.b); 70 | } 71 | 72 | @Override 73 | public int hashCode () { 74 | final int prime = 71; 75 | int result = 1; 76 | result = prime * result + this.a.hashCode(); 77 | result = prime * result + this.b.hashCode(); 78 | return result; 79 | } 80 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/math/collision/Sphere.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | ******************************************************************************/ 16 | 17 | package com.badlogic.gdx.math.collision; 18 | 19 | import java.io.Serializable; 20 | 21 | import com.badlogic.gdx.math.MathUtils; 22 | import com.badlogic.gdx.math.Vector3; 23 | import com.badlogic.gdx.utils.NumberUtils; 24 | 25 | /** Encapsulates a 3D sphere with a center and a radius 26 | * 27 | * @author badlogicgames@gmail.com */ 28 | public class Sphere implements Serializable { 29 | private static final long serialVersionUID = -6487336868908521596L; 30 | /** the radius of the sphere **/ 31 | public float radius; 32 | /** the center of the sphere **/ 33 | public final Vector3 center; 34 | 35 | private static final float PI_4_3 = MathUtils.PI * 4f / 3f; 36 | 37 | /** Constructs a sphere with the given center and radius 38 | * @param center The center 39 | * @param radius The radius */ 40 | public Sphere (Vector3 center, float radius) { 41 | this.center = new Vector3(center); 42 | this.radius = radius; 43 | } 44 | 45 | /** @param sphere the other sphere 46 | * @return whether this and the other sphere overlap */ 47 | public boolean overlaps (Sphere sphere) { 48 | return center.dst2(sphere.center) < (radius + sphere.radius) * (radius + sphere.radius); 49 | } 50 | 51 | @Override 52 | public int hashCode () { 53 | final int prime = 71; 54 | int result = 1; 55 | result = prime * result + this.center.hashCode(); 56 | result = prime * result + NumberUtils.floatToRawIntBits(this.radius); 57 | return result; 58 | } 59 | 60 | @Override 61 | public boolean equals (Object o) { 62 | if (this == o) return true; 63 | if (o == null || o.getClass() != this.getClass()) return false; 64 | Sphere s = (Sphere)o; 65 | return this.radius == s.radius && this.center.equals(s.center); 66 | } 67 | 68 | public float volume () { 69 | return PI_4_3 * this.radius * this.radius * this.radius; 70 | } 71 | 72 | public float surfaceArea () { 73 | return 4 * MathUtils.PI * this.radius * this.radius; 74 | } 75 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/utils/Collections.java: -------------------------------------------------------------------------------- 1 | package com.badlogic.gdx.utils; 2 | 3 | public class Collections { 4 | 5 | /** When true, {@link Iterable#iterator()} for {@link Array}, {@link ObjectMap}, and other collections will allocate a new 6 | * iterator for each invocation. When false, the iterator is reused and nested use will throw an exception. Default is 7 | * false. */ 8 | public static boolean allocateIterators; 9 | 10 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/utils/GdxRuntimeException.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | ******************************************************************************/ 16 | 17 | package com.badlogic.gdx.utils; 18 | 19 | /** Typed runtime exception used throughout libgdx 20 | * 21 | * @author mzechner */ 22 | public class GdxRuntimeException extends RuntimeException { 23 | private static final long serialVersionUID = 6735854402467673117L; 24 | 25 | public GdxRuntimeException (String message) { 26 | super(message); 27 | } 28 | 29 | public GdxRuntimeException (Throwable t) { 30 | super(t); 31 | } 32 | 33 | public GdxRuntimeException (String message, Throwable t) { 34 | super(message, t); 35 | } 36 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/utils/Null.java: -------------------------------------------------------------------------------- 1 | package com.badlogic.gdx.utils; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Target; 6 | 7 | /** An element with this annotation claims that the element may have a {@code null} value. Apart from documentation purposes this 8 | * annotation is intended to be used by static analysis tools to validate against probable runtime errors or contract violations. 9 | * @author maltaisn */ 10 | @Documented 11 | @Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE}) 12 | public @interface Null { 13 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/utils/NumberUtils.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | ******************************************************************************/ 16 | 17 | package com.badlogic.gdx.utils; 18 | 19 | public final class NumberUtils { 20 | public static int floatToIntBits (float value) { 21 | return Float.floatToIntBits(value); 22 | } 23 | 24 | public static int floatToRawIntBits (float value) { 25 | return Float.floatToRawIntBits(value); 26 | } 27 | 28 | /** Converts the color from a float ABGR encoding to an int ABGR encoding. The alpha is expanded from 0-254 in the float 29 | * encoding (see {@link #intToFloatColor(int)}) to 0-255, which means converting from int to float and back to int can be 30 | * lossy. */ 31 | public static int floatToIntColor (float value) { 32 | int intBits = Float.floatToRawIntBits(value); 33 | intBits |= (int)((intBits >>> 24) * (255f / 254f)) << 24; 34 | return intBits; 35 | } 36 | 37 | /** Encodes the ABGR int color as a float. The alpha is compressed to use only even numbers between 0-254 to avoid using bits 38 | * in the NaN range (see {@link Float#intBitsToFloat(int)} javadocs). Rendering which uses colors encoded as floats should 39 | * expand the 0-254 back to 0-255, else colors cannot be fully opaque. */ 40 | public static float intToFloatColor (int value) { 41 | return Float.intBitsToFloat(value & 0xfeffffff); 42 | } 43 | 44 | public static float intBitsToFloat (int value) { 45 | return Float.intBitsToFloat(value); 46 | } 47 | 48 | public static long doubleToLongBits (double value) { 49 | return Double.doubleToLongBits(value); 50 | } 51 | 52 | public static double longBitsToDouble (long value) { 53 | return Double.longBitsToDouble(value); 54 | } 55 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/utils/ReflectionPool.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | ******************************************************************************/ 16 | 17 | package com.badlogic.gdx.utils; 18 | 19 | import com.badlogic.gdx.utils.reflect.ClassReflection; 20 | import com.badlogic.gdx.utils.reflect.Constructor; 21 | import com.badlogic.gdx.utils.reflect.ReflectionException; 22 | 23 | /** Pool that creates new instances of a type using reflection. The type must have a zero argument constructor. 24 | * {@link Constructor#setAccessible(boolean)} will be used if the class and/or constructor is not visible. 25 | * @author Nathan Sweet */ 26 | public class ReflectionPool extends Pool { 27 | private final Constructor constructor; 28 | 29 | public ReflectionPool (Class type) { 30 | this(type, 16, Integer.MAX_VALUE); 31 | } 32 | 33 | public ReflectionPool (Class type, int initialCapacity) { 34 | this(type, initialCapacity, Integer.MAX_VALUE); 35 | } 36 | 37 | public ReflectionPool (Class type, int initialCapacity, int max) { 38 | super(initialCapacity, max); 39 | constructor = findConstructor(type); 40 | if (constructor == null) 41 | throw new RuntimeException("Class cannot be created (missing no-arg constructor): " + type.getName()); 42 | } 43 | 44 | private @Null Constructor findConstructor (Class type) { 45 | try { 46 | return ClassReflection.getConstructor(type, (Class[])null); 47 | } catch (Exception ex1) { 48 | try { 49 | Constructor constructor = ClassReflection.getDeclaredConstructor(type, (Class[])null); 50 | constructor.setAccessible(true); 51 | return constructor; 52 | } catch (ReflectionException ex2) { 53 | return null; 54 | } 55 | } 56 | } 57 | 58 | protected T newObject () { 59 | try { 60 | return (T)constructor.newInstance((Object[])null); 61 | } catch (Exception ex) { 62 | throw new GdxRuntimeException("Unable to create new instance: " + constructor.getDeclaringClass().getName(), ex); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/utils/Sort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the 5 | * License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" 10 | * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | */ 13 | 14 | package com.badlogic.gdx.utils; 15 | 16 | import java.util.Comparator; 17 | 18 | /** Provides methods to sort arrays of objects. Sorting requires working memory and this class allows that memory to be reused to 19 | * avoid allocation. The sorting is otherwise identical to the Arrays.sort methods (uses timsort).
20 | *
21 | * Note that sorting primitive arrays with the Arrays.sort methods does not allocate memory (unless sorting large arrays of char, 22 | * short, or byte). 23 | * @author Nathan Sweet */ 24 | public class Sort { 25 | static private Sort instance; 26 | 27 | private TimSort timSort; 28 | private ComparableTimSort comparableTimSort; 29 | 30 | public void sort (Array a) { 31 | if (comparableTimSort == null) comparableTimSort = new ComparableTimSort(); 32 | comparableTimSort.doSort(a.items, 0, a.size); 33 | } 34 | 35 | /** The specified objects must implement {@link Comparable}. */ 36 | public void sort (Object[] a) { 37 | if (comparableTimSort == null) comparableTimSort = new ComparableTimSort(); 38 | comparableTimSort.doSort(a, 0, a.length); 39 | } 40 | 41 | /** The specified objects must implement {@link Comparable}. */ 42 | public void sort (Object[] a, int fromIndex, int toIndex) { 43 | if (comparableTimSort == null) comparableTimSort = new ComparableTimSort(); 44 | comparableTimSort.doSort(a, fromIndex, toIndex); 45 | } 46 | 47 | public void sort (Array a, Comparator c) { 48 | if (timSort == null) timSort = new TimSort(); 49 | timSort.doSort(a.items, c, 0, a.size); 50 | } 51 | 52 | public void sort (T[] a, Comparator c) { 53 | if (timSort == null) timSort = new TimSort(); 54 | timSort.doSort(a, c, 0, a.length); 55 | } 56 | 57 | public void sort (T[] a, Comparator c, int fromIndex, int toIndex) { 58 | if (timSort == null) timSort = new TimSort(); 59 | timSort.doSort(a, c, fromIndex, toIndex); 60 | } 61 | 62 | /** Returns a Sort instance for convenience. Multiple threads must not use this instance at the same time. */ 63 | static public Sort instance () { 64 | if (instance == null) instance = new Sort(); 65 | return instance; 66 | } 67 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/utils/reflect/Annotation.java: -------------------------------------------------------------------------------- 1 | package com.badlogic.gdx.utils.reflect; 2 | 3 | /** Provides information about, and access to, an annotation of a field, class or interface. 4 | * @author dludwig */ 5 | public final class Annotation { 6 | 7 | private java.lang.annotation.Annotation annotation; 8 | 9 | Annotation (java.lang.annotation.Annotation annotation) { 10 | this.annotation = annotation; 11 | } 12 | 13 | @SuppressWarnings("unchecked") 14 | public T getAnnotation (Class annotationType) { 15 | if (annotation.annotationType().equals(annotationType)) { 16 | return (T) annotation; 17 | } 18 | return null; 19 | } 20 | 21 | public Class getAnnotationType () { 22 | return annotation.annotationType(); 23 | } 24 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/utils/reflect/ArrayReflection.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | ******************************************************************************/ 16 | 17 | package com.badlogic.gdx.utils.reflect; 18 | 19 | /** Utilities for Array reflection. 20 | * @author nexsoftware */ 21 | public final class ArrayReflection { 22 | 23 | /** Creates a new array with the specified component type and length. */ 24 | static public Object newInstance (Class c, int size) { 25 | return java.lang.reflect.Array.newInstance(c, size); 26 | } 27 | 28 | /** Returns the length of the supplied array. */ 29 | static public int getLength (Object array) { 30 | return java.lang.reflect.Array.getLength(array); 31 | } 32 | 33 | /** Returns the value of the indexed component in the supplied array. */ 34 | static public Object get (Object array, int index) { 35 | return java.lang.reflect.Array.get(array, index); 36 | } 37 | 38 | /** Sets the value of the indexed component in the supplied array to the supplied value. */ 39 | static public void set (Object array, int index, Object value) { 40 | java.lang.reflect.Array.set(array, index, value); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/java/com/badlogic/gdx/utils/reflect/ReflectionException.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011 See AUTHORS file. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | ******************************************************************************/ 16 | 17 | package com.badlogic.gdx.utils.reflect; 18 | 19 | /** Thrown when an exception occurs during reflection. 20 | * @author nexsoftware */ 21 | public class ReflectionException extends Exception { 22 | 23 | public ReflectionException () { 24 | super(); 25 | } 26 | 27 | public ReflectionException (String message) { 28 | super(message); 29 | } 30 | 31 | public ReflectionException (Throwable cause) { 32 | super(cause); 33 | } 34 | 35 | public ReflectionException (String message, Throwable cause) { 36 | super(message, cause); 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/kotlin/kt/coroutines/AutoThreadLocalElement.kt: -------------------------------------------------------------------------------- 1 | package kt.coroutines 2 | 3 | import kotlinx.coroutines.ThreadContextElement 4 | import kotlin.coroutines.CoroutineContext 5 | import kotlin.coroutines.EmptyCoroutineContext 6 | 7 | private data class ThreadLocalKey(private val threadLocal: ThreadLocal<*>) : CoroutineContext.Key> 8 | 9 | class AutoThreadLocalElement( 10 | private var value: T, 11 | private val threadLocal: ThreadLocal 12 | ) : ThreadContextElement { 13 | override val key: CoroutineContext.Key<*> = ThreadLocalKey(threadLocal) 14 | 15 | @Suppress("UNCHECKED_CAST") 16 | override fun updateThreadContext(context: CoroutineContext): T { 17 | // val oldState = threadLocal.get() 18 | threadLocal.set(value) 19 | 20 | return null as T 21 | } 22 | 23 | override fun restoreThreadContext(context: CoroutineContext, oldState: T) { 24 | value = threadLocal.get() 25 | threadLocal.remove() 26 | } 27 | 28 | // this method is overridden to perform value comparison (==) on key 29 | override fun minusKey(key: CoroutineContext.Key<*>): CoroutineContext { 30 | return if (this.key == key) EmptyCoroutineContext else this 31 | } 32 | 33 | // this method is overridden to perform value comparison (==) on key 34 | override operator fun get(key: CoroutineContext.Key): E? = 35 | @Suppress("UNCHECKED_CAST") 36 | if (this.key == key) this as E else null 37 | 38 | override fun toString(): String = "ThreadLocal(value=$value, threadLocal = $threadLocal)" 39 | } 40 | 41 | fun ThreadLocal.asAutoContextElement(value: T = get()): AutoThreadLocalElement = 42 | AutoThreadLocalElement(value, this) 43 | -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/kotlin/kt/date/kxdate.kt: -------------------------------------------------------------------------------- 1 | package kt.date 2 | 3 | import java.time.Duration 4 | import java.time.LocalDate 5 | import java.time.LocalDateTime 6 | import java.time.Period 7 | 8 | object ago 9 | 10 | object fromNow 11 | 12 | val Int.nanoseconds: Duration 13 | get() = Duration.ofNanos(toLong()) 14 | 15 | val Int.microseconds: Duration 16 | get() = Duration.ofNanos(toLong() * 1000L) 17 | 18 | val Int.milliseconds: Duration 19 | get() = Duration.ofMillis(toLong()) 20 | 21 | val Int.seconds: Duration 22 | get() = Duration.ofSeconds(toLong()) 23 | 24 | val Int.minutes: Duration 25 | get() = Duration.ofMinutes(toLong()) 26 | 27 | val Int.hours: Duration 28 | get() = Duration.ofHours(toLong()) 29 | 30 | val Int.days: Period 31 | get() = Period.ofDays(this) 32 | 33 | val Int.weeks: Period 34 | get() = Period.ofWeeks(this) 35 | 36 | val Int.months: Period 37 | get() = Period.ofMonths(this) 38 | 39 | val Int.years: Period 40 | get() = Period.ofYears(this) 41 | 42 | val Duration.ago: LocalDateTime 43 | get() = baseTime() - this 44 | 45 | val Duration.fromNow: LocalDateTime 46 | get() = baseTime() + this 47 | 48 | val Period.ago: LocalDate 49 | get() = baseDate() - this 50 | 51 | val Period.fromNow: LocalDate 52 | get() = baseDate() + this 53 | 54 | infix fun Int.nanoseconds(fromNow: fromNow) = baseTime().plusNanos(toLong()) 55 | 56 | infix fun Int.nanoseconds(ago: ago) = baseTime().minusNanos(toLong()) 57 | 58 | infix fun Int.microseconds(fromNow: fromNow) = baseTime().plusNanos(1000L * toLong()) 59 | 60 | infix fun Int.microseconds(ago: ago) = baseTime().minusNanos(1000L * toLong()) 61 | 62 | infix fun Int.milliseconds(fromNow: fromNow) = baseTime().plusNanos(1000000L * toLong()) 63 | 64 | infix fun Int.milliseconds(ago: ago) = baseTime().minusNanos(1000000L * toLong()) 65 | 66 | infix fun Int.seconds(fromNow: fromNow) = baseTime().plusSeconds(toLong()) 67 | 68 | infix fun Int.seconds(ago: ago) = baseTime().minusSeconds(toLong()) 69 | 70 | infix fun Int.minutes(fromNow: fromNow) = baseTime().plusMinutes(toLong()) 71 | 72 | infix fun Int.minutes(ago: ago) = baseTime().minusMinutes(toLong()) 73 | 74 | infix fun Int.hours(fromNow: fromNow) = baseTime().plusHours(toLong()) 75 | 76 | infix fun Int.hours(ago: ago) = baseTime().minusHours(toLong()) 77 | 78 | infix fun Int.days(fromNow: fromNow) = baseDate().plusDays(toLong()) 79 | 80 | infix fun Int.days(ago: ago) = baseDate().minusDays(toLong()) 81 | 82 | infix fun Int.weeks(fromNow: fromNow) = baseDate().plusWeeks(toLong()) 83 | 84 | infix fun Int.weeks(ago: ago) = baseDate().minusWeeks(toLong()) 85 | 86 | infix fun Int.months(fromNow: fromNow) = baseDate().plusMonths(toLong()) 87 | 88 | infix fun Int.months(ago: ago) = baseDate().minusMonths(toLong()) 89 | 90 | infix fun Int.years(fromNow: fromNow) = baseDate().plusYears(toLong()) 91 | 92 | infix fun Int.years(ago: ago) = baseDate().minusYears(toLong()) 93 | 94 | private fun baseDate() = LocalDate.now() 95 | 96 | private fun baseTime() = LocalDateTime.now() -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/kotlin/kt/objectPool/PoolConfig.kt: -------------------------------------------------------------------------------- 1 | package kt.objectPool 2 | 3 | class PoolConfig( 4 | // 数量控制参数 5 | // 对象池中最大对象数,默认为8 6 | val maxTotal: Int = 8, 7 | // 对象池中最大空闲的对象数,默认也为8 8 | val maxIdle: Int = 8, 9 | // 对象池中最少空闲的对象数,默认为 -1 10 | val minIdle: Int = -1, 11 | // 驱逐检测的间隔时间, 默认10分钟 12 | val timeBetweenEvictionRunsSeconds: Int = 600, 13 | // 从对象池里借对象时的超时时间, 拍脑袋决定默认值 2000 ms 14 | // 设置为 0 或者负数的时候, 表示不进行超时控制 15 | val borrowTimeoutMs: Long = 2000 16 | ) -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/kotlin/kt/objectPool/PooledObject.kt: -------------------------------------------------------------------------------- 1 | package kt.objectPool 2 | 3 | import java.io.Closeable 4 | import java.time.Instant 5 | 6 | @Suppress("MemberVisibilityCanBePrivate") 7 | class PooledObject(val target: T, private val pool: ObjectPool) : Closeable { 8 | 9 | internal var status = PooledObjectStatus.Idle 10 | internal val createTime = Instant.now() 11 | internal var lastBorrowTime = createTime 12 | internal var lastReturnTime = createTime 13 | 14 | private var _broken = false 15 | 16 | val broken: Boolean 17 | get() = _broken 18 | 19 | fun markBroken() { 20 | _broken = true 21 | } 22 | 23 | val identityHashCode: Int by lazy { 24 | System.identityHashCode(target) 25 | } 26 | 27 | override fun close() { 28 | if (status == PooledObjectStatus.Using) { 29 | status = PooledObjectStatus.Returning 30 | pool.returnObject(this) 31 | } 32 | } 33 | 34 | override fun toString(): String { 35 | val buf = StringBuilder() 36 | buf.appendLine("PooledObject:") 37 | buf.appendLine(" identityHashCode: $identityHashCode") 38 | buf.appendLine(" target type: ${target.javaClass.name}") 39 | buf.appendLine(" status: ${status.name}") 40 | buf.appendLine(" createTime: ${createTime}") 41 | buf.appendLine(" lastBorrowTime: ${lastBorrowTime}") 42 | buf.appendLine(" lastReturnTime: ${lastReturnTime}") 43 | buf.appendLine(" isBroken: $broken") 44 | 45 | return buf.toString() 46 | } 47 | } 48 | 49 | enum class PooledObjectStatus { 50 | Idle, 51 | Using, 52 | Returning, 53 | Broken, 54 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/kotlin/kt/objectPool/PooledObjectFactory.kt: -------------------------------------------------------------------------------- 1 | package kt.objectPool 2 | 3 | import kt.scaffold.tools.logger.Logger 4 | 5 | abstract class PooledObjectFactory { 6 | 7 | abstract suspend fun createObjectAwait(): T 8 | 9 | open suspend fun wrapObject(pool: ObjectPool): PooledObject? { 10 | try { 11 | val obj = createObjectAwait() 12 | return PooledObject(target = obj, pool = pool) 13 | } catch (ex: Exception) { 14 | Logger.warn("Create ${this.javaClass.name} object failed.\n$ex") 15 | return null 16 | } 17 | 18 | } 19 | 20 | open fun destoryObject(target: T) { 21 | // Logger.debug("Destory pooled object: [${System.identityHashCode(obj)}]") 22 | } 23 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/kotlin/kt/scaffold/ext/ConfigExt.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.ext 2 | 3 | import com.typesafe.config.Config 4 | 5 | 6 | fun Config.getStringOrElse(path: String, defaultValue: String): String { 7 | if (this.hasPath(path)) { 8 | val v = this.getString(path) 9 | if (v.isNullOrBlank()) { 10 | return defaultValue 11 | } else { 12 | return v 13 | } 14 | } else { 15 | return defaultValue 16 | } 17 | } 18 | 19 | fun Config.getStringListOrEmpty(path: String): List { 20 | if (this.hasPath(path)) { 21 | return this.getStringList(path) 22 | } else { 23 | return listOf() 24 | } 25 | } 26 | 27 | fun Config.getStringOrNll(path: String):String? { 28 | return if (this.hasPath(path)) { 29 | this.getString(path) 30 | } else { 31 | null 32 | } 33 | } 34 | 35 | fun Config.getIntOrElse(path: String, defaultValue: Int): Int { 36 | if (this.hasPath(path)) { 37 | return this.getInt(path) 38 | } else { 39 | return defaultValue 40 | } 41 | } 42 | 43 | fun Config.getLongOrElse(path: String, defaultValue: Long): Long { 44 | if (this.hasPath(path)) { 45 | return this.getLong(path) 46 | } else { 47 | return defaultValue 48 | } 49 | } 50 | 51 | fun Config.getBooleanOrElse(path: String, defaultValue: Boolean): Boolean { 52 | if (this.hasPath(path)) { 53 | return this.getBoolean(path) 54 | } else { 55 | return defaultValue 56 | } 57 | } 58 | 59 | fun Config.existThenApply(path: String, block: ()->Unit) { 60 | if (this.hasPath(path)) { 61 | block() 62 | } 63 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/kotlin/kt/scaffold/ext/LoggerExt.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.ext 2 | 3 | import kt.scaffold.tools.json.toShortJson 4 | import org.slf4j.Logger 5 | import kt.scaffold.tools.logger.Logger as KtLogger 6 | 7 | fun Logger.trace(item: Any) { 8 | this.trace(item.toShortJson()) 9 | } 10 | 11 | fun Logger.debug(item: Any) { 12 | this.debug(item.toShortJson()) 13 | } 14 | 15 | fun Logger.info(item: Any) { 16 | this.info(item.toShortJson()) 17 | } 18 | 19 | fun Logger.warn(item: Any) { 20 | this.warn(item.toShortJson()) 21 | } 22 | 23 | fun Logger.error(item: Any) { 24 | this.error(item.toShortJson()) 25 | } 26 | 27 | fun KtLogger.trace(item: Any) { 28 | appLogger.trace(item) 29 | } 30 | 31 | fun KtLogger.debug(item: Any) { 32 | appLogger.debug(item) 33 | } 34 | 35 | fun KtLogger.info(item: Any) { 36 | appLogger.info(item) 37 | } 38 | 39 | fun KtLogger.warn(item: Any) { 40 | appLogger.warn(item) 41 | } 42 | 43 | fun KtLogger.error(item: Any) { 44 | appLogger.error(item) 45 | } 46 | 47 | -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/kotlin/kt/scaffold/tools/csv/CSV.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.tools.csv 2 | 3 | import com.fasterxml.jackson.databind.module.SimpleModule 4 | import com.fasterxml.jackson.dataformat.csv.CsvMapper 5 | import com.fasterxml.jackson.datatype.jdk8.Jdk8Module 6 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule 7 | import com.fasterxml.jackson.module.kotlin.registerKotlinModule 8 | import java.io.File 9 | import java.io.FileOutputStream 10 | 11 | object CSV { 12 | 13 | val mapper = CsvMapper() 14 | 15 | init { 16 | val JDateTimeModule = SimpleModule("CustomTypeModule") 17 | 18 | mapper.registerKotlinModule() 19 | .registerModule(Jdk8Module()) 20 | .registerModule(JavaTimeModule()) 21 | .registerModule(JDateTimeModule) 22 | } 23 | 24 | fun saveToFile(csvFile: File, beans: List<*>, clazz: Class<*>, append: Boolean = false) { 25 | val csvSchema = mapper.schemaFor(clazz) 26 | val needWriteHeader = append.not() || csvFile.exists().not() || csvFile.length() == 0L 27 | 28 | val fos = FileOutputStream(csvFile, append).buffered() 29 | 30 | val objw = if (needWriteHeader) { 31 | mapper.writerFor(clazz).with(csvSchema.withHeader()).writeValues(fos) 32 | } else { 33 | mapper.writerFor(clazz).with(csvSchema).writeValues(fos) 34 | } 35 | 36 | objw.use { 37 | objw.writeAll(beans) 38 | } 39 | } 40 | 41 | inline fun saveToFile(csvFilePath: String, beans: List, append: Boolean = false) { 42 | saveToFile(File(csvFilePath), beans, T::class.java, append) 43 | } 44 | 45 | inline fun saveToFile(csvFileh: File, beans: List, append: Boolean = false) { 46 | saveToFile(csvFileh, beans, T::class.java, append) 47 | } 48 | 49 | inline fun loadFromFile(csvFile: File): List { 50 | val csvSchema = mapper.schemaFor(T::class.java).withHeader() 51 | 52 | val it = mapper.readerFor(T::class.java).with(csvSchema).readValues(csvFile.bufferedReader()) 53 | return it.readAll() 54 | } 55 | 56 | inline fun loadFromFile(csvFilePath: String): List { 57 | return loadFromFile(File(csvFilePath)) 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/main/kotlin/kt/scaffold/tools/json/JsonExt.kt: -------------------------------------------------------------------------------- 1 | package kt.scaffold.tools.json 2 | 3 | import com.fasterxml.jackson.core.type.TypeReference 4 | import com.fasterxml.jackson.databind.JsonNode 5 | 6 | 7 | fun Any.toJsonPretty(): String { 8 | if (this is String) return this 9 | return Json.toJsonStrPretty(this) 10 | } 11 | 12 | /** 13 | * 把对象序列化成单行json字符串, 并且忽略其中为空的字段(包括 null, 空字符串, 空列表, 空map) 14 | */ 15 | fun Any.toShortJson(): String { 16 | if (this is String) return this 17 | return Json.toJsonExcludeEmptyFields(this) 18 | } 19 | 20 | /** 21 | * 把对象序列化成单行json字符串 22 | */ 23 | fun Any.singleLineJson(): String { 24 | if (this is String) return this 25 | return Json.toJsonStr(this) 26 | } 27 | 28 | fun String.toJsonNode(): JsonNode { 29 | return Json.parse(this) 30 | } 31 | 32 | fun JsonNode.toObj(clazz: Class): A { 33 | return Json.fromJsonNode(this, clazz) 34 | } 35 | 36 | /** 37 | * 将JsonNode对象转换成指定类型的Bean对象 38 | */ 39 | inline fun JsonNode.toBean(): T { 40 | return this.toJsonPretty().toBean() 41 | } 42 | 43 | /** 44 | * 将json字符串转换成指定类型的Bean对象 45 | */ 46 | inline fun String.toBean(): T { 47 | return Json.mapper.readValue(this, object : TypeReference() {}) 48 | } 49 | 50 | inline fun String.toBeanList(): List { 51 | return Json.mapper.readValue(this, object : TypeReference>() {}) 52 | } 53 | 54 | inline fun String.toBeanMap(): Map { 55 | return Json.mapper.readValue(this, object : TypeReference>() {}) 56 | } 57 | 58 | inline fun String.toMutableMap(): MutableMap { 59 | return Json.mapper.readValue(this, object : TypeReference>() {}) 60 | } -------------------------------------------------------------------------------- /subProjects/nice-tools/src/test/kotlin/ExpressionParserTest.kt: -------------------------------------------------------------------------------- 1 | import kt.scaffold.tools.ExpressionParser 2 | import kt.scaffold.tools.logger.Logger 3 | import org.junit.After 4 | import org.junit.Before 5 | import org.junit.Test 6 | 7 | class ExpressionParserTest { 8 | @Before 9 | fun setUp(){ 10 | 11 | } 12 | 13 | @After 14 | fun tearDown(){ 15 | 16 | } 17 | 18 | @Test 19 | fun testHealPoint(){ 20 | 21 | val parser = ExpressionParser() 22 | val exp = parser.evaluteExpression("(5+3)*8^2-5*(-2)") 23 | Logger.debug(" = ${exp.value}") 24 | 25 | 26 | val exp2 = parser.evaluteExpression("sin(x*PI/180)") 27 | exp2.parameters["x"]!!.value = 45.0 28 | Logger.debug("Sin(45)= ${exp2.value}") 29 | 30 | 31 | val sinFunc = exp2.toDelegate("x") 32 | Logger.debug("Sin(90)= ${sinFunc(arrayOf(90.0))}") 33 | 34 | val exp3 = parser.evaluteExpression("sin(angle/180*PI) * length,cos(angle/180*PI) * length") 35 | val f = exp3.toMultiResultDelegate("angle", "length") 36 | val res = f(arrayOf(30.0,1.0)) 37 | 38 | 39 | 40 | parser.addFunc("test"){ p-> 41 | Logger.debug("Test: ${p.size}") 42 | return@addFunc 42.0 43 | } 44 | Logger.debug("Result : ${parser.evaluate("2*test(1,5)")}") 45 | 46 | 47 | parser.addConst("meaningOfLife"){ 42.0} 48 | Logger.debug("Result: ${parser.evaluate("2*meaningOfLife")}") 49 | 50 | 51 | val exp4 = parser.evaluteExpression("攻击力*2 +100 + 防御力*10") 52 | exp4.parameters["攻击力"]!!.value = 10.0 53 | exp4.parameters["防御力"]!!.value = 20.0 54 | Logger.debug("攻击力: ${exp4.value}") 55 | } 56 | 57 | 58 | } --------------------------------------------------------------------------------