mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-12 21:02:26 +08:00
init commit
This commit is contained in:
7
service/annie-user-api/entity/test_entity.go
Normal file
7
service/annie-user-api/entity/test_entity.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package entity
|
||||
|
||||
type TestEntity struct {
|
||||
ID uint64
|
||||
Name string
|
||||
Age int64
|
||||
}
|
||||
8
service/annie-user-api/entity/user_entity.go
Normal file
8
service/annie-user-api/entity/user_entity.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package entity
|
||||
|
||||
type User struct {
|
||||
Uid uint64
|
||||
Username string
|
||||
Password string
|
||||
IsAdmin bool
|
||||
}
|
||||
3
service/annie-user-api/go.mod
Normal file
3
service/annie-user-api/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module annie-user-api
|
||||
|
||||
go 1.19
|
||||
17
service/annie-user/cmd/application.toml
Normal file
17
service/annie-user/cmd/application.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
http_port = 9002
|
||||
|
||||
[logger]
|
||||
level = "DEBUG"
|
||||
method = "CONSOLE"
|
||||
track_line = true
|
||||
|
||||
[air]
|
||||
addr = "air"
|
||||
port = 8086
|
||||
service_name = "annie-user-app"
|
||||
|
||||
[database]
|
||||
url = "root:flswld@(mysql:3306)/annie_user?charset=utf8&parseTime=True&loc=Local"
|
||||
|
||||
[light]
|
||||
port = 10003
|
||||
58
service/annie-user/cmd/main.go
Normal file
58
service/annie-user/cmd/main.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"annie-user/controller"
|
||||
"annie-user/dao"
|
||||
"annie-user/service"
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/light"
|
||||
"flswld.com/logger"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filePath := "./application.toml"
|
||||
config.InitConfig(filePath)
|
||||
|
||||
logger.InitLogger()
|
||||
logger.LOG.Info("user start")
|
||||
|
||||
httpProvider := light.NewHttpProvider()
|
||||
|
||||
db := dao.NewDao()
|
||||
|
||||
svc := service.NewService(db)
|
||||
rpcSvc := service.NewRpcService(db, svc)
|
||||
|
||||
rpcProvider := light.NewRpcProvider(rpcSvc)
|
||||
|
||||
// 认证服务
|
||||
rpcWaterAuthConsumer := light.NewRpcConsumer("water-auth")
|
||||
|
||||
rpcHk4eGatewayConsumer := light.NewRpcConsumer("hk4e-gateway")
|
||||
|
||||
_ = controller.NewController(svc, rpcWaterAuthConsumer, rpcHk4eGatewayConsumer)
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
|
||||
for {
|
||||
s := <-c
|
||||
logger.LOG.Info("get a signal %s", s.String())
|
||||
switch s {
|
||||
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
|
||||
rpcProvider.CloseRpcProvider()
|
||||
db.CloseDao()
|
||||
rpcWaterAuthConsumer.CloseRpcConsumer()
|
||||
httpProvider.CloseHttpProvider()
|
||||
logger.LOG.Info("user exit")
|
||||
time.Sleep(time.Second)
|
||||
return
|
||||
case syscall.SIGHUP:
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
34
service/annie-user/controller/admin_controller.go
Normal file
34
service/annie-user/controller/admin_controller.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
apiEntity "annie-user/entity/api"
|
||||
"flswld.com/common/entity/dto"
|
||||
waterAuth "flswld.com/water-api/auth"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (c *Controller) queryUserByUsername(context *gin.Context) {
|
||||
accessToken := c.getAccessToken(context)
|
||||
user, err := waterAuth.WaterQueryUserByAccessToken(c.rpcWaterAuthConsumer, accessToken)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(1001, "服务器内部错误", nil))
|
||||
return
|
||||
}
|
||||
if !user.IsAdmin {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10001, "没有访问权限", nil))
|
||||
return
|
||||
}
|
||||
username := context.Query("username")
|
||||
userQuery := c.service.QueryUserByUsername(username)
|
||||
if userQuery == nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "未查询到用户", nil))
|
||||
return
|
||||
}
|
||||
userRet := new(apiEntity.User)
|
||||
userRet.Uid = userQuery.Uid
|
||||
userRet.Username = userQuery.Username
|
||||
userRet.Password = userQuery.Password
|
||||
userRet.IsAdmin = userQuery.IsAdmin
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(0, "查询用户成功", userRet))
|
||||
}
|
||||
78
service/annie-user/controller/controller.go
Normal file
78
service/annie-user/controller/controller.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"annie-user/service"
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/light"
|
||||
waterAuth "flswld.com/water-api/auth"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
service *service.Service
|
||||
rpcWaterAuthConsumer *light.Consumer
|
||||
rpcHk4eGatewayConsumer *light.Consumer
|
||||
}
|
||||
|
||||
func NewController(service *service.Service, rpcWaterAuthConsumer *light.Consumer, rpcHk4eGatewayConsumer *light.Consumer) (r *Controller) {
|
||||
r = new(Controller)
|
||||
r.service = service
|
||||
r.rpcWaterAuthConsumer = rpcWaterAuthConsumer
|
||||
r.rpcHk4eGatewayConsumer = rpcHk4eGatewayConsumer
|
||||
go r.registerRouter()
|
||||
return r
|
||||
}
|
||||
|
||||
func (c *Controller) getAccessToken(context *gin.Context) string {
|
||||
accessToken := context.GetHeader("Authorization")
|
||||
divIndex := strings.Index(accessToken, " ")
|
||||
if divIndex > 0 {
|
||||
payload := accessToken[divIndex+1:]
|
||||
return payload
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// access_token鉴权
|
||||
func (c *Controller) authorize() gin.HandlerFunc {
|
||||
return func(context *gin.Context) {
|
||||
valid, err := waterAuth.WaterVerifyAccessToken(c.rpcWaterAuthConsumer, c.getAccessToken(context))
|
||||
if err == nil && valid == true {
|
||||
// 验证通过
|
||||
context.Next()
|
||||
return
|
||||
}
|
||||
// 验证不通过
|
||||
context.Abort()
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": "10001",
|
||||
"msg": "没有访问权限",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) registerRouter() {
|
||||
if config.CONF.Logger.Level == "DEBUG" {
|
||||
gin.SetMode(gin.DebugMode)
|
||||
} else {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
engine := gin.Default()
|
||||
// 未认证接口
|
||||
engine.POST("/user/reg", c.userRegister)
|
||||
engine.Use(c.authorize())
|
||||
// 认证接口
|
||||
engine.POST("/user/update/pwd", c.userUpdatePassword)
|
||||
// 管理员
|
||||
admin := engine.Group("/user/admin")
|
||||
{
|
||||
admin.GET("/query/user", c.queryUserByUsername)
|
||||
}
|
||||
port := strconv.FormatInt(int64(config.CONF.HttpPort), 10)
|
||||
portStr := ":" + port
|
||||
_ = engine.Run(portStr)
|
||||
}
|
||||
93
service/annie-user/controller/user_controller.go
Normal file
93
service/annie-user/controller/user_controller.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
apiEntity "annie-user/entity/api"
|
||||
dbEntity "annie-user/entity/db"
|
||||
"flswld.com/common/entity/dto"
|
||||
"flswld.com/common/utils/endec"
|
||||
"flswld.com/logger"
|
||||
waterAuth "flswld.com/water-api/auth"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func (c *Controller) userRegister(context *gin.Context) {
|
||||
userRegInfo := new(apiEntity.User)
|
||||
err := context.BindJSON(&userRegInfo)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": 10003,
|
||||
"msg": "参数错误",
|
||||
})
|
||||
return
|
||||
}
|
||||
username := userRegInfo.Username
|
||||
password := userRegInfo.Password
|
||||
if len(username) < 6 || len(username) > 20 {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "用户名为6-20位字符", nil))
|
||||
return
|
||||
}
|
||||
if len(password) < 8 || len(password) > 20 {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "密码为8-20位字符", nil))
|
||||
return
|
||||
}
|
||||
ok, err := regexp.MatchString("^[a-zA-Z0-9]{6,20}$", username)
|
||||
if err != nil || !ok {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "用户名只能包含大小写字母和数字", nil))
|
||||
return
|
||||
}
|
||||
user := c.service.QueryUserByUsername(username)
|
||||
if user != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "用户名已注册", nil))
|
||||
return
|
||||
}
|
||||
user = new(dbEntity.User)
|
||||
user.Username = username
|
||||
user.Password = password
|
||||
ok = c.service.RegisterUser(user)
|
||||
if !ok {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "用户注册失败", nil))
|
||||
return
|
||||
}
|
||||
logger.LOG.Info("user register success, username: %v", username)
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(0, "用户注册成功", nil))
|
||||
}
|
||||
|
||||
func (c *Controller) userUpdatePassword(context *gin.Context) {
|
||||
accessToken := c.getAccessToken(context)
|
||||
user, err := waterAuth.WaterQueryUserByAccessToken(c.rpcWaterAuthConsumer, accessToken)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(1001, "服务器内部错误", nil))
|
||||
return
|
||||
}
|
||||
json := make(map[string]string)
|
||||
err = context.BindJSON(&json)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": 10003,
|
||||
"msg": "参数错误",
|
||||
})
|
||||
return
|
||||
}
|
||||
oldPassword := json["oldPassword"]
|
||||
newPassword := json["newPassword"]
|
||||
if len(oldPassword) < 8 || len(oldPassword) > 20 || len(newPassword) < 8 || len(newPassword) > 20 {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "密码为8-20位字符", nil))
|
||||
return
|
||||
}
|
||||
dbUser := c.service.QueryUserByUsername(user.Username)
|
||||
if dbUser.Password != endec.Md5Str(oldPassword) {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "旧密码错误", nil))
|
||||
return
|
||||
}
|
||||
dbUser.Password = endec.Md5Str(newPassword)
|
||||
ok := c.service.UpdateUser(dbUser)
|
||||
if !ok {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "修改密码失败", nil))
|
||||
return
|
||||
}
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(0, "修改密码成功", nil))
|
||||
// TODO 处理各种失效
|
||||
_ = c.rpcHk4eGatewayConsumer.CallFunction("RpcManager", "UserPasswordChange", &dbUser.Uid, &ok)
|
||||
}
|
||||
30
service/annie-user/dao/dao.go
Normal file
30
service/annie-user/dao/dao.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/logger"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
)
|
||||
|
||||
type Dao struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewDao() (r *Dao) {
|
||||
r = new(Dao)
|
||||
db, err := gorm.Open("mysql", config.CONF.Database.Url)
|
||||
if err != nil {
|
||||
logger.LOG.Error("db open error: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
if config.CONF.Logger.Level == "DEBUG" {
|
||||
db.LogMode(true)
|
||||
}
|
||||
r.db = db
|
||||
return r
|
||||
}
|
||||
|
||||
func (d *Dao) CloseDao() {
|
||||
_ = d.db.Close()
|
||||
}
|
||||
37
service/annie-user/dao/user_dao.go
Normal file
37
service/annie-user/dao/user_dao.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
dbEntity "annie-user/entity/db"
|
||||
)
|
||||
|
||||
func (d *Dao) InsertUser(user *dbEntity.User) error {
|
||||
db := d.db
|
||||
err := db.Create(user).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dao) UpdateUser(user *dbEntity.User) error {
|
||||
db := d.db
|
||||
db = db.Model(&user)
|
||||
err := db.Updates(user).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dao) QueryUser(user *dbEntity.User) ([]dbEntity.User, error) {
|
||||
var userList []dbEntity.User
|
||||
db := d.db
|
||||
if user.Uid != 0 {
|
||||
db = db.Where("`uid` = ?", user.Uid)
|
||||
}
|
||||
if user.Username != "" {
|
||||
db = db.Where("`username` = ?", user.Username)
|
||||
}
|
||||
if user.Password != "" {
|
||||
db = db.Where("`password` = ?", user.Password)
|
||||
}
|
||||
if user.IsAdmin != false {
|
||||
db = db.Where("`is_admin` = ?", user.IsAdmin)
|
||||
}
|
||||
err := db.Find(&userList).Error
|
||||
return userList, err
|
||||
}
|
||||
8
service/annie-user/entity/api/user_entity.go
Normal file
8
service/annie-user/entity/api/user_entity.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package api
|
||||
|
||||
type User struct {
|
||||
Uid uint64 `json:"uid"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
IsAdmin bool `json:"isAdmin"`
|
||||
}
|
||||
12
service/annie-user/entity/db/user_entity.go
Normal file
12
service/annie-user/entity/db/user_entity.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package db
|
||||
|
||||
type User struct {
|
||||
Uid uint64 `gorm:"column:uid;primary_key;auto_increment"`
|
||||
Username string `gorm:"column:username"`
|
||||
Password string `gorm:"column:password"`
|
||||
IsAdmin bool `gorm:"column:is_admin"`
|
||||
}
|
||||
|
||||
func (User) TableName() string {
|
||||
return "user"
|
||||
}
|
||||
51
service/annie-user/go.mod
Normal file
51
service/annie-user/go.mod
Normal file
@@ -0,0 +1,51 @@
|
||||
module annie-user
|
||||
|
||||
go 1.19
|
||||
|
||||
require flswld.com/common v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/common => ../../common
|
||||
|
||||
require flswld.com/logger v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/logger => ../../logger
|
||||
|
||||
require flswld.com/air-api v0.0.0-incompatible // indirect
|
||||
|
||||
replace flswld.com/air-api => ../../air-api
|
||||
|
||||
require flswld.com/light v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/light => ../../light
|
||||
|
||||
require flswld.com/annie-user-api v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/annie-user-api => ../annie-user-api
|
||||
|
||||
require flswld.com/water-api v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/water-api => ../../water-api
|
||||
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.6.3
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.2.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||
github.com/golang/protobuf v1.3.3 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.9 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
)
|
||||
80
service/annie-user/go.sum
Normal file
80
service/annie-user/go.sum
Normal file
@@ -0,0 +1,80 @@
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
|
||||
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
|
||||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM=
|
||||
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
17
service/annie-user/service/rpc_service.go
Normal file
17
service/annie-user/service/rpc_service.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"annie-user/dao"
|
||||
)
|
||||
|
||||
type RpcService struct {
|
||||
dao *dao.Dao
|
||||
service *Service
|
||||
}
|
||||
|
||||
func NewRpcService(dao *dao.Dao, service *Service) (r *RpcService) {
|
||||
r = new(RpcService)
|
||||
r.service = service
|
||||
r.dao = dao
|
||||
return r
|
||||
}
|
||||
28
service/annie-user/service/rpc_user_service.go
Normal file
28
service/annie-user/service/rpc_user_service.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
dbEntity "annie-user/entity/db"
|
||||
"errors"
|
||||
rpcEntity "flswld.com/annie-user-api/entity"
|
||||
"flswld.com/common/utils/object"
|
||||
"flswld.com/logger"
|
||||
)
|
||||
|
||||
func (s *RpcService) RpcQueryUser(user *rpcEntity.User, res *[]rpcEntity.User) error {
|
||||
dbUser := new(dbEntity.User)
|
||||
dbUser.Uid = user.Uid
|
||||
dbUser.Username = user.Username
|
||||
dbUser.Password = user.Password
|
||||
dbUser.IsAdmin = user.IsAdmin
|
||||
userList, err := s.dao.QueryUser(dbUser)
|
||||
if err != nil {
|
||||
logger.LOG.Error("QueryUser error: %v", err)
|
||||
return errors.New("query user error")
|
||||
}
|
||||
err = object.ObjectDeepCopy(userList, res)
|
||||
if err != nil {
|
||||
logger.LOG.Error("ObjectDeepCopy error: %v", err)
|
||||
return errors.New("query user error")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
15
service/annie-user/service/service.go
Normal file
15
service/annie-user/service/service.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"annie-user/dao"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
dao *dao.Dao
|
||||
}
|
||||
|
||||
func NewService(dao *dao.Dao) (r *Service) {
|
||||
r = new(Service)
|
||||
r.dao = dao
|
||||
return r
|
||||
}
|
||||
43
service/annie-user/service/user_service.go
Normal file
43
service/annie-user/service/user_service.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
dbEntity "annie-user/entity/db"
|
||||
"flswld.com/common/utils/endec"
|
||||
"flswld.com/logger"
|
||||
)
|
||||
|
||||
func (s *Service) RegisterUser(user *dbEntity.User) bool {
|
||||
user.Password = endec.Md5Str(user.Password)
|
||||
user.IsAdmin = false
|
||||
err := s.dao.InsertUser(user)
|
||||
if err != nil {
|
||||
logger.LOG.Error("insert user to db error: %v", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *Service) UpdateUser(user *dbEntity.User) bool {
|
||||
err := s.dao.UpdateUser(user)
|
||||
if err != nil {
|
||||
logger.LOG.Error("update user from db error: %v", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *Service) QueryUserByUsername(username string) *dbEntity.User {
|
||||
userList, err := s.dao.QueryUser(&dbEntity.User{Username: username})
|
||||
if err != nil {
|
||||
logger.LOG.Error("query user from db error: %v", err)
|
||||
return nil
|
||||
}
|
||||
if len(userList) == 0 {
|
||||
return nil
|
||||
} else if len(userList) == 1 {
|
||||
return &(userList[0])
|
||||
} else {
|
||||
logger.LOG.Error("find not only one user")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
22
service/game-hk4e/cmd/application.toml
Normal file
22
service/game-hk4e/cmd/application.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
[hk4e]
|
||||
resource_path = "/usr/local/game_hk4e/resources/GameDataConfigTable"
|
||||
gacha_history_server = "https://hk4e.flswld.com/api/v1"
|
||||
|
||||
[logger]
|
||||
level = "DEBUG"
|
||||
method = "CONSOLE"
|
||||
track_line = true
|
||||
|
||||
[air]
|
||||
addr = "air"
|
||||
port = 8086
|
||||
service_name = "game-hk4e-app"
|
||||
|
||||
[light]
|
||||
port = 10006
|
||||
|
||||
[database]
|
||||
url = "mongodb://mongo:27017"
|
||||
|
||||
[mq]
|
||||
nats_url = "nats://nats1:4222,nats://nats2:4222,nats://nats3:4222"
|
||||
81
service/game-hk4e/cmd/main.go
Normal file
81
service/game-hk4e/cmd/main.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/light"
|
||||
"flswld.com/logger"
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/dao"
|
||||
"game-hk4e/game"
|
||||
"game-hk4e/mq"
|
||||
"game-hk4e/rpc"
|
||||
"github.com/arl/statsviz"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filePath := "./application.toml"
|
||||
config.InitConfig(filePath)
|
||||
|
||||
logger.InitLogger()
|
||||
logger.LOG.Info("game-hk4e start")
|
||||
|
||||
go func() {
|
||||
// 性能检测
|
||||
err := statsviz.RegisterDefault()
|
||||
if err != nil {
|
||||
logger.LOG.Error("statsviz init error: %v", err)
|
||||
}
|
||||
err = http.ListenAndServe("0.0.0.0:3456", nil)
|
||||
if err != nil {
|
||||
logger.LOG.Error("perf debug http start error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
constant.InitConstant()
|
||||
|
||||
gdc.InitGameDataConfig()
|
||||
|
||||
db := dao.NewDao()
|
||||
|
||||
netMsgInput := make(chan *proto.NetMsg, 10000)
|
||||
netMsgOutput := make(chan *proto.NetMsg, 10000)
|
||||
|
||||
hk4eGatewayConsumer := light.NewRpcConsumer("hk4e-gateway")
|
||||
rpcManager := rpc.NewRpcManager(hk4eGatewayConsumer)
|
||||
gameServiceProvider := light.NewRpcProvider(rpcManager)
|
||||
|
||||
messageQueue := mq.NewMessageQueue(netMsgInput, netMsgOutput)
|
||||
messageQueue.Start()
|
||||
|
||||
gameManager := game.NewGameManager(db, rpcManager, netMsgInput, netMsgOutput)
|
||||
gameManager.Start()
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
|
||||
for {
|
||||
s := <-c
|
||||
logger.LOG.Info("get a signal %s", s.String())
|
||||
switch s {
|
||||
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
|
||||
logger.LOG.Info("game-hk4e exit")
|
||||
gameManager.Stop()
|
||||
db.CloseDao()
|
||||
gameServiceProvider.CloseRpcProvider()
|
||||
hk4eGatewayConsumer.CloseRpcConsumer()
|
||||
messageQueue.Close()
|
||||
time.Sleep(time.Second)
|
||||
return
|
||||
case syscall.SIGHUP:
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
73
service/game-hk4e/config/ability_embryos.go
Normal file
73
service/game-hk4e/config/ability_embryos.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/logger"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AvatarConfigAbility struct {
|
||||
AbilityName string `json:"abilityName"`
|
||||
}
|
||||
|
||||
type AvatarConfig struct {
|
||||
Abilities []*AvatarConfigAbility `json:"abilities"`
|
||||
TargetAbilities []*AvatarConfigAbility `json:"targetAbilities"`
|
||||
}
|
||||
|
||||
type AbilityEmbryoEntry struct {
|
||||
Name string
|
||||
Abilities []string
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadAbilityEmbryos() {
|
||||
dirPath := g.binPrefix + "Avatar"
|
||||
fileList, err := ioutil.ReadDir(dirPath)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open dir error: %v", err)
|
||||
return
|
||||
}
|
||||
embryoList := make([]*AbilityEmbryoEntry, 0)
|
||||
for _, file := range fileList {
|
||||
fileName := file.Name()
|
||||
if !strings.Contains(fileName, "ConfigAvatar_") {
|
||||
continue
|
||||
}
|
||||
startIndex := strings.Index(fileName, "ConfigAvatar_")
|
||||
endIndex := strings.Index(fileName, ".json")
|
||||
if startIndex == -1 || endIndex == -1 || startIndex+13 > endIndex {
|
||||
logger.LOG.Error("file name format error: %v", fileName)
|
||||
continue
|
||||
}
|
||||
avatarName := fileName[startIndex+13 : endIndex]
|
||||
fileData, err := ioutil.ReadFile(dirPath + "/" + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
continue
|
||||
}
|
||||
avatarConfig := new(AvatarConfig)
|
||||
err = json.Unmarshal(fileData, avatarConfig)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
if len(avatarConfig.Abilities) == 0 {
|
||||
continue
|
||||
}
|
||||
abilityEmbryoEntry := new(AbilityEmbryoEntry)
|
||||
abilityEmbryoEntry.Name = avatarName
|
||||
for _, v := range avatarConfig.Abilities {
|
||||
abilityEmbryoEntry.Abilities = append(abilityEmbryoEntry.Abilities, v.AbilityName)
|
||||
}
|
||||
embryoList = append(embryoList, abilityEmbryoEntry)
|
||||
}
|
||||
if len(embryoList) == 0 {
|
||||
logger.LOG.Error("no embryo load")
|
||||
}
|
||||
g.AbilityEmbryos = make(map[string]*AbilityEmbryoEntry)
|
||||
for _, v := range embryoList {
|
||||
g.AbilityEmbryos[v.Name] = v
|
||||
}
|
||||
logger.LOG.Info("load %v AbilityEmbryos", len(g.AbilityEmbryos))
|
||||
}
|
||||
102
service/game-hk4e/config/avatar_data.go
Normal file
102
service/game-hk4e/config/avatar_data.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/common/utils/endec"
|
||||
"flswld.com/logger"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AvatarData struct {
|
||||
IconName string `json:"iconName"`
|
||||
BodyType string `json:"bodyType"`
|
||||
QualityType string `json:"qualityType"`
|
||||
ChargeEfficiency int32 `json:"chargeEfficiency"`
|
||||
InitialWeapon int32 `json:"initialWeapon"`
|
||||
WeaponType string `json:"weaponType"`
|
||||
ImageName string `json:"imageName"`
|
||||
AvatarPromoteId int32 `json:"avatarPromoteId"`
|
||||
CutsceneShow string `json:"cutsceneShow"`
|
||||
SkillDepotId int32 `json:"skillDepotId"`
|
||||
StaminaRecoverSpeed int32 `json:"staminaRecoverSpeed"`
|
||||
CandSkillDepotIds []int32 `json:"candSkillDepotIds"`
|
||||
AvatarIdentityType string `json:"avatarIdentityType"`
|
||||
AvatarPromoteRewardLevelList []int32 `json:"avatarPromoteRewardLevelList"`
|
||||
AvatarPromoteRewardIdList []int32 `json:"avatarPromoteRewardIdList"`
|
||||
|
||||
NameTextMapHash int64 `json:"nameTextMapHash"`
|
||||
|
||||
HpBase float64 `json:"hpBase"`
|
||||
AttackBase float64 `json:"attackBase"`
|
||||
DefenseBase float64 `json:"defenseBase"`
|
||||
Critical float64 `json:"critical"`
|
||||
CriticalHurt float64 `json:"criticalHurt"`
|
||||
|
||||
PropGrowCurves []*PropGrowCurve `json:"propGrowCurves"`
|
||||
Id int32 `json:"id"`
|
||||
|
||||
// 计算数据
|
||||
Name string `json:"-"`
|
||||
Abilities []int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadAvatarData() {
|
||||
g.AvatarDataMap = make(map[int32]*AvatarData)
|
||||
fileNameList := []string{"AvatarExcelConfigData.json"}
|
||||
for _, fileName := range fileNameList {
|
||||
fileData, err := ioutil.ReadFile(g.excelBinPrefix + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
continue
|
||||
}
|
||||
list := make([]map[string]any, 0)
|
||||
err = json.Unmarshal(fileData, &list)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
for _, v := range list {
|
||||
i, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
avatarData := new(AvatarData)
|
||||
err = json.Unmarshal(i, avatarData)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
g.AvatarDataMap[avatarData.Id] = avatarData
|
||||
}
|
||||
}
|
||||
logger.LOG.Info("load %v AvatarData", len(g.AvatarDataMap))
|
||||
for _, v := range g.AvatarDataMap {
|
||||
split := strings.Split(v.IconName, "_")
|
||||
if len(split) > 0 {
|
||||
v.Name = split[len(split)-1]
|
||||
info := g.AbilityEmbryos[v.Name]
|
||||
if info != nil {
|
||||
v.Abilities = make([]int32, 0)
|
||||
for _, ability := range info.Abilities {
|
||||
v.Abilities = append(v.Abilities, endec.Hk4eAbilityHashCode(ability))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 成长属性要读表
|
||||
|
||||
func (a *AvatarData) GetBaseHpByLevel(level uint8) float64 {
|
||||
return a.HpBase * float64(level)
|
||||
}
|
||||
|
||||
func (a *AvatarData) GetBaseAttackByLevel(level uint8) float64 {
|
||||
return a.AttackBase * float64(level)
|
||||
}
|
||||
|
||||
func (a *AvatarData) GetBaseDefenseByLevel(level uint8) float64 {
|
||||
return a.DefenseBase * float64(level)
|
||||
}
|
||||
65
service/game-hk4e/config/avatar_skill_data.go
Normal file
65
service/game-hk4e/config/avatar_skill_data.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/constant"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type AvatarSkillData struct {
|
||||
Id int32 `json:"id"`
|
||||
CdTime float64 `json:"cdTime"`
|
||||
CostElemVal int32 `json:"costElemVal"`
|
||||
MaxChargeNum int32 `json:"maxChargeNum"`
|
||||
TriggerID int32 `json:"triggerID"`
|
||||
IsAttackCameraLock bool `json:"isAttackCameraLock"`
|
||||
ProudSkillGroupId int32 `json:"proudSkillGroupId"`
|
||||
CostElemType string `json:"costElemType"`
|
||||
LockWeightParams []float64 `json:"lockWeightParams"`
|
||||
|
||||
NameTextMapHash int64 `json:"nameTextMapHash"`
|
||||
|
||||
AbilityName string `json:"abilityName"`
|
||||
LockShape string `json:"lockShape"`
|
||||
GlobalValueKey string `json:"globalValueKey"`
|
||||
|
||||
// 计算属性
|
||||
CostElemTypeX *constant.ElementTypeValue `json:"-"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadAvatarSkillData() {
|
||||
g.AvatarSkillDataMap = make(map[int32]*AvatarSkillData)
|
||||
fileNameList := []string{"AvatarSkillExcelConfigData.json"}
|
||||
for _, fileName := range fileNameList {
|
||||
fileData, err := ioutil.ReadFile(g.excelBinPrefix + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
continue
|
||||
}
|
||||
list := make([]map[string]any, 0)
|
||||
err = json.Unmarshal(fileData, &list)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
for _, v := range list {
|
||||
i, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
avatarSkillData := new(AvatarSkillData)
|
||||
err = json.Unmarshal(i, avatarSkillData)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
g.AvatarSkillDataMap[avatarSkillData.Id] = avatarSkillData
|
||||
}
|
||||
}
|
||||
logger.LOG.Info("load %v AvatarSkillData", len(g.AvatarSkillDataMap))
|
||||
for _, v := range g.AvatarSkillDataMap {
|
||||
v.CostElemTypeX = constant.ElementTypeConst.STRING_MAP[v.CostElemType]
|
||||
}
|
||||
}
|
||||
84
service/game-hk4e/config/avatar_skill_depot_data.go
Normal file
84
service/game-hk4e/config/avatar_skill_depot_data.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/common/utils/endec"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/constant"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type InherentProudSkillOpens struct {
|
||||
ProudSkillGroupId int32 `json:"proudSkillGroupId"`
|
||||
NeedAvatarPromoteLevel int32 `json:"needAvatarPromoteLevel"`
|
||||
}
|
||||
|
||||
type AvatarSkillDepotData struct {
|
||||
Id int32 `json:"id"`
|
||||
EnergySkill int32 `json:"energySkill"`
|
||||
AttackModeSkill int32 `json:"attackModeSkill"`
|
||||
|
||||
Skills []int32 `json:"skills"`
|
||||
SubSkills []int32 `json:"subSkills"`
|
||||
ExtraAbilities []string `json:"extraAbilities"`
|
||||
Talents []int32 `json:"talents"`
|
||||
InherentProudSkillOpens []*InherentProudSkillOpens `json:"inherentProudSkillOpens"`
|
||||
TalentStarName string `json:"talentStarName"`
|
||||
SkillDepotAbilityGroup string `json:"skillDepotAbilityGroup"`
|
||||
|
||||
// 计算属性
|
||||
EnergySkillData *AvatarSkillData `json:"-"`
|
||||
ElementType *constant.ElementTypeValue `json:"-"`
|
||||
Abilities []int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadAvatarSkillDepotData() {
|
||||
g.AvatarSkillDepotDataMap = make(map[int32]*AvatarSkillDepotData)
|
||||
fileNameList := []string{"AvatarSkillDepotExcelConfigData.json"}
|
||||
for _, fileName := range fileNameList {
|
||||
fileData, err := ioutil.ReadFile(g.excelBinPrefix + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
continue
|
||||
}
|
||||
list := make([]map[string]any, 0)
|
||||
err = json.Unmarshal(fileData, &list)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
for _, v := range list {
|
||||
i, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
avatarSkillDepotData := new(AvatarSkillDepotData)
|
||||
err = json.Unmarshal(i, avatarSkillDepotData)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
g.AvatarSkillDepotDataMap[avatarSkillDepotData.Id] = avatarSkillDepotData
|
||||
}
|
||||
}
|
||||
logger.LOG.Info("load %v AvatarSkillDepotData", len(g.AvatarSkillDepotDataMap))
|
||||
for _, v := range g.AvatarSkillDepotDataMap {
|
||||
// set energy skill data
|
||||
v.EnergySkillData = g.AvatarSkillDataMap[v.EnergySkill]
|
||||
if v.EnergySkillData != nil {
|
||||
v.ElementType = v.EnergySkillData.CostElemTypeX
|
||||
} else {
|
||||
v.ElementType = constant.ElementTypeConst.None
|
||||
}
|
||||
// set embryo abilities if player skill depot
|
||||
if v.SkillDepotAbilityGroup != "" {
|
||||
config := g.GameDepot.PlayerAbilities[v.SkillDepotAbilityGroup]
|
||||
if config != nil {
|
||||
for _, targetAbility := range config.TargetAbilities {
|
||||
v.Abilities = append(v.Abilities, endec.Hk4eAbilityHashCode(targetAbility.AbilityName))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
service/game-hk4e/config/drop_group_data.go
Normal file
59
service/game-hk4e/config/drop_group_data.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"flswld.com/logger"
|
||||
"github.com/jszwec/csvutil"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Drop struct {
|
||||
DropId int32 `csv:"DropId"`
|
||||
Weight int32 `csv:"Weight"`
|
||||
Result int32 `csv:"Result"`
|
||||
IsEnd bool `csv:"IsEnd"`
|
||||
}
|
||||
|
||||
type DropGroupData struct {
|
||||
DropId int32
|
||||
WeightAll int32
|
||||
DropConfig []*Drop
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadDropGroupData() {
|
||||
g.DropGroupDataMap = make(map[int32]*DropGroupData)
|
||||
fileNameList := []string{"DropGachaAvatarUp.csv", "DropGachaWeaponUp.csv", "DropGachaNormal.csv"}
|
||||
for _, fileName := range fileNameList {
|
||||
fileData, err := ioutil.ReadFile(g.csvPrefix + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
return
|
||||
}
|
||||
// 去除第二三行的内容变成标准格式的csv
|
||||
index1 := strings.Index(string(fileData), "\n")
|
||||
index2 := strings.Index(string(fileData[(index1+1):]), "\n")
|
||||
index3 := strings.Index(string(fileData[(index2+1)+(index1+1):]), "\n")
|
||||
standardCsvData := make([]byte, 0)
|
||||
standardCsvData = append(standardCsvData, fileData[:index1]...)
|
||||
standardCsvData = append(standardCsvData, fileData[index3+(index2+1)+(index1+1):]...)
|
||||
var dropList []*Drop
|
||||
err = csvutil.Unmarshal(standardCsvData, &dropList)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
return
|
||||
}
|
||||
for _, drop := range dropList {
|
||||
dropGroupData, exist := g.DropGroupDataMap[drop.DropId]
|
||||
if !exist {
|
||||
dropGroupData = new(DropGroupData)
|
||||
dropGroupData.DropId = drop.DropId
|
||||
dropGroupData.WeightAll = 0
|
||||
dropGroupData.DropConfig = make([]*Drop, 0)
|
||||
g.DropGroupDataMap[drop.DropId] = dropGroupData
|
||||
}
|
||||
dropGroupData.WeightAll += drop.Weight
|
||||
dropGroupData.DropConfig = append(dropGroupData.DropConfig, drop)
|
||||
}
|
||||
}
|
||||
logger.LOG.Info("load %v DropGroupData", len(g.DropGroupDataMap))
|
||||
}
|
||||
54
service/game-hk4e/config/fetter_data.go
Normal file
54
service/game-hk4e/config/fetter_data.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/logger"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type FetterData struct {
|
||||
AvatarId int32 `json:"avatarId"`
|
||||
FetterId int32 `json:"fetterId"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadFetterData() {
|
||||
g.FetterDataMap = make(map[int32]*FetterData)
|
||||
fileNameList := []string{"FetterInfoExcelConfigData.json", "FettersExcelConfigData.json", "FetterStoryExcelConfigData.json", "PhotographExpressionExcelConfigData.json", "PhotographPosenameExcelConfigData.json"}
|
||||
for _, fileName := range fileNameList {
|
||||
fileData, err := ioutil.ReadFile(g.excelBinPrefix + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
continue
|
||||
}
|
||||
list := make([]map[string]any, 0)
|
||||
err = json.Unmarshal(fileData, &list)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
for _, v := range list {
|
||||
i, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
fetterData := new(FetterData)
|
||||
err = json.Unmarshal(i, fetterData)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
g.FetterDataMap[fetterData.FetterId] = fetterData
|
||||
}
|
||||
}
|
||||
logger.LOG.Info("load %v FetterData", len(g.FetterDataMap))
|
||||
g.AvatarFetterDataMap = make(map[int32][]int32)
|
||||
for _, v := range g.FetterDataMap {
|
||||
avatarFetterIdList, exist := g.AvatarFetterDataMap[v.AvatarId]
|
||||
if !exist {
|
||||
avatarFetterIdList = make([]int32, 0)
|
||||
}
|
||||
avatarFetterIdList = append(avatarFetterIdList, v.FetterId)
|
||||
g.AvatarFetterDataMap[v.AvatarId] = avatarFetterIdList
|
||||
}
|
||||
}
|
||||
60
service/game-hk4e/config/gadget_data.go
Normal file
60
service/game-hk4e/config/gadget_data.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/constant"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type GadgetData struct {
|
||||
Id int32 `json:"id"`
|
||||
Type string `json:"type"`
|
||||
JsonName string `json:"jsonName"`
|
||||
IsInteractive bool `json:"isInteractive"`
|
||||
Tags []string `json:"tags"`
|
||||
ItemJsonName string `json:"itemJsonName"`
|
||||
InteeIconName string `json:"inteeIconName"`
|
||||
NameTextMapHash int64 `json:"nameTextMapHash"`
|
||||
CampID int32 `json:"campID"`
|
||||
LODPatternName string `json:"LODPatternName"`
|
||||
|
||||
// 计算属性
|
||||
TypeX uint16 `json:"-"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadGadgetData() {
|
||||
g.GadgetDataMap = make(map[int32]*GadgetData)
|
||||
fileNameList := []string{"GadgetExcelConfigData.json"}
|
||||
for _, fileName := range fileNameList {
|
||||
fileData, err := ioutil.ReadFile(g.excelBinPrefix + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
continue
|
||||
}
|
||||
list := make([]map[string]any, 0)
|
||||
err = json.Unmarshal(fileData, &list)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
for _, v := range list {
|
||||
i, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
gadgetData := new(GadgetData)
|
||||
err = json.Unmarshal(i, gadgetData)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
g.GadgetDataMap[gadgetData.Id] = gadgetData
|
||||
}
|
||||
}
|
||||
logger.LOG.Info("load %v GadgetData", len(g.GadgetDataMap))
|
||||
for _, v := range g.GadgetDataMap {
|
||||
v.TypeX = constant.EntityTypeConst.STRING_MAP[v.Type]
|
||||
}
|
||||
}
|
||||
154
service/game-hk4e/config/game_data_config.go
Normal file
154
service/game-hk4e/config/game_data_config.go
Normal file
@@ -0,0 +1,154 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
appConfig "flswld.com/common/config"
|
||||
"flswld.com/logger"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var CONF *GameDataConfig = nil
|
||||
|
||||
type GameDataConfig struct {
|
||||
binPrefix string
|
||||
excelBinPrefix string
|
||||
csvPrefix string
|
||||
GameDepot *GameDepot
|
||||
// 配置表
|
||||
// BinOutput
|
||||
// 技能列表
|
||||
AbilityEmbryos map[string]*AbilityEmbryoEntry
|
||||
OpenConfigEntries map[string]*OpenConfigEntry
|
||||
// ExcelBinOutput
|
||||
FetterDataMap map[int32]*FetterData
|
||||
AvatarFetterDataMap map[int32][]int32
|
||||
// 资源
|
||||
// 场景传送点
|
||||
ScenePointEntries map[string]*ScenePointEntry
|
||||
ScenePointIdList []int32
|
||||
// 角色
|
||||
AvatarDataMap map[int32]*AvatarData
|
||||
// 道具
|
||||
ItemDataMap map[int32]*ItemData
|
||||
// 角色技能
|
||||
AvatarSkillDataMap map[int32]*AvatarSkillData
|
||||
AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData
|
||||
// 掉落组配置表
|
||||
DropGroupDataMap map[int32]*DropGroupData
|
||||
// GG
|
||||
GadgetDataMap map[int32]*GadgetData
|
||||
// 采集物
|
||||
GatherDataMap map[int32]*GatherData
|
||||
}
|
||||
|
||||
func InitGameDataConfig() {
|
||||
CONF = new(GameDataConfig)
|
||||
CONF.binPrefix = ""
|
||||
CONF.excelBinPrefix = ""
|
||||
CONF.csvPrefix = ""
|
||||
CONF.loadAll()
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) load() {
|
||||
g.loadGameDepot()
|
||||
// 技能列表
|
||||
g.loadAbilityEmbryos()
|
||||
g.loadOpenConfig()
|
||||
// 资源
|
||||
g.loadFetterData()
|
||||
// 场景传送点
|
||||
g.loadScenePoints()
|
||||
// 角色
|
||||
g.loadAvatarData()
|
||||
// 道具
|
||||
g.loadItemData()
|
||||
// 角色技能
|
||||
g.loadAvatarSkillData()
|
||||
g.loadAvatarSkillDepotData()
|
||||
// 掉落组配置表
|
||||
g.loadDropGroupData()
|
||||
// GG
|
||||
g.loadGadgetData()
|
||||
// 采集物
|
||||
g.loadGatherData()
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) getResourcePathPrefix() string {
|
||||
resourcePath := appConfig.CONF.Hk4e.ResourcePath
|
||||
// for dev
|
||||
if runtime.GOOS == "windows" {
|
||||
resourcePath = "C:/Users/FlourishingWorld/Desktop/GI/GameDataConfigTable"
|
||||
}
|
||||
return resourcePath
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadAll() {
|
||||
resourcePath := g.getResourcePathPrefix()
|
||||
dirInfo, err := os.Stat(resourcePath)
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.LOG.Error("open game data config dir error: %v", err)
|
||||
return
|
||||
}
|
||||
g.binPrefix = resourcePath + "/BinOutput"
|
||||
g.excelBinPrefix = resourcePath + "/ExcelBinOutput"
|
||||
g.csvPrefix = resourcePath + "/Csv"
|
||||
dirInfo, err = os.Stat(g.binPrefix)
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.LOG.Error("open game data bin output config dir error: %v", err)
|
||||
return
|
||||
}
|
||||
dirInfo, err = os.Stat(g.excelBinPrefix)
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.LOG.Error("open game data excel bin output config dir error: %v", err)
|
||||
return
|
||||
}
|
||||
dirInfo, err = os.Stat(g.csvPrefix)
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.LOG.Error("open game data csv config dir error: %v", err)
|
||||
return
|
||||
}
|
||||
g.binPrefix += "/"
|
||||
g.excelBinPrefix += "/"
|
||||
g.csvPrefix += "/"
|
||||
g.load()
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) ReadWorldTerrain() []byte {
|
||||
resourcePath := g.getResourcePathPrefix()
|
||||
dirInfo, err := os.Stat(resourcePath)
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.LOG.Error("open game data config dir error: %v", err)
|
||||
return nil
|
||||
}
|
||||
dirInfo, err = os.Stat(resourcePath + "/WorldStatic")
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.LOG.Error("open game data world static dir error: %v", err)
|
||||
return nil
|
||||
}
|
||||
data, err := ioutil.ReadFile(resourcePath + "/WorldStatic/world_terrain.bin")
|
||||
if err != nil {
|
||||
logger.LOG.Error("read world terrain file error: %v", err)
|
||||
return nil
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) WriteWorldTerrain(data []byte) {
|
||||
resourcePath := g.getResourcePathPrefix()
|
||||
dirInfo, err := os.Stat(resourcePath)
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.LOG.Error("open game data config dir error: %v", err)
|
||||
return
|
||||
}
|
||||
dirInfo, err = os.Stat(resourcePath + "/WorldStatic")
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.LOG.Error("open game data world static dir error: %v", err)
|
||||
return
|
||||
}
|
||||
err = ioutil.WriteFile(resourcePath+"/WorldStatic/world_terrain.bin", data, 0644)
|
||||
if err != nil {
|
||||
logger.LOG.Error("write world terrain file error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
29
service/game-hk4e/config/game_depot.go
Normal file
29
service/game-hk4e/config/game_depot.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/logger"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type GameDepot struct {
|
||||
PlayerAbilities map[string]*AvatarConfig
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadGameDepot() {
|
||||
g.GameDepot = new(GameDepot)
|
||||
playerElementsFilePath := g.binPrefix + "AbilityGroup/AbilityGroup_Other_PlayerElementAbility.json"
|
||||
playerElementsFile, err := ioutil.ReadFile(playerElementsFilePath)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
return
|
||||
}
|
||||
playerAbilities := make(map[string]*AvatarConfig)
|
||||
err = json.Unmarshal(playerElementsFile, &playerAbilities)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
return
|
||||
}
|
||||
g.GameDepot.PlayerAbilities = playerAbilities
|
||||
logger.LOG.Info("load %v PlayerAbilities", len(g.GameDepot.PlayerAbilities))
|
||||
}
|
||||
50
service/game-hk4e/config/gather_data.go
Normal file
50
service/game-hk4e/config/gather_data.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/logger"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type GatherData struct {
|
||||
Id int32 `json:"id"`
|
||||
PointType int32 `json:"pointType"`
|
||||
GadgetId int32 `json:"gadgetId"`
|
||||
ItemId int32 `json:"itemId"`
|
||||
Cd int32 `json:"cd"`
|
||||
IsForbidGuest bool `json:"isForbidGuest"`
|
||||
InitDisableInteract bool `json:"initDisableInteract"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadGatherData() {
|
||||
g.GatherDataMap = make(map[int32]*GatherData)
|
||||
fileNameList := []string{"GatherExcelConfigData.json"}
|
||||
for _, fileName := range fileNameList {
|
||||
fileData, err := ioutil.ReadFile(g.excelBinPrefix + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
continue
|
||||
}
|
||||
list := make([]map[string]any, 0)
|
||||
err = json.Unmarshal(fileData, &list)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
for _, v := range list {
|
||||
i, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
gatherData := new(GatherData)
|
||||
err = json.Unmarshal(i, gatherData)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
g.GatherDataMap[gatherData.Id] = gatherData
|
||||
}
|
||||
}
|
||||
logger.LOG.Info("load %v GatherData", len(g.GatherDataMap))
|
||||
}
|
||||
161
service/game-hk4e/config/item_data.go
Normal file
161
service/game-hk4e/config/item_data.go
Normal file
@@ -0,0 +1,161 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/constant"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type ItemUseData struct {
|
||||
UseOp string `json:"useOp"`
|
||||
UseParam []string `json:"useParam"`
|
||||
}
|
||||
|
||||
type WeaponProperty struct {
|
||||
PropType string `json:"propType"`
|
||||
InitValue float64 `json:"initValue"`
|
||||
Type string `json:"type"`
|
||||
FightProp uint16 `json:"-"`
|
||||
}
|
||||
|
||||
type ItemData struct {
|
||||
Id int32 `json:"id"`
|
||||
StackLimit int32 `json:"stackLimit"`
|
||||
MaxUseCount int32 `json:"maxUseCount"`
|
||||
RankLevel int32 `json:"rankLevel"`
|
||||
EffectName string `json:"effectName"`
|
||||
SatiationParams []int32 `json:"satiationParams"`
|
||||
Rank int32 `json:"rank"`
|
||||
Weight int32 `json:"weight"`
|
||||
GadgetId int32 `json:"gadgetId"`
|
||||
DestroyReturnMaterial []int32 `json:"destroyReturnMaterial"`
|
||||
DestroyReturnMaterialCount []int32 `json:"destroyReturnMaterialCount"`
|
||||
ItemUse []*ItemUseData `json:"itemUse"`
|
||||
|
||||
// food
|
||||
FoodQuality string `json:"foodQuality"`
|
||||
UseTarget string `json:"useTarget"`
|
||||
IseParam []string `json:"iseParam"`
|
||||
|
||||
// string enums
|
||||
ItemType string `json:"itemType"`
|
||||
MaterialType string `json:"materialType"`
|
||||
EquipType string `json:"equipType"`
|
||||
EffectType string `json:"effectType"`
|
||||
DestroyRule string `json:"destroyRule"`
|
||||
|
||||
// post load enum forms of above
|
||||
MaterialEnumType uint16 `json:"-"`
|
||||
ItemEnumType uint16 `json:"-"`
|
||||
EquipEnumType uint16 `json:"-"`
|
||||
|
||||
// relic
|
||||
MainPropDepotId int32 `json:"mainPropDepotId"`
|
||||
AppendPropDepotId int32 `json:"appendPropDepotId"`
|
||||
AppendPropNum int32 `json:"appendPropNum"`
|
||||
SetId int32 `json:"setId"`
|
||||
AddPropLevels []int32 `json:"addPropLevels"`
|
||||
BaseConvExp int32 `json:"baseConvExp"`
|
||||
MaxLevel int32 `json:"maxLevel"`
|
||||
|
||||
// weapon
|
||||
WeaponPromoteId int32 `json:"weaponPromoteId"`
|
||||
WeaponBaseExp int32 `json:"weaponBaseExp"`
|
||||
StoryId int32 `json:"storyId"`
|
||||
AvatarPromoteId int32 `json:"avatarPromoteId"`
|
||||
AwakenMaterial int32 `json:"awakenMaterial"`
|
||||
AwakenCosts []int32 `json:"awakenCosts"`
|
||||
SkillAffix []int32 `json:"skillAffix"`
|
||||
WeaponProp []*WeaponProperty `json:"weaponProp"`
|
||||
|
||||
// hash
|
||||
Icon string `json:"icon"`
|
||||
NameTextMapHash int64 `json:"nameTextMapHash"`
|
||||
|
||||
AddPropLevelSet map[int32]bool `json:"-"`
|
||||
|
||||
// furniture
|
||||
Comfort int32 `json:"comfort"`
|
||||
FurnType []int32 `json:"furnType"`
|
||||
FurnitureGadgetID []int32 `json:"furnitureGadgetID"`
|
||||
RoomSceneId int32 `json:"roomSceneId"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadItemData() {
|
||||
g.ItemDataMap = make(map[int32]*ItemData)
|
||||
fileNameList := []string{"MaterialExcelConfigData.json", "WeaponExcelConfigData.json", "ReliquaryExcelConfigData.json", "HomeWorldFurnitureExcelConfigData.json"}
|
||||
for _, fileName := range fileNameList {
|
||||
fileData, err := ioutil.ReadFile(g.excelBinPrefix + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
continue
|
||||
}
|
||||
list := make([]map[string]any, 0)
|
||||
err = json.Unmarshal(fileData, &list)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
for _, v := range list {
|
||||
i, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
itemData := new(ItemData)
|
||||
err = json.Unmarshal(i, itemData)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
g.ItemDataMap[itemData.Id] = itemData
|
||||
}
|
||||
}
|
||||
logger.LOG.Info("load %v ItemData", len(g.ItemDataMap))
|
||||
|
||||
for _, itemData := range g.ItemDataMap {
|
||||
itemData.ItemEnumType = constant.ItemTypeConst.STRING_MAP[itemData.ItemType]
|
||||
itemData.MaterialEnumType = constant.MaterialTypeConst.STRING_MAP[itemData.MaterialType]
|
||||
|
||||
if itemData.ItemEnumType == constant.ItemTypeConst.ITEM_RELIQUARY {
|
||||
itemData.EquipEnumType = constant.EquipTypeConst.STRING_MAP[itemData.EquipType]
|
||||
if itemData.AddPropLevels != nil || len(itemData.AddPropLevels) > 0 {
|
||||
itemData.AddPropLevelSet = make(map[int32]bool)
|
||||
for _, v := range itemData.AddPropLevels {
|
||||
itemData.AddPropLevelSet[v] = true
|
||||
}
|
||||
}
|
||||
} else if itemData.ItemEnumType == constant.ItemTypeConst.ITEM_WEAPON {
|
||||
itemData.EquipEnumType = constant.EquipTypeConst.EQUIP_WEAPON
|
||||
} else {
|
||||
itemData.EquipEnumType = constant.EquipTypeConst.EQUIP_NONE
|
||||
}
|
||||
|
||||
if itemData.WeaponProp != nil {
|
||||
for i, v := range itemData.WeaponProp {
|
||||
v.FightProp = constant.FightPropertyConst.STRING_MAP[v.PropType]
|
||||
itemData.WeaponProp[i] = v
|
||||
}
|
||||
}
|
||||
|
||||
if itemData.FurnType != nil {
|
||||
furnType := make([]int32, 0)
|
||||
for _, v := range itemData.FurnType {
|
||||
if v > 0 {
|
||||
furnType = append(furnType, v)
|
||||
}
|
||||
}
|
||||
itemData.FurnType = furnType
|
||||
}
|
||||
if itemData.FurnitureGadgetID != nil {
|
||||
furnitureGadgetID := make([]int32, 0)
|
||||
for _, v := range itemData.FurnitureGadgetID {
|
||||
if v > 0 {
|
||||
furnitureGadgetID = append(furnitureGadgetID, v)
|
||||
}
|
||||
}
|
||||
itemData.FurnitureGadgetID = furnitureGadgetID
|
||||
}
|
||||
}
|
||||
}
|
||||
92
service/game-hk4e/config/open_config_entries.go
Normal file
92
service/game-hk4e/config/open_config_entries.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/logger"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SkillPointModifier struct {
|
||||
SkillId int32
|
||||
Delta int32
|
||||
}
|
||||
|
||||
type OpenConfigEntry struct {
|
||||
Name string
|
||||
AddAbilities []string
|
||||
ExtraTalentIndex int32
|
||||
SkillPointModifiers []*SkillPointModifier
|
||||
}
|
||||
|
||||
func NewOpenConfigEntry(name string, data []*OpenConfigData) (r *OpenConfigEntry) {
|
||||
r = new(OpenConfigEntry)
|
||||
r.Name = name
|
||||
abilityList := make([]string, 0)
|
||||
modList := make([]*SkillPointModifier, 0)
|
||||
for _, v := range data {
|
||||
if strings.Contains(v.DollarType, "AddAbility") {
|
||||
abilityList = append(abilityList, v.AbilityName)
|
||||
} else if v.TalentIndex > 0 {
|
||||
r.ExtraTalentIndex = v.TalentIndex
|
||||
} else if strings.Contains(v.DollarType, "ModifySkillPoint") {
|
||||
modList = append(modList, &SkillPointModifier{
|
||||
SkillId: v.SkillID,
|
||||
Delta: v.PointDelta,
|
||||
})
|
||||
}
|
||||
}
|
||||
r.AddAbilities = abilityList
|
||||
r.SkillPointModifiers = modList
|
||||
return r
|
||||
}
|
||||
|
||||
type OpenConfigData struct {
|
||||
DollarType string `json:"$type"`
|
||||
AbilityName string `json:"abilityName"`
|
||||
TalentIndex int32 `json:"talentIndex"`
|
||||
SkillID int32 `json:"skillID"`
|
||||
PointDelta int32 `json:"pointDelta"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadOpenConfig() {
|
||||
list := make([]*OpenConfigEntry, 0)
|
||||
folderNames := []string{"Talent/EquipTalents", "Talent/AvatarTalents"}
|
||||
for _, v := range folderNames {
|
||||
dirPath := g.binPrefix + v
|
||||
fileList, err := ioutil.ReadDir(dirPath)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open dir error: %v", err)
|
||||
return
|
||||
}
|
||||
for _, file := range fileList {
|
||||
fileName := file.Name()
|
||||
if !strings.Contains(fileName, ".json") {
|
||||
continue
|
||||
}
|
||||
config := make(map[string][]*OpenConfigData)
|
||||
fileData, err := ioutil.ReadFile(dirPath + "/" + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
continue
|
||||
}
|
||||
err = json.Unmarshal(fileData, &config)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
for kk, vv := range config {
|
||||
entry := NewOpenConfigEntry(kk, vv)
|
||||
list = append(list, entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(list) == 0 {
|
||||
logger.LOG.Error("no open config entries load")
|
||||
}
|
||||
g.OpenConfigEntries = make(map[string]*OpenConfigEntry)
|
||||
for _, v := range list {
|
||||
g.OpenConfigEntries[v.Name] = v
|
||||
}
|
||||
logger.LOG.Info("load %v OpenConfig", len(g.OpenConfigEntries))
|
||||
}
|
||||
6
service/game-hk4e/config/prop_grow_curve.go
Normal file
6
service/game-hk4e/config/prop_grow_curve.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package config
|
||||
|
||||
type PropGrowCurve struct {
|
||||
Type string `json:"type"`
|
||||
GrowCurve string `json:"growCurve"`
|
||||
}
|
||||
85
service/game-hk4e/config/scene_points.go
Normal file
85
service/game-hk4e/config/scene_points.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/logger"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ScenePointEntry struct {
|
||||
Name string
|
||||
PointData *PointData
|
||||
}
|
||||
|
||||
type ScenePointConfig struct {
|
||||
Points map[string]*PointData `json:"points"`
|
||||
}
|
||||
|
||||
type PointData struct {
|
||||
Id int32 `json:"-"`
|
||||
DollarType string `json:"$type"`
|
||||
TranPos *Position `json:"tranPos"`
|
||||
DungeonIds []int32 `json:"dungeonIds"`
|
||||
DungeonRandomList []int32 `json:"dungeonRandomList"`
|
||||
TranSceneId int32 `json:"tranSceneId"`
|
||||
}
|
||||
|
||||
type Position struct {
|
||||
X float64 `json:"x"`
|
||||
Y float64 `json:"y"`
|
||||
Z float64 `json:"z"`
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) loadScenePoints() {
|
||||
g.ScenePointEntries = make(map[string]*ScenePointEntry)
|
||||
g.ScenePointIdList = make([]int32, 0)
|
||||
dirPath := g.binPrefix + "Scene/Point"
|
||||
fileList, err := ioutil.ReadDir(dirPath)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open dir error: %v", err)
|
||||
return
|
||||
}
|
||||
for _, file := range fileList {
|
||||
fileName := file.Name()
|
||||
if !strings.Contains(fileName, "scene") {
|
||||
continue
|
||||
}
|
||||
startIndex := strings.Index(fileName, "scene")
|
||||
endIndex := strings.Index(fileName, "_point.json")
|
||||
if startIndex == -1 || endIndex == -1 || startIndex+5 > endIndex {
|
||||
logger.LOG.Error("file name format error: %v", fileName)
|
||||
continue
|
||||
}
|
||||
sceneId := fileName[startIndex+5 : endIndex]
|
||||
fileData, err := ioutil.ReadFile(dirPath + "/" + fileName)
|
||||
if err != nil {
|
||||
logger.LOG.Error("open file error: %v", err)
|
||||
continue
|
||||
}
|
||||
scenePointConfig := new(ScenePointConfig)
|
||||
err = json.Unmarshal(fileData, scenePointConfig)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
if len(scenePointConfig.Points) == 0 {
|
||||
continue
|
||||
}
|
||||
for k, v := range scenePointConfig.Points {
|
||||
sceneIdInt32, err := strconv.ParseInt(k, 10, 32)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse file error: %v", err)
|
||||
continue
|
||||
}
|
||||
v.Id = int32(sceneIdInt32)
|
||||
scenePointEntry := new(ScenePointEntry)
|
||||
scenePointEntry.Name = sceneId + "_" + k
|
||||
scenePointEntry.PointData = v
|
||||
g.ScenePointIdList = append(g.ScenePointIdList, int32(sceneIdInt32))
|
||||
g.ScenePointEntries[scenePointEntry.Name] = scenePointEntry
|
||||
}
|
||||
}
|
||||
logger.LOG.Info("load %v ScenePointEntries", len(g.ScenePointEntries))
|
||||
}
|
||||
357
service/game-hk4e/constant/action_reason.go
Normal file
357
service/game-hk4e/constant/action_reason.go
Normal file
@@ -0,0 +1,357 @@
|
||||
package constant
|
||||
|
||||
var ActionReasonConst *ActionReason
|
||||
|
||||
type ActionReason struct {
|
||||
None uint16
|
||||
QuestItem uint16
|
||||
QuestReward uint16
|
||||
Trifle uint16
|
||||
Shop uint16
|
||||
PlayerUpgradeReward uint16
|
||||
AddAvatar uint16
|
||||
GadgetEnvAnimal uint16
|
||||
MonsterEnvAnimal uint16
|
||||
Compound uint16
|
||||
Cook uint16
|
||||
Gather uint16
|
||||
MailAttachment uint16
|
||||
CityLevelupReturn uint16
|
||||
CityLevelupReward uint16
|
||||
AreaExploreReward uint16
|
||||
UnlockPointReward uint16
|
||||
DungeonFirstPass uint16
|
||||
DungeonPass uint16
|
||||
ChangeElemType uint16
|
||||
FetterOpen uint16
|
||||
DailyTaskScore uint16
|
||||
DailyTaskHost uint16
|
||||
RandTaskHost uint16
|
||||
Expedition uint16
|
||||
Gacha uint16
|
||||
Combine uint16
|
||||
RandTaskGuest uint16
|
||||
DailyTaskGuest uint16
|
||||
ForgeOutput uint16
|
||||
ForgeReturn uint16
|
||||
InitAvatar uint16
|
||||
MonsterDie uint16
|
||||
Gm uint16
|
||||
OpenChest uint16
|
||||
GadgetDie uint16
|
||||
MonsterChangeHp uint16
|
||||
SubfieldDrop uint16
|
||||
PushTipsReward uint16
|
||||
ActivityMonsterDrop uint16
|
||||
ActivityGather uint16
|
||||
ActivitySubfieldDrop uint16
|
||||
TowerScheduleReward uint16
|
||||
TowerFloorStarReward uint16
|
||||
TowerFirstPassReward uint16
|
||||
TowerDailyReward uint16
|
||||
HitClientTrivialEntity uint16
|
||||
OpenWorldBossChest uint16
|
||||
MaterialDeleteReturn uint16
|
||||
SignInReward uint16
|
||||
OpenBlossomChest uint16
|
||||
Recharge uint16
|
||||
BonusActivityReward uint16
|
||||
TowerCommemorativeReward uint16
|
||||
TowerSkipFloorReward uint16
|
||||
RechargeBonus uint16
|
||||
RechargeCard uint16
|
||||
RechargeCardDaily uint16
|
||||
RechargeCardReplace uint16
|
||||
RechargeCardReplaceFree uint16
|
||||
RechargePlayReplace uint16
|
||||
MpPlayTakeReward uint16
|
||||
ActivityWatcher uint16
|
||||
SalesmanDeliverItem uint16
|
||||
SalesmanReward uint16
|
||||
Rebate uint16
|
||||
McoinExchangeHcoin uint16
|
||||
DailyTaskExchangeLegendaryKey uint16
|
||||
UnlockPersonLine uint16
|
||||
FetterLevelReward uint16
|
||||
BuyResin uint16
|
||||
RechargePackage uint16
|
||||
DeliveryDailyReward uint16
|
||||
CityReputationLevel uint16
|
||||
CityReputationQuest uint16
|
||||
CityReputationRequest uint16
|
||||
CityReputationExplore uint16
|
||||
OffergingLevel uint16
|
||||
RoutineHost uint16
|
||||
RoutineGuest uint16
|
||||
TreasureMapSpotToken uint16
|
||||
TreasureMapBonusLevelReward uint16
|
||||
TreasureMapMpReward uint16
|
||||
Convert uint16
|
||||
OverflowTransform uint16
|
||||
ActivityAvatarSelectionReward uint16
|
||||
ActivityWatcherBatch uint16
|
||||
HitTreeDrop uint16
|
||||
GetHomeLevelupReward uint16
|
||||
HomeDefaultFurniture uint16
|
||||
ActivityCond uint16
|
||||
BattlePassNotify uint16
|
||||
PlayerUseItem uint16
|
||||
DropItem uint16
|
||||
WeaponUpgrade uint16
|
||||
WeaponPromote uint16
|
||||
WeaponAwaken uint16
|
||||
RelicUpgrade uint16
|
||||
Ability uint16
|
||||
DungeonStatueDrop uint16
|
||||
OfflineMsg uint16
|
||||
AvatarUpgrade uint16
|
||||
AvatarPromote uint16
|
||||
QuestAction uint16
|
||||
CityLevelup uint16
|
||||
UpgradeSkill uint16
|
||||
UnlockTalent uint16
|
||||
UpgradeProudSkill uint16
|
||||
PlayerLevelLimitUp uint16
|
||||
DungeonDaily uint16
|
||||
ItemGiving uint16
|
||||
ForgeCost uint16
|
||||
InvestigationReward uint16
|
||||
InvestigationTargetReward uint16
|
||||
GadgetInteract uint16
|
||||
SeaLampCiMaterial uint16
|
||||
SeaLampContributionReward uint16
|
||||
SeaLampPhaseReward uint16
|
||||
SeaLampFlyLamp uint16
|
||||
AutoRecover uint16
|
||||
ActivityExpireItem uint16
|
||||
SubCoinNegative uint16
|
||||
BargainDeduct uint16
|
||||
BattlePassPaidReward uint16
|
||||
BattlePassLevelReward uint16
|
||||
TrialAvatarActivityFirstPassReward uint16
|
||||
BuyBattlePassLevel uint16
|
||||
GrantBirthdayBenefit uint16
|
||||
AchievementReward uint16
|
||||
AchievementGoalReward uint16
|
||||
FirstShareToSocialNetwork uint16
|
||||
DestroyMaterial uint16
|
||||
CodexLevelupReward uint16
|
||||
HuntingOfferReward uint16
|
||||
UseWidgetAnchorPoint uint16
|
||||
UseWidgetBonfire uint16
|
||||
UngradeWeaponReturnMaterial uint16
|
||||
UseWidgetOneoffGatherPointDetector uint16
|
||||
UseWidgetClientCollector uint16
|
||||
UseWidgetClientDetector uint16
|
||||
TakeGeneralReward uint16
|
||||
AsterTakeSpecialReward uint16
|
||||
RemoveCodexBook uint16
|
||||
OfferingItem uint16
|
||||
UseWidgetGadgetBuilder uint16
|
||||
EffigyFirstPassReward uint16
|
||||
EffigyReward uint16
|
||||
ReunionFirstGiftReward uint16
|
||||
ReunionSignInReward uint16
|
||||
ReunionWatcherReward uint16
|
||||
SalesmanMpReward uint16
|
||||
ActionReasionAvatarPromoteReward uint16
|
||||
BlessingRedeemReward uint16
|
||||
ActionMiracleRingReward uint16
|
||||
ExpeditionReward uint16
|
||||
TreasureMapRemoveDetector uint16
|
||||
MechanicusDungeonTicket uint16
|
||||
MechanicusLevelupGear uint16
|
||||
MechanicusBattleSettle uint16
|
||||
RegionSearchReward uint16
|
||||
UnlockCoopChapter uint16
|
||||
TakeCoopReward uint16
|
||||
FleurFairDungeonReward uint16
|
||||
ActivityScore uint16
|
||||
ChannellerSlabOneoffDungeonReward uint16
|
||||
FurnitureMakeStart uint16
|
||||
FurnitureMakeTake uint16
|
||||
FurnitureMakeCancel uint16
|
||||
FurnitureMakeFastFinish uint16
|
||||
ChannellerSlabLoopDungeonFirstPassReward uint16
|
||||
ChannellerSlabLoopDungeonScoreReward uint16
|
||||
HomeLimitedShopBuy uint16
|
||||
HomeCoinCollect uint16
|
||||
}
|
||||
|
||||
func InitActionReasonConst() {
|
||||
ActionReasonConst = new(ActionReason)
|
||||
|
||||
ActionReasonConst.None = 0
|
||||
ActionReasonConst.QuestItem = 1
|
||||
ActionReasonConst.QuestReward = 2
|
||||
ActionReasonConst.Trifle = 3
|
||||
ActionReasonConst.Shop = 4
|
||||
ActionReasonConst.PlayerUpgradeReward = 5
|
||||
ActionReasonConst.AddAvatar = 6
|
||||
ActionReasonConst.GadgetEnvAnimal = 7
|
||||
ActionReasonConst.MonsterEnvAnimal = 8
|
||||
ActionReasonConst.Compound = 9
|
||||
ActionReasonConst.Cook = 10
|
||||
ActionReasonConst.Gather = 11
|
||||
ActionReasonConst.MailAttachment = 12
|
||||
ActionReasonConst.CityLevelupReturn = 15
|
||||
ActionReasonConst.CityLevelupReward = 17
|
||||
ActionReasonConst.AreaExploreReward = 18
|
||||
ActionReasonConst.UnlockPointReward = 19
|
||||
ActionReasonConst.DungeonFirstPass = 20
|
||||
ActionReasonConst.DungeonPass = 21
|
||||
ActionReasonConst.ChangeElemType = 23
|
||||
ActionReasonConst.FetterOpen = 25
|
||||
ActionReasonConst.DailyTaskScore = 26
|
||||
ActionReasonConst.DailyTaskHost = 27
|
||||
ActionReasonConst.RandTaskHost = 28
|
||||
ActionReasonConst.Expedition = 29
|
||||
ActionReasonConst.Gacha = 30
|
||||
ActionReasonConst.Combine = 31
|
||||
ActionReasonConst.RandTaskGuest = 32
|
||||
ActionReasonConst.DailyTaskGuest = 33
|
||||
ActionReasonConst.ForgeOutput = 34
|
||||
ActionReasonConst.ForgeReturn = 35
|
||||
ActionReasonConst.InitAvatar = 36
|
||||
ActionReasonConst.MonsterDie = 37
|
||||
ActionReasonConst.Gm = 38
|
||||
ActionReasonConst.OpenChest = 39
|
||||
ActionReasonConst.GadgetDie = 40
|
||||
ActionReasonConst.MonsterChangeHp = 41
|
||||
ActionReasonConst.SubfieldDrop = 42
|
||||
ActionReasonConst.PushTipsReward = 43
|
||||
ActionReasonConst.ActivityMonsterDrop = 44
|
||||
ActionReasonConst.ActivityGather = 45
|
||||
ActionReasonConst.ActivitySubfieldDrop = 46
|
||||
ActionReasonConst.TowerScheduleReward = 47
|
||||
ActionReasonConst.TowerFloorStarReward = 48
|
||||
ActionReasonConst.TowerFirstPassReward = 49
|
||||
ActionReasonConst.TowerDailyReward = 50
|
||||
ActionReasonConst.HitClientTrivialEntity = 51
|
||||
ActionReasonConst.OpenWorldBossChest = 52
|
||||
ActionReasonConst.MaterialDeleteReturn = 53
|
||||
ActionReasonConst.SignInReward = 54
|
||||
ActionReasonConst.OpenBlossomChest = 55
|
||||
ActionReasonConst.Recharge = 56
|
||||
ActionReasonConst.BonusActivityReward = 57
|
||||
ActionReasonConst.TowerCommemorativeReward = 58
|
||||
ActionReasonConst.TowerSkipFloorReward = 59
|
||||
ActionReasonConst.RechargeBonus = 60
|
||||
ActionReasonConst.RechargeCard = 61
|
||||
ActionReasonConst.RechargeCardDaily = 62
|
||||
ActionReasonConst.RechargeCardReplace = 63
|
||||
ActionReasonConst.RechargeCardReplaceFree = 64
|
||||
ActionReasonConst.RechargePlayReplace = 65
|
||||
ActionReasonConst.MpPlayTakeReward = 66
|
||||
ActionReasonConst.ActivityWatcher = 67
|
||||
ActionReasonConst.SalesmanDeliverItem = 68
|
||||
ActionReasonConst.SalesmanReward = 69
|
||||
ActionReasonConst.Rebate = 70
|
||||
ActionReasonConst.McoinExchangeHcoin = 71
|
||||
ActionReasonConst.DailyTaskExchangeLegendaryKey = 72
|
||||
ActionReasonConst.UnlockPersonLine = 73
|
||||
ActionReasonConst.FetterLevelReward = 74
|
||||
ActionReasonConst.BuyResin = 75
|
||||
ActionReasonConst.RechargePackage = 76
|
||||
ActionReasonConst.DeliveryDailyReward = 77
|
||||
ActionReasonConst.CityReputationLevel = 78
|
||||
ActionReasonConst.CityReputationQuest = 79
|
||||
ActionReasonConst.CityReputationRequest = 80
|
||||
ActionReasonConst.CityReputationExplore = 81
|
||||
ActionReasonConst.OffergingLevel = 82
|
||||
ActionReasonConst.RoutineHost = 83
|
||||
ActionReasonConst.RoutineGuest = 84
|
||||
ActionReasonConst.TreasureMapSpotToken = 89
|
||||
ActionReasonConst.TreasureMapBonusLevelReward = 90
|
||||
ActionReasonConst.TreasureMapMpReward = 91
|
||||
ActionReasonConst.Convert = 92
|
||||
ActionReasonConst.OverflowTransform = 93
|
||||
ActionReasonConst.ActivityAvatarSelectionReward = 96
|
||||
ActionReasonConst.ActivityWatcherBatch = 97
|
||||
ActionReasonConst.HitTreeDrop = 98
|
||||
ActionReasonConst.GetHomeLevelupReward = 99
|
||||
ActionReasonConst.HomeDefaultFurniture = 100
|
||||
ActionReasonConst.ActivityCond = 101
|
||||
ActionReasonConst.BattlePassNotify = 102
|
||||
ActionReasonConst.PlayerUseItem = 1001
|
||||
ActionReasonConst.DropItem = 1002
|
||||
ActionReasonConst.WeaponUpgrade = 1011
|
||||
ActionReasonConst.WeaponPromote = 1012
|
||||
ActionReasonConst.WeaponAwaken = 1013
|
||||
ActionReasonConst.RelicUpgrade = 1014
|
||||
ActionReasonConst.Ability = 1015
|
||||
ActionReasonConst.DungeonStatueDrop = 1016
|
||||
ActionReasonConst.OfflineMsg = 1017
|
||||
ActionReasonConst.AvatarUpgrade = 1018
|
||||
ActionReasonConst.AvatarPromote = 1019
|
||||
ActionReasonConst.QuestAction = 1021
|
||||
ActionReasonConst.CityLevelup = 1022
|
||||
ActionReasonConst.UpgradeSkill = 1024
|
||||
ActionReasonConst.UnlockTalent = 1025
|
||||
ActionReasonConst.UpgradeProudSkill = 1026
|
||||
ActionReasonConst.PlayerLevelLimitUp = 1027
|
||||
ActionReasonConst.DungeonDaily = 1028
|
||||
ActionReasonConst.ItemGiving = 1030
|
||||
ActionReasonConst.ForgeCost = 1031
|
||||
ActionReasonConst.InvestigationReward = 1032
|
||||
ActionReasonConst.InvestigationTargetReward = 1033
|
||||
ActionReasonConst.GadgetInteract = 1034
|
||||
ActionReasonConst.SeaLampCiMaterial = 1036
|
||||
ActionReasonConst.SeaLampContributionReward = 1037
|
||||
ActionReasonConst.SeaLampPhaseReward = 1038
|
||||
ActionReasonConst.SeaLampFlyLamp = 1039
|
||||
ActionReasonConst.AutoRecover = 1040
|
||||
ActionReasonConst.ActivityExpireItem = 1041
|
||||
ActionReasonConst.SubCoinNegative = 1042
|
||||
ActionReasonConst.BargainDeduct = 1043
|
||||
ActionReasonConst.BattlePassPaidReward = 1044
|
||||
ActionReasonConst.BattlePassLevelReward = 1045
|
||||
ActionReasonConst.TrialAvatarActivityFirstPassReward = 1046
|
||||
ActionReasonConst.BuyBattlePassLevel = 1047
|
||||
ActionReasonConst.GrantBirthdayBenefit = 1048
|
||||
ActionReasonConst.AchievementReward = 1049
|
||||
ActionReasonConst.AchievementGoalReward = 1050
|
||||
ActionReasonConst.FirstShareToSocialNetwork = 1051
|
||||
ActionReasonConst.DestroyMaterial = 1052
|
||||
ActionReasonConst.CodexLevelupReward = 1053
|
||||
ActionReasonConst.HuntingOfferReward = 1054
|
||||
ActionReasonConst.UseWidgetAnchorPoint = 1055
|
||||
ActionReasonConst.UseWidgetBonfire = 1056
|
||||
ActionReasonConst.UngradeWeaponReturnMaterial = 1057
|
||||
ActionReasonConst.UseWidgetOneoffGatherPointDetector = 1058
|
||||
ActionReasonConst.UseWidgetClientCollector = 1059
|
||||
ActionReasonConst.UseWidgetClientDetector = 1060
|
||||
ActionReasonConst.TakeGeneralReward = 1061
|
||||
ActionReasonConst.AsterTakeSpecialReward = 1062
|
||||
ActionReasonConst.RemoveCodexBook = 1063
|
||||
ActionReasonConst.OfferingItem = 1064
|
||||
ActionReasonConst.UseWidgetGadgetBuilder = 1065
|
||||
ActionReasonConst.EffigyFirstPassReward = 1066
|
||||
ActionReasonConst.EffigyReward = 1067
|
||||
ActionReasonConst.ReunionFirstGiftReward = 1068
|
||||
ActionReasonConst.ReunionSignInReward = 1069
|
||||
ActionReasonConst.ReunionWatcherReward = 1070
|
||||
ActionReasonConst.SalesmanMpReward = 1071
|
||||
ActionReasonConst.ActionReasionAvatarPromoteReward = 1072
|
||||
ActionReasonConst.BlessingRedeemReward = 1073
|
||||
ActionReasonConst.ActionMiracleRingReward = 1074
|
||||
ActionReasonConst.ExpeditionReward = 1075
|
||||
ActionReasonConst.TreasureMapRemoveDetector = 1076
|
||||
ActionReasonConst.MechanicusDungeonTicket = 1077
|
||||
ActionReasonConst.MechanicusLevelupGear = 1078
|
||||
ActionReasonConst.MechanicusBattleSettle = 1079
|
||||
ActionReasonConst.RegionSearchReward = 1080
|
||||
ActionReasonConst.UnlockCoopChapter = 1081
|
||||
ActionReasonConst.TakeCoopReward = 1082
|
||||
ActionReasonConst.FleurFairDungeonReward = 1083
|
||||
ActionReasonConst.ActivityScore = 1084
|
||||
ActionReasonConst.ChannellerSlabOneoffDungeonReward = 1085
|
||||
ActionReasonConst.FurnitureMakeStart = 1086
|
||||
ActionReasonConst.FurnitureMakeTake = 1087
|
||||
ActionReasonConst.FurnitureMakeCancel = 1088
|
||||
ActionReasonConst.FurnitureMakeFastFinish = 1089
|
||||
ActionReasonConst.ChannellerSlabLoopDungeonFirstPassReward = 1090
|
||||
ActionReasonConst.ChannellerSlabLoopDungeonScoreReward = 1091
|
||||
ActionReasonConst.HomeLimitedShopBuy = 1092
|
||||
ActionReasonConst.HomeCoinCollect = 1093
|
||||
}
|
||||
25
service/game-hk4e/constant/climate_type.go
Normal file
25
service/game-hk4e/constant/climate_type.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package constant
|
||||
|
||||
var ClimateTypeConst *ClimateType
|
||||
|
||||
type ClimateType struct {
|
||||
CLIMATE_NONE uint16
|
||||
CLIMATE_SUNNY uint16
|
||||
CLIMATE_CLOUDY uint16
|
||||
CLIMATE_RAIN uint16
|
||||
CLIMATE_THUNDERSTORM uint16
|
||||
CLIMATE_SNOW uint16
|
||||
CLIMATE_MIST uint16
|
||||
}
|
||||
|
||||
func InitClimateTypeConst() {
|
||||
ClimateTypeConst = new(ClimateType)
|
||||
|
||||
ClimateTypeConst.CLIMATE_NONE = 0
|
||||
ClimateTypeConst.CLIMATE_SUNNY = 1
|
||||
ClimateTypeConst.CLIMATE_CLOUDY = 2
|
||||
ClimateTypeConst.CLIMATE_RAIN = 3
|
||||
ClimateTypeConst.CLIMATE_THUNDERSTORM = 4
|
||||
ClimateTypeConst.CLIMATE_SNOW = 5
|
||||
ClimateTypeConst.CLIMATE_MIST = 6
|
||||
}
|
||||
21
service/game-hk4e/constant/constant.go
Normal file
21
service/game-hk4e/constant/constant.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package constant
|
||||
|
||||
func InitConstant() {
|
||||
InitFightPropertyConst()
|
||||
InitActionReasonConst()
|
||||
InitClimateTypeConst()
|
||||
InitElementTypeConst()
|
||||
InitEnterReasonConst()
|
||||
InitEntityIdTypeConst()
|
||||
InitEquipTypeConst()
|
||||
InitFetterStateConst()
|
||||
InitGameConstant()
|
||||
InitGrowCurveConst()
|
||||
InitItemTypeConst()
|
||||
InitLifeStateConst()
|
||||
InitMaterialTypeConst()
|
||||
InitOpenStateConst()
|
||||
InitPlayerPropertyConst()
|
||||
InitSceneTypeConst()
|
||||
InitEntityTypeConst()
|
||||
}
|
||||
151
service/game-hk4e/constant/element_type.go
Normal file
151
service/game-hk4e/constant/element_type.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package constant
|
||||
|
||||
import "flswld.com/common/utils/endec"
|
||||
|
||||
var ElementTypeConst *ElementType
|
||||
|
||||
type ElementTypeValue struct {
|
||||
Value uint16
|
||||
CurrEnergyProp uint16
|
||||
MaxEnergyProp uint16
|
||||
TeamResonanceId uint16
|
||||
ConfigName string
|
||||
ConfigHash int32
|
||||
}
|
||||
|
||||
type ElementType struct {
|
||||
None *ElementTypeValue
|
||||
Fire *ElementTypeValue
|
||||
Water *ElementTypeValue
|
||||
Grass *ElementTypeValue
|
||||
Electric *ElementTypeValue
|
||||
Ice *ElementTypeValue
|
||||
Frozen *ElementTypeValue
|
||||
Wind *ElementTypeValue
|
||||
Rock *ElementTypeValue
|
||||
AntiFire *ElementTypeValue
|
||||
Default *ElementTypeValue
|
||||
STRING_MAP map[string]*ElementTypeValue
|
||||
VALUE_MAP map[uint16]*ElementTypeValue
|
||||
}
|
||||
|
||||
func InitElementTypeConst() {
|
||||
ElementTypeConst = new(ElementType)
|
||||
|
||||
ElementTypeConst.None = &ElementTypeValue{
|
||||
0,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_FIRE_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_FIRE_ENERGY,
|
||||
0,
|
||||
"",
|
||||
endec.Hk4eAbilityHashCode(""),
|
||||
}
|
||||
ElementTypeConst.Fire = &ElementTypeValue{
|
||||
1,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_FIRE_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_FIRE_ENERGY,
|
||||
10101,
|
||||
"TeamResonance_Fire_Lv2",
|
||||
endec.Hk4eAbilityHashCode("TeamResonance_Fire_Lv2"),
|
||||
}
|
||||
ElementTypeConst.Water = &ElementTypeValue{
|
||||
2,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_WATER_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_WATER_ENERGY,
|
||||
10201,
|
||||
"TeamResonance_Water_Lv2",
|
||||
endec.Hk4eAbilityHashCode("TeamResonance_Water_Lv2"),
|
||||
}
|
||||
ElementTypeConst.Grass = &ElementTypeValue{
|
||||
3,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_GRASS_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_GRASS_ENERGY,
|
||||
0,
|
||||
"",
|
||||
endec.Hk4eAbilityHashCode(""),
|
||||
}
|
||||
ElementTypeConst.Electric = &ElementTypeValue{
|
||||
4,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_ELEC_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_ELEC_ENERGY,
|
||||
10401,
|
||||
"TeamResonance_Electric_Lv2",
|
||||
endec.Hk4eAbilityHashCode("TeamResonance_Electric_Lv2"),
|
||||
}
|
||||
ElementTypeConst.Ice = &ElementTypeValue{
|
||||
5,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_ICE_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_ICE_ENERGY,
|
||||
10601,
|
||||
"TeamResonance_Ice_Lv2",
|
||||
endec.Hk4eAbilityHashCode("TeamResonance_Ice_Lv2"),
|
||||
}
|
||||
ElementTypeConst.Frozen = &ElementTypeValue{
|
||||
6,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_ICE_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_ICE_ENERGY,
|
||||
0,
|
||||
"",
|
||||
endec.Hk4eAbilityHashCode(""),
|
||||
}
|
||||
ElementTypeConst.Wind = &ElementTypeValue{
|
||||
7,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_WIND_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_WIND_ENERGY,
|
||||
10301,
|
||||
"TeamResonance_Wind_Lv2",
|
||||
endec.Hk4eAbilityHashCode("TeamResonance_Wind_Lv2"),
|
||||
}
|
||||
ElementTypeConst.Rock = &ElementTypeValue{
|
||||
8,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_ROCK_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_ROCK_ENERGY,
|
||||
10701,
|
||||
"TeamResonance_Rock_Lv2",
|
||||
endec.Hk4eAbilityHashCode("TeamResonance_Rock_Lv2"),
|
||||
}
|
||||
ElementTypeConst.AntiFire = &ElementTypeValue{
|
||||
9,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_FIRE_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_FIRE_ENERGY,
|
||||
0,
|
||||
"",
|
||||
endec.Hk4eAbilityHashCode(""),
|
||||
}
|
||||
ElementTypeConst.Default = &ElementTypeValue{
|
||||
255,
|
||||
FightPropertyConst.FIGHT_PROP_CUR_FIRE_ENERGY,
|
||||
FightPropertyConst.FIGHT_PROP_MAX_FIRE_ENERGY,
|
||||
10801,
|
||||
"TeamResonance_AllDifferent",
|
||||
endec.Hk4eAbilityHashCode("TeamResonance_AllDifferent"),
|
||||
}
|
||||
|
||||
ElementTypeConst.STRING_MAP = make(map[string]*ElementTypeValue)
|
||||
|
||||
ElementTypeConst.STRING_MAP["None"] = ElementTypeConst.None
|
||||
ElementTypeConst.STRING_MAP["Fire"] = ElementTypeConst.Fire
|
||||
ElementTypeConst.STRING_MAP["Water"] = ElementTypeConst.Water
|
||||
ElementTypeConst.STRING_MAP["Grass"] = ElementTypeConst.Grass
|
||||
ElementTypeConst.STRING_MAP["Electric"] = ElementTypeConst.Electric
|
||||
ElementTypeConst.STRING_MAP["Ice"] = ElementTypeConst.Ice
|
||||
ElementTypeConst.STRING_MAP["Frozen"] = ElementTypeConst.Frozen
|
||||
ElementTypeConst.STRING_MAP["Wind"] = ElementTypeConst.Wind
|
||||
ElementTypeConst.STRING_MAP["Rock"] = ElementTypeConst.Rock
|
||||
ElementTypeConst.STRING_MAP["AntiFire"] = ElementTypeConst.AntiFire
|
||||
ElementTypeConst.STRING_MAP["Default"] = ElementTypeConst.Default
|
||||
|
||||
ElementTypeConst.VALUE_MAP = make(map[uint16]*ElementTypeValue)
|
||||
|
||||
ElementTypeConst.VALUE_MAP[0] = ElementTypeConst.None
|
||||
ElementTypeConst.VALUE_MAP[1] = ElementTypeConst.Fire
|
||||
ElementTypeConst.VALUE_MAP[2] = ElementTypeConst.Water
|
||||
ElementTypeConst.VALUE_MAP[3] = ElementTypeConst.Grass
|
||||
ElementTypeConst.VALUE_MAP[4] = ElementTypeConst.Electric
|
||||
ElementTypeConst.VALUE_MAP[5] = ElementTypeConst.Ice
|
||||
ElementTypeConst.VALUE_MAP[6] = ElementTypeConst.Frozen
|
||||
ElementTypeConst.VALUE_MAP[7] = ElementTypeConst.Wind
|
||||
ElementTypeConst.VALUE_MAP[8] = ElementTypeConst.Rock
|
||||
ElementTypeConst.VALUE_MAP[9] = ElementTypeConst.AntiFire
|
||||
ElementTypeConst.VALUE_MAP[255] = ElementTypeConst.Default
|
||||
}
|
||||
75
service/game-hk4e/constant/enter_reason.go
Normal file
75
service/game-hk4e/constant/enter_reason.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package constant
|
||||
|
||||
var EnterReasonConst *EnterReason
|
||||
|
||||
type EnterReason struct {
|
||||
None uint16
|
||||
Login uint16
|
||||
DungeonReplay uint16
|
||||
DungeonReviveOnWaypoint uint16
|
||||
DungeonEnter uint16
|
||||
DungeonQuit uint16
|
||||
Gm uint16
|
||||
QuestRollback uint16
|
||||
Revival uint16
|
||||
PersonalScene uint16
|
||||
TransPoint uint16
|
||||
ClientTransmit uint16
|
||||
ForceDragBack uint16
|
||||
TeamKick uint16
|
||||
TeamJoin uint16
|
||||
TeamBack uint16
|
||||
Muip uint16
|
||||
DungeonInviteAccept uint16
|
||||
Lua uint16
|
||||
ActivityLoadTerrain uint16
|
||||
HostFromSingleToMp uint16
|
||||
MpPlay uint16
|
||||
AnchorPoint uint16
|
||||
LuaSkipUi uint16
|
||||
ReloadTerrain uint16
|
||||
DraftTransfer uint16
|
||||
EnterHome uint16
|
||||
ExitHome uint16
|
||||
ChangeHomeModule uint16
|
||||
Gallery uint16
|
||||
HomeSceneJump uint16
|
||||
HideAndSeek uint16
|
||||
}
|
||||
|
||||
func InitEnterReasonConst() {
|
||||
EnterReasonConst = new(EnterReason)
|
||||
|
||||
EnterReasonConst.None = 0
|
||||
EnterReasonConst.Login = 1
|
||||
EnterReasonConst.DungeonReplay = 11
|
||||
EnterReasonConst.DungeonReviveOnWaypoint = 12
|
||||
EnterReasonConst.DungeonEnter = 13
|
||||
EnterReasonConst.DungeonQuit = 14
|
||||
EnterReasonConst.Gm = 21
|
||||
EnterReasonConst.QuestRollback = 31
|
||||
EnterReasonConst.Revival = 32
|
||||
EnterReasonConst.PersonalScene = 41
|
||||
EnterReasonConst.TransPoint = 42
|
||||
EnterReasonConst.ClientTransmit = 43
|
||||
EnterReasonConst.ForceDragBack = 44
|
||||
EnterReasonConst.TeamKick = 51
|
||||
EnterReasonConst.TeamJoin = 52
|
||||
EnterReasonConst.TeamBack = 53
|
||||
EnterReasonConst.Muip = 54
|
||||
EnterReasonConst.DungeonInviteAccept = 55
|
||||
EnterReasonConst.Lua = 56
|
||||
EnterReasonConst.ActivityLoadTerrain = 57
|
||||
EnterReasonConst.HostFromSingleToMp = 58
|
||||
EnterReasonConst.MpPlay = 59
|
||||
EnterReasonConst.AnchorPoint = 60
|
||||
EnterReasonConst.LuaSkipUi = 61
|
||||
EnterReasonConst.ReloadTerrain = 62
|
||||
EnterReasonConst.DraftTransfer = 63
|
||||
EnterReasonConst.EnterHome = 64
|
||||
EnterReasonConst.ExitHome = 65
|
||||
EnterReasonConst.ChangeHomeModule = 66
|
||||
EnterReasonConst.Gallery = 67
|
||||
EnterReasonConst.HomeSceneJump = 68
|
||||
EnterReasonConst.HideAndSeek = 69
|
||||
}
|
||||
25
service/game-hk4e/constant/entity_id_type.go
Normal file
25
service/game-hk4e/constant/entity_id_type.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package constant
|
||||
|
||||
var EntityIdTypeConst *EntityIdType
|
||||
|
||||
type EntityIdType struct {
|
||||
AVATAR uint16
|
||||
MONSTER uint16
|
||||
NPC uint16
|
||||
GADGET uint16
|
||||
WEAPON uint16
|
||||
TEAM uint16
|
||||
MPLEVEL uint16
|
||||
}
|
||||
|
||||
func InitEntityIdTypeConst() {
|
||||
EntityIdTypeConst = new(EntityIdType)
|
||||
|
||||
EntityIdTypeConst.AVATAR = 0x01
|
||||
EntityIdTypeConst.MONSTER = 0x02
|
||||
EntityIdTypeConst.NPC = 0x03
|
||||
EntityIdTypeConst.GADGET = 0x04
|
||||
EntityIdTypeConst.WEAPON = 0x06
|
||||
EntityIdTypeConst.TEAM = 0x09
|
||||
EntityIdTypeConst.MPLEVEL = 0x0b
|
||||
}
|
||||
180
service/game-hk4e/constant/entity_type.go
Normal file
180
service/game-hk4e/constant/entity_type.go
Normal file
@@ -0,0 +1,180 @@
|
||||
package constant
|
||||
|
||||
var EntityTypeConst *EntityType
|
||||
|
||||
type EntityType struct {
|
||||
None uint16
|
||||
Avatar uint16
|
||||
Monster uint16
|
||||
Bullet uint16
|
||||
AttackPhyisicalUnit uint16
|
||||
AOE uint16
|
||||
Camera uint16
|
||||
EnviroArea uint16
|
||||
Equip uint16
|
||||
MonsterEquip uint16
|
||||
Grass uint16
|
||||
Level uint16
|
||||
NPC uint16
|
||||
TransPointFirst uint16
|
||||
TransPointFirstGadget uint16
|
||||
TransPointSecond uint16
|
||||
TransPointSecondGadget uint16
|
||||
DropItem uint16
|
||||
Field uint16
|
||||
Gadget uint16
|
||||
Water uint16
|
||||
GatherPoint uint16
|
||||
GatherObject uint16
|
||||
AirflowField uint16
|
||||
SpeedupField uint16
|
||||
Gear uint16
|
||||
Chest uint16
|
||||
EnergyBall uint16
|
||||
ElemCrystal uint16
|
||||
Timeline uint16
|
||||
Worktop uint16
|
||||
Team uint16
|
||||
Platform uint16
|
||||
AmberWind uint16
|
||||
EnvAnimal uint16
|
||||
SealGadget uint16
|
||||
Tree uint16
|
||||
Bush uint16
|
||||
QuestGadget uint16
|
||||
Lightning uint16
|
||||
RewardPoint uint16
|
||||
RewardStatue uint16
|
||||
MPLevel uint16
|
||||
WindSeed uint16
|
||||
MpPlayRewardPoint uint16
|
||||
ViewPoint uint16
|
||||
RemoteAvatar uint16
|
||||
GeneralRewardPoint uint16
|
||||
PlayTeam uint16
|
||||
OfferingGadget uint16
|
||||
EyePoint uint16
|
||||
MiracleRing uint16
|
||||
Foundation uint16
|
||||
WidgetGadget uint16
|
||||
PlaceHolder uint16
|
||||
STRING_MAP map[string]uint16
|
||||
}
|
||||
|
||||
func InitEntityTypeConst() {
|
||||
EntityTypeConst = new(EntityType)
|
||||
|
||||
EntityTypeConst.None = 0
|
||||
EntityTypeConst.Avatar = 1
|
||||
EntityTypeConst.Monster = 2
|
||||
EntityTypeConst.Bullet = 3
|
||||
EntityTypeConst.AttackPhyisicalUnit = 4
|
||||
EntityTypeConst.AOE = 5
|
||||
EntityTypeConst.Camera = 6
|
||||
EntityTypeConst.EnviroArea = 7
|
||||
EntityTypeConst.Equip = 8
|
||||
EntityTypeConst.MonsterEquip = 9
|
||||
EntityTypeConst.Grass = 10
|
||||
EntityTypeConst.Level = 11
|
||||
EntityTypeConst.NPC = 12
|
||||
EntityTypeConst.TransPointFirst = 13
|
||||
EntityTypeConst.TransPointFirstGadget = 14
|
||||
EntityTypeConst.TransPointSecond = 15
|
||||
EntityTypeConst.TransPointSecondGadget = 16
|
||||
EntityTypeConst.DropItem = 17
|
||||
EntityTypeConst.Field = 18
|
||||
EntityTypeConst.Gadget = 19
|
||||
EntityTypeConst.Water = 20
|
||||
EntityTypeConst.GatherPoint = 21
|
||||
EntityTypeConst.GatherObject = 22
|
||||
EntityTypeConst.AirflowField = 23
|
||||
EntityTypeConst.SpeedupField = 24
|
||||
EntityTypeConst.Gear = 25
|
||||
EntityTypeConst.Chest = 26
|
||||
EntityTypeConst.EnergyBall = 27
|
||||
EntityTypeConst.ElemCrystal = 28
|
||||
EntityTypeConst.Timeline = 29
|
||||
EntityTypeConst.Worktop = 30
|
||||
EntityTypeConst.Team = 31
|
||||
EntityTypeConst.Platform = 32
|
||||
EntityTypeConst.AmberWind = 33
|
||||
EntityTypeConst.EnvAnimal = 34
|
||||
EntityTypeConst.SealGadget = 35
|
||||
EntityTypeConst.Tree = 36
|
||||
EntityTypeConst.Bush = 37
|
||||
EntityTypeConst.QuestGadget = 38
|
||||
EntityTypeConst.Lightning = 39
|
||||
EntityTypeConst.RewardPoint = 40
|
||||
EntityTypeConst.RewardStatue = 41
|
||||
EntityTypeConst.MPLevel = 42
|
||||
EntityTypeConst.WindSeed = 43
|
||||
EntityTypeConst.MpPlayRewardPoint = 44
|
||||
EntityTypeConst.ViewPoint = 45
|
||||
EntityTypeConst.RemoteAvatar = 46
|
||||
EntityTypeConst.GeneralRewardPoint = 47
|
||||
EntityTypeConst.PlayTeam = 48
|
||||
EntityTypeConst.OfferingGadget = 49
|
||||
EntityTypeConst.EyePoint = 50
|
||||
EntityTypeConst.MiracleRing = 51
|
||||
EntityTypeConst.Foundation = 52
|
||||
EntityTypeConst.WidgetGadget = 53
|
||||
EntityTypeConst.PlaceHolder = 99
|
||||
|
||||
EntityTypeConst.STRING_MAP = make(map[string]uint16)
|
||||
|
||||
EntityTypeConst.STRING_MAP["None"] = EntityTypeConst.None
|
||||
EntityTypeConst.STRING_MAP["Avatar"] = EntityTypeConst.Avatar
|
||||
EntityTypeConst.STRING_MAP["Monster"] = EntityTypeConst.Monster
|
||||
EntityTypeConst.STRING_MAP["Bullet"] = EntityTypeConst.Bullet
|
||||
EntityTypeConst.STRING_MAP["AttackPhyisicalUnit"] = EntityTypeConst.AttackPhyisicalUnit
|
||||
EntityTypeConst.STRING_MAP["AOE"] = EntityTypeConst.AOE
|
||||
EntityTypeConst.STRING_MAP["Camera"] = EntityTypeConst.Camera
|
||||
EntityTypeConst.STRING_MAP["EnviroArea"] = EntityTypeConst.EnviroArea
|
||||
EntityTypeConst.STRING_MAP["Equip"] = EntityTypeConst.Equip
|
||||
EntityTypeConst.STRING_MAP["MonsterEquip"] = EntityTypeConst.MonsterEquip
|
||||
EntityTypeConst.STRING_MAP["Grass"] = EntityTypeConst.Grass
|
||||
EntityTypeConst.STRING_MAP["Level"] = EntityTypeConst.Level
|
||||
EntityTypeConst.STRING_MAP["NPC"] = EntityTypeConst.NPC
|
||||
EntityTypeConst.STRING_MAP["TransPointFirst"] = EntityTypeConst.TransPointFirst
|
||||
EntityTypeConst.STRING_MAP["TransPointFirstGadget"] = EntityTypeConst.TransPointFirstGadget
|
||||
EntityTypeConst.STRING_MAP["TransPointSecond"] = EntityTypeConst.TransPointSecond
|
||||
EntityTypeConst.STRING_MAP["TransPointSecondGadget"] = EntityTypeConst.TransPointSecondGadget
|
||||
EntityTypeConst.STRING_MAP["DropItem"] = EntityTypeConst.DropItem
|
||||
EntityTypeConst.STRING_MAP["Field"] = EntityTypeConst.Field
|
||||
EntityTypeConst.STRING_MAP["Gadget"] = EntityTypeConst.Gadget
|
||||
EntityTypeConst.STRING_MAP["Water"] = EntityTypeConst.Water
|
||||
EntityTypeConst.STRING_MAP["GatherPoint"] = EntityTypeConst.GatherPoint
|
||||
EntityTypeConst.STRING_MAP["GatherObject"] = EntityTypeConst.GatherObject
|
||||
EntityTypeConst.STRING_MAP["AirflowField"] = EntityTypeConst.AirflowField
|
||||
EntityTypeConst.STRING_MAP["SpeedupField"] = EntityTypeConst.SpeedupField
|
||||
EntityTypeConst.STRING_MAP["Gear"] = EntityTypeConst.Gear
|
||||
EntityTypeConst.STRING_MAP["Chest"] = EntityTypeConst.Chest
|
||||
EntityTypeConst.STRING_MAP["EnergyBall"] = EntityTypeConst.EnergyBall
|
||||
EntityTypeConst.STRING_MAP["ElemCrystal"] = EntityTypeConst.ElemCrystal
|
||||
EntityTypeConst.STRING_MAP["Timeline"] = EntityTypeConst.Timeline
|
||||
EntityTypeConst.STRING_MAP["Worktop"] = EntityTypeConst.Worktop
|
||||
EntityTypeConst.STRING_MAP["Team"] = EntityTypeConst.Team
|
||||
EntityTypeConst.STRING_MAP["Platform"] = EntityTypeConst.Platform
|
||||
EntityTypeConst.STRING_MAP["AmberWind"] = EntityTypeConst.AmberWind
|
||||
EntityTypeConst.STRING_MAP["EnvAnimal"] = EntityTypeConst.EnvAnimal
|
||||
EntityTypeConst.STRING_MAP["SealGadget"] = EntityTypeConst.SealGadget
|
||||
EntityTypeConst.STRING_MAP["Tree"] = EntityTypeConst.Tree
|
||||
EntityTypeConst.STRING_MAP["Bush"] = EntityTypeConst.Bush
|
||||
EntityTypeConst.STRING_MAP["QuestGadget"] = EntityTypeConst.QuestGadget
|
||||
EntityTypeConst.STRING_MAP["Lightning"] = EntityTypeConst.Lightning
|
||||
EntityTypeConst.STRING_MAP["RewardPoint"] = EntityTypeConst.RewardPoint
|
||||
EntityTypeConst.STRING_MAP["RewardStatue"] = EntityTypeConst.RewardStatue
|
||||
EntityTypeConst.STRING_MAP["MPLevel"] = EntityTypeConst.MPLevel
|
||||
EntityTypeConst.STRING_MAP["WindSeed"] = EntityTypeConst.WindSeed
|
||||
EntityTypeConst.STRING_MAP["MpPlayRewardPoint"] = EntityTypeConst.MpPlayRewardPoint
|
||||
EntityTypeConst.STRING_MAP["ViewPoint"] = EntityTypeConst.ViewPoint
|
||||
EntityTypeConst.STRING_MAP["RemoteAvatar"] = EntityTypeConst.RemoteAvatar
|
||||
EntityTypeConst.STRING_MAP["GeneralRewardPoint"] = EntityTypeConst.GeneralRewardPoint
|
||||
EntityTypeConst.STRING_MAP["PlayTeam"] = EntityTypeConst.PlayTeam
|
||||
EntityTypeConst.STRING_MAP["OfferingGadget"] = EntityTypeConst.OfferingGadget
|
||||
EntityTypeConst.STRING_MAP["EyePoint"] = EntityTypeConst.EyePoint
|
||||
EntityTypeConst.STRING_MAP["MiracleRing"] = EntityTypeConst.MiracleRing
|
||||
EntityTypeConst.STRING_MAP["Foundation"] = EntityTypeConst.Foundation
|
||||
EntityTypeConst.STRING_MAP["WidgetGadget"] = EntityTypeConst.WidgetGadget
|
||||
EntityTypeConst.STRING_MAP["PlaceHolder"] = EntityTypeConst.PlaceHolder
|
||||
}
|
||||
36
service/game-hk4e/constant/equip_type.go
Normal file
36
service/game-hk4e/constant/equip_type.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package constant
|
||||
|
||||
var EquipTypeConst *EquipType
|
||||
|
||||
type EquipType struct {
|
||||
EQUIP_NONE uint16
|
||||
EQUIP_BRACER uint16
|
||||
EQUIP_NECKLACE uint16
|
||||
EQUIP_SHOES uint16
|
||||
EQUIP_RING uint16
|
||||
EQUIP_DRESS uint16
|
||||
EQUIP_WEAPON uint16
|
||||
STRING_MAP map[string]uint16
|
||||
}
|
||||
|
||||
func InitEquipTypeConst() {
|
||||
EquipTypeConst = new(EquipType)
|
||||
|
||||
EquipTypeConst.EQUIP_NONE = 0
|
||||
EquipTypeConst.EQUIP_BRACER = 1
|
||||
EquipTypeConst.EQUIP_NECKLACE = 2
|
||||
EquipTypeConst.EQUIP_SHOES = 3
|
||||
EquipTypeConst.EQUIP_RING = 4
|
||||
EquipTypeConst.EQUIP_DRESS = 5
|
||||
EquipTypeConst.EQUIP_WEAPON = 6
|
||||
|
||||
EquipTypeConst.STRING_MAP = make(map[string]uint16)
|
||||
|
||||
EquipTypeConst.STRING_MAP["EQUIP_NONE"] = 0
|
||||
EquipTypeConst.STRING_MAP["EQUIP_BRACER"] = 1
|
||||
EquipTypeConst.STRING_MAP["EQUIP_NECKLACE"] = 2
|
||||
EquipTypeConst.STRING_MAP["EQUIP_SHOES"] = 3
|
||||
EquipTypeConst.STRING_MAP["EQUIP_RING"] = 4
|
||||
EquipTypeConst.STRING_MAP["EQUIP_DRESS"] = 5
|
||||
EquipTypeConst.STRING_MAP["EQUIP_WEAPON"] = 6
|
||||
}
|
||||
19
service/game-hk4e/constant/fetter_state.go
Normal file
19
service/game-hk4e/constant/fetter_state.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package constant
|
||||
|
||||
var FetterStateConst *FetterState
|
||||
|
||||
type FetterState struct {
|
||||
NONE uint16
|
||||
NOT_OPEN uint16
|
||||
OPEN uint16
|
||||
FINISH uint16
|
||||
}
|
||||
|
||||
func InitFetterStateConst() {
|
||||
FetterStateConst = new(FetterState)
|
||||
|
||||
FetterStateConst.NONE = 0
|
||||
FetterStateConst.NOT_OPEN = 1
|
||||
FetterStateConst.OPEN = 1
|
||||
FetterStateConst.FINISH = 3
|
||||
}
|
||||
303
service/game-hk4e/constant/fight_property.go
Normal file
303
service/game-hk4e/constant/fight_property.go
Normal file
@@ -0,0 +1,303 @@
|
||||
package constant
|
||||
|
||||
var FightPropertyConst *FightProperty
|
||||
|
||||
type FightProperty struct {
|
||||
FIGHT_PROP_NONE uint16
|
||||
FIGHT_PROP_BASE_HP uint16
|
||||
FIGHT_PROP_HP uint16
|
||||
FIGHT_PROP_HP_PERCENT uint16
|
||||
FIGHT_PROP_BASE_ATTACK uint16
|
||||
FIGHT_PROP_ATTACK uint16
|
||||
FIGHT_PROP_ATTACK_PERCENT uint16
|
||||
FIGHT_PROP_BASE_DEFENSE uint16
|
||||
FIGHT_PROP_DEFENSE uint16
|
||||
FIGHT_PROP_DEFENSE_PERCENT uint16
|
||||
FIGHT_PROP_BASE_SPEED uint16
|
||||
FIGHT_PROP_SPEED_PERCENT uint16
|
||||
FIGHT_PROP_HP_MP_PERCENT uint16
|
||||
FIGHT_PROP_ATTACK_MP_PERCENT uint16
|
||||
FIGHT_PROP_CRITICAL uint16
|
||||
FIGHT_PROP_ANTI_CRITICAL uint16
|
||||
FIGHT_PROP_CRITICAL_HURT uint16
|
||||
FIGHT_PROP_CHARGE_EFFICIENCY uint16
|
||||
FIGHT_PROP_ADD_HURT uint16
|
||||
FIGHT_PROP_SUB_HURT uint16
|
||||
FIGHT_PROP_HEAL_ADD uint16
|
||||
FIGHT_PROP_HEALED_ADD uint16
|
||||
FIGHT_PROP_ELEMENT_MASTERY uint16
|
||||
FIGHT_PROP_PHYSICAL_SUB_HURT uint16
|
||||
FIGHT_PROP_PHYSICAL_ADD_HURT uint16
|
||||
FIGHT_PROP_DEFENCE_IGNORE_RATIO uint16
|
||||
FIGHT_PROP_DEFENCE_IGNORE_DELTA uint16
|
||||
FIGHT_PROP_FIRE_ADD_HURT uint16
|
||||
FIGHT_PROP_ELEC_ADD_HURT uint16
|
||||
FIGHT_PROP_WATER_ADD_HURT uint16
|
||||
FIGHT_PROP_GRASS_ADD_HURT uint16
|
||||
FIGHT_PROP_WIND_ADD_HURT uint16
|
||||
FIGHT_PROP_ROCK_ADD_HURT uint16
|
||||
FIGHT_PROP_ICE_ADD_HURT uint16
|
||||
FIGHT_PROP_HIT_HEAD_ADD_HURT uint16
|
||||
FIGHT_PROP_FIRE_SUB_HURT uint16
|
||||
FIGHT_PROP_ELEC_SUB_HURT uint16
|
||||
FIGHT_PROP_WATER_SUB_HURT uint16
|
||||
FIGHT_PROP_GRASS_SUB_HURT uint16
|
||||
FIGHT_PROP_WIND_SUB_HURT uint16
|
||||
FIGHT_PROP_ROCK_SUB_HURT uint16
|
||||
FIGHT_PROP_ICE_SUB_HURT uint16
|
||||
FIGHT_PROP_EFFECT_HIT uint16
|
||||
FIGHT_PROP_EFFECT_RESIST uint16
|
||||
FIGHT_PROP_FREEZE_RESIST uint16
|
||||
FIGHT_PROP_TORPOR_RESIST uint16
|
||||
FIGHT_PROP_DIZZY_RESIST uint16
|
||||
FIGHT_PROP_FREEZE_SHORTEN uint16
|
||||
FIGHT_PROP_TORPOR_SHORTEN uint16
|
||||
FIGHT_PROP_DIZZY_SHORTEN uint16
|
||||
FIGHT_PROP_MAX_FIRE_ENERGY uint16
|
||||
FIGHT_PROP_MAX_ELEC_ENERGY uint16
|
||||
FIGHT_PROP_MAX_WATER_ENERGY uint16
|
||||
FIGHT_PROP_MAX_GRASS_ENERGY uint16
|
||||
FIGHT_PROP_MAX_WIND_ENERGY uint16
|
||||
FIGHT_PROP_MAX_ICE_ENERGY uint16
|
||||
FIGHT_PROP_MAX_ROCK_ENERGY uint16
|
||||
FIGHT_PROP_SKILL_CD_MINUS_RATIO uint16
|
||||
FIGHT_PROP_SHIELD_COST_MINUS_RATIO uint16
|
||||
FIGHT_PROP_CUR_FIRE_ENERGY uint16
|
||||
FIGHT_PROP_CUR_ELEC_ENERGY uint16
|
||||
FIGHT_PROP_CUR_WATER_ENERGY uint16
|
||||
FIGHT_PROP_CUR_GRASS_ENERGY uint16
|
||||
FIGHT_PROP_CUR_WIND_ENERGY uint16
|
||||
FIGHT_PROP_CUR_ICE_ENERGY uint16
|
||||
FIGHT_PROP_CUR_ROCK_ENERGY uint16
|
||||
FIGHT_PROP_CUR_HP uint16
|
||||
FIGHT_PROP_MAX_HP uint16
|
||||
FIGHT_PROP_CUR_ATTACK uint16
|
||||
FIGHT_PROP_CUR_DEFENSE uint16
|
||||
FIGHT_PROP_CUR_SPEED uint16
|
||||
FIGHT_PROP_NONEXTRA_ATTACK uint16
|
||||
FIGHT_PROP_NONEXTRA_DEFENSE uint16
|
||||
FIGHT_PROP_NONEXTRA_CRITICAL uint16
|
||||
FIGHT_PROP_NONEXTRA_ANTI_CRITICAL uint16
|
||||
FIGHT_PROP_NONEXTRA_CRITICAL_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY uint16
|
||||
FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY uint16
|
||||
FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_WATER_ADD_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_WIND_ADD_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_ICE_ADD_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_WATER_SUB_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_WIND_SUB_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_ICE_SUB_HURT uint16
|
||||
FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO uint16
|
||||
FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO uint16
|
||||
FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT uint16
|
||||
STRING_MAP map[string]uint16
|
||||
}
|
||||
|
||||
func InitFightPropertyConst() {
|
||||
FightPropertyConst = new(FightProperty)
|
||||
|
||||
FightPropertyConst.FIGHT_PROP_NONE = 0
|
||||
FightPropertyConst.FIGHT_PROP_BASE_HP = 1
|
||||
FightPropertyConst.FIGHT_PROP_HP = 2
|
||||
FightPropertyConst.FIGHT_PROP_HP_PERCENT = 3
|
||||
FightPropertyConst.FIGHT_PROP_BASE_ATTACK = 4
|
||||
FightPropertyConst.FIGHT_PROP_ATTACK = 5
|
||||
FightPropertyConst.FIGHT_PROP_ATTACK_PERCENT = 6
|
||||
FightPropertyConst.FIGHT_PROP_BASE_DEFENSE = 7
|
||||
FightPropertyConst.FIGHT_PROP_DEFENSE = 8
|
||||
FightPropertyConst.FIGHT_PROP_DEFENSE_PERCENT = 9
|
||||
FightPropertyConst.FIGHT_PROP_BASE_SPEED = 10
|
||||
FightPropertyConst.FIGHT_PROP_SPEED_PERCENT = 11
|
||||
FightPropertyConst.FIGHT_PROP_HP_MP_PERCENT = 12
|
||||
FightPropertyConst.FIGHT_PROP_ATTACK_MP_PERCENT = 13
|
||||
FightPropertyConst.FIGHT_PROP_CRITICAL = 20
|
||||
FightPropertyConst.FIGHT_PROP_ANTI_CRITICAL = 21
|
||||
FightPropertyConst.FIGHT_PROP_CRITICAL_HURT = 22
|
||||
FightPropertyConst.FIGHT_PROP_CHARGE_EFFICIENCY = 23
|
||||
FightPropertyConst.FIGHT_PROP_ADD_HURT = 24
|
||||
FightPropertyConst.FIGHT_PROP_SUB_HURT = 25
|
||||
FightPropertyConst.FIGHT_PROP_HEAL_ADD = 26
|
||||
FightPropertyConst.FIGHT_PROP_HEALED_ADD = 27
|
||||
FightPropertyConst.FIGHT_PROP_ELEMENT_MASTERY = 28
|
||||
FightPropertyConst.FIGHT_PROP_PHYSICAL_SUB_HURT = 29
|
||||
FightPropertyConst.FIGHT_PROP_PHYSICAL_ADD_HURT = 30
|
||||
FightPropertyConst.FIGHT_PROP_DEFENCE_IGNORE_RATIO = 31
|
||||
FightPropertyConst.FIGHT_PROP_DEFENCE_IGNORE_DELTA = 32
|
||||
FightPropertyConst.FIGHT_PROP_FIRE_ADD_HURT = 40
|
||||
FightPropertyConst.FIGHT_PROP_ELEC_ADD_HURT = 41
|
||||
FightPropertyConst.FIGHT_PROP_WATER_ADD_HURT = 42
|
||||
FightPropertyConst.FIGHT_PROP_GRASS_ADD_HURT = 43
|
||||
FightPropertyConst.FIGHT_PROP_WIND_ADD_HURT = 44
|
||||
FightPropertyConst.FIGHT_PROP_ROCK_ADD_HURT = 45
|
||||
FightPropertyConst.FIGHT_PROP_ICE_ADD_HURT = 46
|
||||
FightPropertyConst.FIGHT_PROP_HIT_HEAD_ADD_HURT = 47
|
||||
FightPropertyConst.FIGHT_PROP_FIRE_SUB_HURT = 50
|
||||
FightPropertyConst.FIGHT_PROP_ELEC_SUB_HURT = 51
|
||||
FightPropertyConst.FIGHT_PROP_WATER_SUB_HURT = 52
|
||||
FightPropertyConst.FIGHT_PROP_GRASS_SUB_HURT = 53
|
||||
FightPropertyConst.FIGHT_PROP_WIND_SUB_HURT = 54
|
||||
FightPropertyConst.FIGHT_PROP_ROCK_SUB_HURT = 55
|
||||
FightPropertyConst.FIGHT_PROP_ICE_SUB_HURT = 56
|
||||
FightPropertyConst.FIGHT_PROP_EFFECT_HIT = 60
|
||||
FightPropertyConst.FIGHT_PROP_EFFECT_RESIST = 61
|
||||
FightPropertyConst.FIGHT_PROP_FREEZE_RESIST = 62
|
||||
FightPropertyConst.FIGHT_PROP_TORPOR_RESIST = 63
|
||||
FightPropertyConst.FIGHT_PROP_DIZZY_RESIST = 64
|
||||
FightPropertyConst.FIGHT_PROP_FREEZE_SHORTEN = 65
|
||||
FightPropertyConst.FIGHT_PROP_TORPOR_SHORTEN = 66
|
||||
FightPropertyConst.FIGHT_PROP_DIZZY_SHORTEN = 67
|
||||
FightPropertyConst.FIGHT_PROP_MAX_FIRE_ENERGY = 70
|
||||
FightPropertyConst.FIGHT_PROP_MAX_ELEC_ENERGY = 71
|
||||
FightPropertyConst.FIGHT_PROP_MAX_WATER_ENERGY = 72
|
||||
FightPropertyConst.FIGHT_PROP_MAX_GRASS_ENERGY = 73
|
||||
FightPropertyConst.FIGHT_PROP_MAX_WIND_ENERGY = 74
|
||||
FightPropertyConst.FIGHT_PROP_MAX_ICE_ENERGY = 75
|
||||
FightPropertyConst.FIGHT_PROP_MAX_ROCK_ENERGY = 76
|
||||
FightPropertyConst.FIGHT_PROP_SKILL_CD_MINUS_RATIO = 80
|
||||
FightPropertyConst.FIGHT_PROP_SHIELD_COST_MINUS_RATIO = 81
|
||||
FightPropertyConst.FIGHT_PROP_CUR_FIRE_ENERGY = 1000
|
||||
FightPropertyConst.FIGHT_PROP_CUR_ELEC_ENERGY = 1001
|
||||
FightPropertyConst.FIGHT_PROP_CUR_WATER_ENERGY = 1002
|
||||
FightPropertyConst.FIGHT_PROP_CUR_GRASS_ENERGY = 1003
|
||||
FightPropertyConst.FIGHT_PROP_CUR_WIND_ENERGY = 1004
|
||||
FightPropertyConst.FIGHT_PROP_CUR_ICE_ENERGY = 1005
|
||||
FightPropertyConst.FIGHT_PROP_CUR_ROCK_ENERGY = 1006
|
||||
FightPropertyConst.FIGHT_PROP_CUR_HP = 1010
|
||||
FightPropertyConst.FIGHT_PROP_MAX_HP = 2000
|
||||
FightPropertyConst.FIGHT_PROP_CUR_ATTACK = 2001
|
||||
FightPropertyConst.FIGHT_PROP_CUR_DEFENSE = 2002
|
||||
FightPropertyConst.FIGHT_PROP_CUR_SPEED = 2003
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_ATTACK = 3000
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_DEFENSE = 3001
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_CRITICAL = 3002
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_ANTI_CRITICAL = 3003
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_CRITICAL_HURT = 3004
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY = 3005
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY = 3006
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT = 3007
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT = 3008
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT = 3009
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_WATER_ADD_HURT = 3010
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT = 3011
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_WIND_ADD_HURT = 3012
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT = 3013
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_ICE_ADD_HURT = 3014
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT = 3015
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT = 3016
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_WATER_SUB_HURT = 3017
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT = 3018
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_WIND_SUB_HURT = 3019
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT = 3020
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_ICE_SUB_HURT = 3021
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO = 3022
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO = 3023
|
||||
FightPropertyConst.FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT = 3024
|
||||
|
||||
FightPropertyConst.STRING_MAP = make(map[string]uint16)
|
||||
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONE"] = 0
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_BASE_HP"] = 1
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_HP"] = 2
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_HP_PERCENT"] = 3
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_BASE_ATTACK"] = 4
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ATTACK"] = 5
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ATTACK_PERCENT"] = 6
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_BASE_DEFENSE"] = 7
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_DEFENSE"] = 8
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_DEFENSE_PERCENT"] = 9
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_BASE_SPEED"] = 10
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_SPEED_PERCENT"] = 11
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_HP_MP_PERCENT"] = 12
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ATTACK_MP_PERCENT"] = 13
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CRITICAL"] = 20
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ANTI_CRITICAL"] = 21
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CRITICAL_HURT"] = 22
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CHARGE_EFFICIENCY"] = 23
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ADD_HURT"] = 24
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_SUB_HURT"] = 25
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_HEAL_ADD"] = 26
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_HEALED_ADD"] = 27
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ELEMENT_MASTERY"] = 28
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_PHYSICAL_SUB_HURT"] = 29
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_PHYSICAL_ADD_HURT"] = 30
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_DEFENCE_IGNORE_RATIO"] = 31
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_DEFENCE_IGNORE_DELTA"] = 32
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_FIRE_ADD_HURT"] = 40
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ELEC_ADD_HURT"] = 41
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_WATER_ADD_HURT"] = 42
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_GRASS_ADD_HURT"] = 43
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_WIND_ADD_HURT"] = 44
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ROCK_ADD_HURT"] = 45
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ICE_ADD_HURT"] = 46
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_HIT_HEAD_ADD_HURT"] = 47
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_FIRE_SUB_HURT"] = 50
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ELEC_SUB_HURT"] = 51
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_WATER_SUB_HURT"] = 52
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_GRASS_SUB_HURT"] = 53
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_WIND_SUB_HURT"] = 54
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ROCK_SUB_HURT"] = 55
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_ICE_SUB_HURT"] = 56
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_EFFECT_HIT"] = 60
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_EFFECT_RESIST"] = 61
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_FREEZE_RESIST"] = 62
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_TORPOR_RESIST"] = 63
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_DIZZY_RESIST"] = 64
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_FREEZE_SHORTEN"] = 65
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_TORPOR_SHORTEN"] = 66
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_DIZZY_SHORTEN"] = 67
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_MAX_FIRE_ENERGY"] = 70
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_MAX_ELEC_ENERGY"] = 71
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_MAX_WATER_ENERGY"] = 72
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_MAX_GRASS_ENERGY"] = 73
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_MAX_WIND_ENERGY"] = 74
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_MAX_ICE_ENERGY"] = 75
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_MAX_ROCK_ENERGY"] = 76
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_SKILL_CD_MINUS_RATIO"] = 80
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_SHIELD_COST_MINUS_RATIO"] = 81
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_FIRE_ENERGY"] = 1000
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_ELEC_ENERGY"] = 1001
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_WATER_ENERGY"] = 1002
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_GRASS_ENERGY"] = 1003
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_WIND_ENERGY"] = 1004
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_ICE_ENERGY"] = 1005
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_ROCK_ENERGY"] = 1006
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_HP"] = 1010
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_MAX_HP"] = 2000
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_ATTACK"] = 2001
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_DEFENSE"] = 2002
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_CUR_SPEED"] = 2003
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_ATTACK"] = 3000
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_DEFENSE"] = 3001
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_CRITICAL"] = 3002
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_ANTI_CRITICAL"] = 3003
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_CRITICAL_HURT"] = 3004
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY"] = 3005
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY"] = 3006
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT"] = 3007
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT"] = 3008
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT"] = 3009
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_WATER_ADD_HURT"] = 3010
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT"] = 3011
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_WIND_ADD_HURT"] = 3012
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT"] = 3013
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_ICE_ADD_HURT"] = 3014
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT"] = 3015
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT"] = 3016
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_WATER_SUB_HURT"] = 3017
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT"] = 3018
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_WIND_SUB_HURT"] = 3019
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT"] = 3020
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_ICE_SUB_HURT"] = 3021
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO"] = 3022
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO"] = 3023
|
||||
FightPropertyConst.STRING_MAP["FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT"] = 3024
|
||||
}
|
||||
32
service/game-hk4e/constant/game_constant.go
Normal file
32
service/game-hk4e/constant/game_constant.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package constant
|
||||
|
||||
import "flswld.com/common/utils/endec"
|
||||
|
||||
var GameConstantConst *GameConstant
|
||||
|
||||
type GameConstant struct {
|
||||
DEFAULT_ABILITY_STRINGS []string
|
||||
DEFAULT_ABILITY_HASHES []int32
|
||||
DEFAULT_ABILITY_NAME int32
|
||||
}
|
||||
|
||||
func InitGameConstant() {
|
||||
GameConstantConst = new(GameConstant)
|
||||
|
||||
GameConstantConst.DEFAULT_ABILITY_STRINGS = []string{
|
||||
"Avatar_DefaultAbility_VisionReplaceDieInvincible",
|
||||
"Avatar_DefaultAbility_AvartarInShaderChange",
|
||||
"Avatar_SprintBS_Invincible",
|
||||
"Avatar_Freeze_Duration_Reducer",
|
||||
"Avatar_Attack_ReviveEnergy",
|
||||
"Avatar_Component_Initializer",
|
||||
"Avatar_FallAnthem_Achievement_Listener",
|
||||
}
|
||||
|
||||
GameConstantConst.DEFAULT_ABILITY_HASHES = make([]int32, 0)
|
||||
for _, v := range GameConstantConst.DEFAULT_ABILITY_STRINGS {
|
||||
GameConstantConst.DEFAULT_ABILITY_HASHES = append(GameConstantConst.DEFAULT_ABILITY_HASHES, endec.Hk4eAbilityHashCode(v))
|
||||
}
|
||||
|
||||
GameConstantConst.DEFAULT_ABILITY_NAME = endec.Hk4eAbilityHashCode("Default")
|
||||
}
|
||||
131
service/game-hk4e/constant/grow_curve.go
Normal file
131
service/game-hk4e/constant/grow_curve.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package constant
|
||||
|
||||
var GrowCurveConst *GrowCurve
|
||||
|
||||
type GrowCurve struct {
|
||||
GROW_CURVE_NONE uint16
|
||||
GROW_CURVE_HP uint16
|
||||
GROW_CURVE_ATTACK uint16
|
||||
GROW_CURVE_STAMINA uint16
|
||||
GROW_CURVE_STRIKE uint16
|
||||
GROW_CURVE_ANTI_STRIKE uint16
|
||||
GROW_CURVE_ANTI_STRIKE1 uint16
|
||||
GROW_CURVE_ANTI_STRIKE2 uint16
|
||||
GROW_CURVE_ANTI_STRIKE3 uint16
|
||||
GROW_CURVE_STRIKE_HURT uint16
|
||||
GROW_CURVE_ELEMENT uint16
|
||||
GROW_CURVE_KILL_EXP uint16
|
||||
GROW_CURVE_DEFENSE uint16
|
||||
GROW_CURVE_ATTACK_BOMB uint16
|
||||
GROW_CURVE_HP_LITTLEMONSTER uint16
|
||||
GROW_CURVE_ELEMENT_MASTERY uint16
|
||||
GROW_CURVE_PROGRESSION uint16
|
||||
GROW_CURVE_DEFENDING uint16
|
||||
GROW_CURVE_MHP uint16
|
||||
GROW_CURVE_MATK uint16
|
||||
GROW_CURVE_TOWERATK uint16
|
||||
GROW_CURVE_HP_S5 uint16
|
||||
GROW_CURVE_HP_S4 uint16
|
||||
GROW_CURVE_HP_2 uint16
|
||||
GROW_CURVE_ATTACK_S5 uint16
|
||||
GROW_CURVE_ATTACK_S4 uint16
|
||||
GROW_CURVE_ATTACK_S3 uint16
|
||||
GROW_CURVE_STRIKE_S5 uint16
|
||||
GROW_CURVE_DEFENSE_S5 uint16
|
||||
GROW_CURVE_DEFENSE_S4 uint16
|
||||
GROW_CURVE_ATTACK_101 uint16
|
||||
GROW_CURVE_ATTACK_102 uint16
|
||||
GROW_CURVE_ATTACK_103 uint16
|
||||
GROW_CURVE_ATTACK_104 uint16
|
||||
GROW_CURVE_ATTACK_105 uint16
|
||||
GROW_CURVE_ATTACK_201 uint16
|
||||
GROW_CURVE_ATTACK_202 uint16
|
||||
GROW_CURVE_ATTACK_203 uint16
|
||||
GROW_CURVE_ATTACK_204 uint16
|
||||
GROW_CURVE_ATTACK_205 uint16
|
||||
GROW_CURVE_ATTACK_301 uint16
|
||||
GROW_CURVE_ATTACK_302 uint16
|
||||
GROW_CURVE_ATTACK_303 uint16
|
||||
GROW_CURVE_ATTACK_304 uint16
|
||||
GROW_CURVE_ATTACK_305 uint16
|
||||
GROW_CURVE_CRITICAL_101 uint16
|
||||
GROW_CURVE_CRITICAL_102 uint16
|
||||
GROW_CURVE_CRITICAL_103 uint16
|
||||
GROW_CURVE_CRITICAL_104 uint16
|
||||
GROW_CURVE_CRITICAL_105 uint16
|
||||
GROW_CURVE_CRITICAL_201 uint16
|
||||
GROW_CURVE_CRITICAL_202 uint16
|
||||
GROW_CURVE_CRITICAL_203 uint16
|
||||
GROW_CURVE_CRITICAL_204 uint16
|
||||
GROW_CURVE_CRITICAL_205 uint16
|
||||
GROW_CURVE_CRITICAL_301 uint16
|
||||
GROW_CURVE_CRITICAL_302 uint16
|
||||
GROW_CURVE_CRITICAL_303 uint16
|
||||
GROW_CURVE_CRITICAL_304 uint16
|
||||
GROW_CURVE_CRITICAL_305 uint16
|
||||
}
|
||||
|
||||
func InitGrowCurveConst() {
|
||||
GrowCurveConst = new(GrowCurve)
|
||||
|
||||
GrowCurveConst.GROW_CURVE_NONE = 0
|
||||
GrowCurveConst.GROW_CURVE_HP = 1
|
||||
GrowCurveConst.GROW_CURVE_ATTACK = 2
|
||||
GrowCurveConst.GROW_CURVE_STAMINA = 3
|
||||
GrowCurveConst.GROW_CURVE_STRIKE = 4
|
||||
GrowCurveConst.GROW_CURVE_ANTI_STRIKE = 5
|
||||
GrowCurveConst.GROW_CURVE_ANTI_STRIKE1 = 6
|
||||
GrowCurveConst.GROW_CURVE_ANTI_STRIKE2 = 7
|
||||
GrowCurveConst.GROW_CURVE_ANTI_STRIKE3 = 8
|
||||
GrowCurveConst.GROW_CURVE_STRIKE_HURT = 9
|
||||
GrowCurveConst.GROW_CURVE_ELEMENT = 10
|
||||
GrowCurveConst.GROW_CURVE_KILL_EXP = 11
|
||||
GrowCurveConst.GROW_CURVE_DEFENSE = 12
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_BOMB = 13
|
||||
GrowCurveConst.GROW_CURVE_HP_LITTLEMONSTER = 14
|
||||
GrowCurveConst.GROW_CURVE_ELEMENT_MASTERY = 15
|
||||
GrowCurveConst.GROW_CURVE_PROGRESSION = 16
|
||||
GrowCurveConst.GROW_CURVE_DEFENDING = 17
|
||||
GrowCurveConst.GROW_CURVE_MHP = 18
|
||||
GrowCurveConst.GROW_CURVE_MATK = 19
|
||||
GrowCurveConst.GROW_CURVE_TOWERATK = 20
|
||||
GrowCurveConst.GROW_CURVE_HP_S5 = 21
|
||||
GrowCurveConst.GROW_CURVE_HP_S4 = 22
|
||||
GrowCurveConst.GROW_CURVE_HP_2 = 23
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_S5 = 31
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_S4 = 32
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_S3 = 33
|
||||
GrowCurveConst.GROW_CURVE_STRIKE_S5 = 34
|
||||
GrowCurveConst.GROW_CURVE_DEFENSE_S5 = 41
|
||||
GrowCurveConst.GROW_CURVE_DEFENSE_S4 = 42
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_101 = 1101
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_102 = 1102
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_103 = 1103
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_104 = 1104
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_105 = 1105
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_201 = 1201
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_202 = 1202
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_203 = 1203
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_204 = 1204
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_205 = 1205
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_301 = 1301
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_302 = 1302
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_303 = 1303
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_304 = 1304
|
||||
GrowCurveConst.GROW_CURVE_ATTACK_305 = 1305
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_101 = 2101
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_102 = 2102
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_103 = 2103
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_104 = 2104
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_105 = 2105
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_201 = 2201
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_202 = 2202
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_203 = 2203
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_204 = 2204
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_205 = 2205
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_301 = 2301
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_302 = 2302
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_303 = 2303
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_304 = 2304
|
||||
GrowCurveConst.GROW_CURVE_CRITICAL_305 = 2305
|
||||
}
|
||||
36
service/game-hk4e/constant/item_type.go
Normal file
36
service/game-hk4e/constant/item_type.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package constant
|
||||
|
||||
var ItemTypeConst *ItemType
|
||||
|
||||
type ItemType struct {
|
||||
ITEM_NONE uint16
|
||||
ITEM_VIRTUAL uint16
|
||||
ITEM_MATERIAL uint16
|
||||
ITEM_RELIQUARY uint16
|
||||
ITEM_WEAPON uint16
|
||||
ITEM_DISPLAY uint16
|
||||
ITEM_FURNITURE uint16
|
||||
STRING_MAP map[string]uint16
|
||||
}
|
||||
|
||||
func InitItemTypeConst() {
|
||||
ItemTypeConst = new(ItemType)
|
||||
|
||||
ItemTypeConst.ITEM_NONE = 0
|
||||
ItemTypeConst.ITEM_VIRTUAL = 1
|
||||
ItemTypeConst.ITEM_MATERIAL = 2
|
||||
ItemTypeConst.ITEM_RELIQUARY = 3
|
||||
ItemTypeConst.ITEM_WEAPON = 4
|
||||
ItemTypeConst.ITEM_DISPLAY = 5
|
||||
ItemTypeConst.ITEM_FURNITURE = 6
|
||||
|
||||
ItemTypeConst.STRING_MAP = make(map[string]uint16)
|
||||
|
||||
ItemTypeConst.STRING_MAP["ITEM_NONE"] = 0
|
||||
ItemTypeConst.STRING_MAP["ITEM_VIRTUAL"] = 1
|
||||
ItemTypeConst.STRING_MAP["ITEM_MATERIAL"] = 2
|
||||
ItemTypeConst.STRING_MAP["ITEM_RELIQUARY"] = 3
|
||||
ItemTypeConst.STRING_MAP["ITEM_WEAPON"] = 4
|
||||
ItemTypeConst.STRING_MAP["ITEM_DISPLAY"] = 5
|
||||
ItemTypeConst.STRING_MAP["ITEM_FURNITURE"] = 6
|
||||
}
|
||||
19
service/game-hk4e/constant/life_state.go
Normal file
19
service/game-hk4e/constant/life_state.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package constant
|
||||
|
||||
var LifeStateConst *LifeState
|
||||
|
||||
type LifeState struct {
|
||||
LIFE_NONE uint16
|
||||
LIFE_ALIVE uint16
|
||||
LIFE_DEAD uint16
|
||||
LIFE_REVIVE uint16
|
||||
}
|
||||
|
||||
func InitLifeStateConst() {
|
||||
LifeStateConst = new(LifeState)
|
||||
|
||||
LifeStateConst.LIFE_NONE = 0
|
||||
LifeStateConst.LIFE_ALIVE = 1
|
||||
LifeStateConst.LIFE_DEAD = 2
|
||||
LifeStateConst.LIFE_REVIVE = 3
|
||||
}
|
||||
102
service/game-hk4e/constant/material_type.go
Normal file
102
service/game-hk4e/constant/material_type.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package constant
|
||||
|
||||
var MaterialTypeConst *MaterialType
|
||||
|
||||
type MaterialType struct {
|
||||
MATERIAL_NONE uint16
|
||||
MATERIAL_FOOD uint16
|
||||
MATERIAL_QUEST uint16
|
||||
MATERIAL_EXCHANGE uint16
|
||||
MATERIAL_CONSUME uint16
|
||||
MATERIAL_EXP_FRUIT uint16
|
||||
MATERIAL_AVATAR uint16
|
||||
MATERIAL_ADSORBATE uint16
|
||||
MATERIAL_CRICKET uint16
|
||||
MATERIAL_ELEM_CRYSTAL uint16
|
||||
MATERIAL_WEAPON_EXP_STONE uint16
|
||||
MATERIAL_CHEST uint16
|
||||
MATERIAL_RELIQUARY_MATERIAL uint16
|
||||
MATERIAL_AVATAR_MATERIAL uint16
|
||||
MATERIAL_NOTICE_ADD_HP uint16
|
||||
MATERIAL_SEA_LAMP uint16
|
||||
MATERIAL_SELECTABLE_CHEST uint16
|
||||
MATERIAL_FLYCLOAK uint16
|
||||
MATERIAL_NAMECARD uint16
|
||||
MATERIAL_TALENT uint16
|
||||
MATERIAL_WIDGET uint16
|
||||
MATERIAL_CHEST_BATCH_USE uint16
|
||||
MATERIAL_FAKE_ABSORBATE uint16
|
||||
MATERIAL_CONSUME_BATCH_USE uint16
|
||||
MATERIAL_WOOD uint16
|
||||
MATERIAL_FURNITURE_FORMULA uint16
|
||||
MATERIAL_CHANNELLER_SLAB_BUFF uint16
|
||||
MATERIAL_FURNITURE_SUITE_FORMULA uint16
|
||||
MATERIAL_COSTUME uint16
|
||||
STRING_MAP map[string]uint16
|
||||
}
|
||||
|
||||
func InitMaterialTypeConst() {
|
||||
MaterialTypeConst = new(MaterialType)
|
||||
|
||||
MaterialTypeConst.MATERIAL_NONE = 0
|
||||
MaterialTypeConst.MATERIAL_FOOD = 1
|
||||
MaterialTypeConst.MATERIAL_QUEST = 2
|
||||
MaterialTypeConst.MATERIAL_EXCHANGE = 4
|
||||
MaterialTypeConst.MATERIAL_CONSUME = 5
|
||||
MaterialTypeConst.MATERIAL_EXP_FRUIT = 6
|
||||
MaterialTypeConst.MATERIAL_AVATAR = 7
|
||||
MaterialTypeConst.MATERIAL_ADSORBATE = 8
|
||||
MaterialTypeConst.MATERIAL_CRICKET = 9
|
||||
MaterialTypeConst.MATERIAL_ELEM_CRYSTAL = 10
|
||||
MaterialTypeConst.MATERIAL_WEAPON_EXP_STONE = 11
|
||||
MaterialTypeConst.MATERIAL_CHEST = 12
|
||||
MaterialTypeConst.MATERIAL_RELIQUARY_MATERIAL = 13
|
||||
MaterialTypeConst.MATERIAL_AVATAR_MATERIAL = 14
|
||||
MaterialTypeConst.MATERIAL_NOTICE_ADD_HP = 15
|
||||
MaterialTypeConst.MATERIAL_SEA_LAMP = 16
|
||||
MaterialTypeConst.MATERIAL_SELECTABLE_CHEST = 17
|
||||
MaterialTypeConst.MATERIAL_FLYCLOAK = 18
|
||||
MaterialTypeConst.MATERIAL_NAMECARD = 19
|
||||
MaterialTypeConst.MATERIAL_TALENT = 20
|
||||
MaterialTypeConst.MATERIAL_WIDGET = 21
|
||||
MaterialTypeConst.MATERIAL_CHEST_BATCH_USE = 22
|
||||
MaterialTypeConst.MATERIAL_FAKE_ABSORBATE = 23
|
||||
MaterialTypeConst.MATERIAL_CONSUME_BATCH_USE = 24
|
||||
MaterialTypeConst.MATERIAL_WOOD = 25
|
||||
MaterialTypeConst.MATERIAL_FURNITURE_FORMULA = 27
|
||||
MaterialTypeConst.MATERIAL_CHANNELLER_SLAB_BUFF = 28
|
||||
MaterialTypeConst.MATERIAL_FURNITURE_SUITE_FORMULA = 29
|
||||
MaterialTypeConst.MATERIAL_COSTUME = 30
|
||||
|
||||
MaterialTypeConst.STRING_MAP = make(map[string]uint16)
|
||||
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_NONE"] = 0
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_FOOD"] = 1
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_QUEST"] = 2
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_EXCHANGE"] = 4
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_CONSUME"] = 5
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_EXP_FRUIT"] = 6
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_AVATAR"] = 7
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_ADSORBATE"] = 8
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_CRICKET"] = 9
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_ELEM_CRYSTAL"] = 10
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_WEAPON_EXP_STONE"] = 11
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_CHEST"] = 12
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_RELIQUARY_MATERIAL"] = 13
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_AVATAR_MATERIAL"] = 14
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_NOTICE_ADD_HP"] = 15
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_SEA_LAMP"] = 16
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_SELECTABLE_CHEST"] = 17
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_FLYCLOAK"] = 18
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_NAMECARD"] = 19
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_TALENT"] = 20
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_WIDGET"] = 21
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_CHEST_BATCH_USE"] = 22
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_FAKE_ABSORBATE"] = 23
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_CONSUME_BATCH_USE"] = 24
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_WOOD"] = 25
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_FURNITURE_FORMULA"] = 27
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_CHANNELLER_SLAB_BUFF"] = 28
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_FURNITURE_SUITE_FORMULA"] = 29
|
||||
MaterialTypeConst.STRING_MAP["MATERIAL_COSTUME"] = 30
|
||||
}
|
||||
343
service/game-hk4e/constant/open_state.go
Normal file
343
service/game-hk4e/constant/open_state.go
Normal file
@@ -0,0 +1,343 @@
|
||||
package constant
|
||||
|
||||
var OpenStateConst *OpenState
|
||||
|
||||
type OpenState struct {
|
||||
OPEN_STATE_NONE uint16
|
||||
OPEN_STATE_PAIMON uint16
|
||||
OPEN_STATE_PAIMON_NAVIGATION uint16
|
||||
OPEN_STATE_AVATAR_PROMOTE uint16
|
||||
OPEN_STATE_AVATAR_TALENT uint16
|
||||
OPEN_STATE_WEAPON_PROMOTE uint16
|
||||
OPEN_STATE_WEAPON_AWAKEN uint16
|
||||
OPEN_STATE_QUEST_REMIND uint16
|
||||
OPEN_STATE_GAME_GUIDE uint16
|
||||
OPEN_STATE_COOK uint16
|
||||
OPEN_STATE_WEAPON_UPGRADE uint16
|
||||
OPEN_STATE_RELIQUARY_UPGRADE uint16
|
||||
OPEN_STATE_RELIQUARY_PROMOTE uint16
|
||||
OPEN_STATE_WEAPON_PROMOTE_GUIDE uint16
|
||||
OPEN_STATE_WEAPON_CHANGE_GUIDE uint16
|
||||
OPEN_STATE_PLAYER_LVUP_GUIDE uint16
|
||||
OPEN_STATE_FRESHMAN_GUIDE uint16
|
||||
OPEN_STATE_SKIP_FRESHMAN_GUIDE uint16
|
||||
OPEN_STATE_GUIDE_MOVE_CAMERA uint16
|
||||
OPEN_STATE_GUIDE_SCALE_CAMERA uint16
|
||||
OPEN_STATE_GUIDE_KEYBOARD uint16
|
||||
OPEN_STATE_GUIDE_MOVE uint16
|
||||
OPEN_STATE_GUIDE_JUMP uint16
|
||||
OPEN_STATE_GUIDE_SPRINT uint16
|
||||
OPEN_STATE_GUIDE_MAP uint16
|
||||
OPEN_STATE_GUIDE_ATTACK uint16
|
||||
OPEN_STATE_GUIDE_FLY uint16
|
||||
OPEN_STATE_GUIDE_TALENT uint16
|
||||
OPEN_STATE_GUIDE_RELIC uint16
|
||||
OPEN_STATE_GUIDE_RELIC_PROM uint16
|
||||
OPEN_STATE_COMBINE uint16
|
||||
OPEN_STATE_GACHA uint16
|
||||
OPEN_STATE_GUIDE_GACHA uint16
|
||||
OPEN_STATE_GUIDE_TEAM uint16
|
||||
OPEN_STATE_GUIDE_PROUD uint16
|
||||
OPEN_STATE_GUIDE_AVATAR_PROMOTE uint16
|
||||
OPEN_STATE_GUIDE_ADVENTURE_CARD uint16
|
||||
OPEN_STATE_FORGE uint16
|
||||
OPEN_STATE_GUIDE_BAG uint16
|
||||
OPEN_STATE_EXPEDITION uint16
|
||||
OPEN_STATE_GUIDE_ADVENTURE_DAILYTASK uint16
|
||||
OPEN_STATE_GUIDE_ADVENTURE_DUNGEON uint16
|
||||
OPEN_STATE_TOWER uint16
|
||||
OPEN_STATE_WORLD_STAMINA uint16
|
||||
OPEN_STATE_TOWER_FIRST_ENTER uint16
|
||||
OPEN_STATE_RESIN uint16
|
||||
OPEN_STATE_LIMIT_REGION_FRESHMEAT uint16
|
||||
OPEN_STATE_LIMIT_REGION_GLOBAL uint16
|
||||
OPEN_STATE_MULTIPLAYER uint16
|
||||
OPEN_STATE_GUIDE_MOUSEPC uint16
|
||||
OPEN_STATE_GUIDE_MULTIPLAYER uint16
|
||||
OPEN_STATE_GUIDE_DUNGEONREWARD uint16
|
||||
OPEN_STATE_GUIDE_BLOSSOM uint16
|
||||
OPEN_STATE_AVATAR_FASHION uint16
|
||||
OPEN_STATE_PHOTOGRAPH uint16
|
||||
OPEN_STATE_GUIDE_KSLQUEST uint16
|
||||
OPEN_STATE_PERSONAL_LINE uint16
|
||||
OPEN_STATE_GUIDE_PERSONAL_LINE uint16
|
||||
OPEN_STATE_GUIDE_APPEARANCE uint16
|
||||
OPEN_STATE_GUIDE_PROCESS uint16
|
||||
OPEN_STATE_GUIDE_PERSONAL_LINE_KEY uint16
|
||||
OPEN_STATE_GUIDE_WIDGET uint16
|
||||
OPEN_STATE_GUIDE_ACTIVITY_SKILL_ASTER uint16
|
||||
OPEN_STATE_GUIDE_COLDCLIMATE uint16
|
||||
OPEN_STATE_DERIVATIVE_MALL uint16
|
||||
OPEN_STATE_GUIDE_EXITMULTIPLAYER uint16
|
||||
OPEN_STATE_GUIDE_THEATREMACHANICUS_BUILD uint16
|
||||
OPEN_STATE_GUIDE_THEATREMACHANICUS_REBUILD uint16
|
||||
OPEN_STATE_GUIDE_THEATREMACHANICUS_CARD uint16
|
||||
OPEN_STATE_GUIDE_THEATREMACHANICUS_MONSTER uint16
|
||||
OPEN_STATE_GUIDE_THEATREMACHANICUS_MISSION_CHECK uint16
|
||||
OPEN_STATE_GUIDE_THEATREMACHANICUS_BUILD_SELECT uint16
|
||||
OPEN_STATE_GUIDE_THEATREMACHANICUS_CHALLENGE_START uint16
|
||||
OPEN_STATE_GUIDE_CONVERT uint16
|
||||
OPEN_STATE_GUIDE_THEATREMACHANICUS_MULTIPLAYER uint16
|
||||
OPEN_STATE_GUIDE_COOP_TASK uint16
|
||||
OPEN_STATE_GUIDE_HOMEWORLD_ADEPTIABODE uint16
|
||||
OPEN_STATE_GUIDE_HOMEWORLD_DEPLOY uint16
|
||||
OPEN_STATE_GUIDE_CHANNELLERSLAB_EQUIP uint16
|
||||
OPEN_STATE_GUIDE_CHANNELLERSLAB_MP_SOLUTION uint16
|
||||
OPEN_STATE_GUIDE_CHANNELLERSLAB_POWER uint16
|
||||
OPEN_STATE_GUIDE_HIDEANDSEEK_SKILL uint16
|
||||
OPEN_STATE_GUIDE_HOMEWORLD_MAPLIST uint16
|
||||
OPEN_STATE_GUIDE_RELICRESOLVE uint16
|
||||
OPEN_STATE_GUIDE_GGUIDE uint16
|
||||
OPEN_STATE_GUIDE_GGUIDE_HINT uint16
|
||||
OPEN_STATE_CITY_REPUATION_MENGDE uint16
|
||||
OPEN_STATE_CITY_REPUATION_LIYUE uint16
|
||||
OPEN_STATE_CITY_REPUATION_UI_HINT uint16
|
||||
OPEN_STATE_CITY_REPUATION_INAZUMA uint16
|
||||
OPEN_STATE_SHOP_TYPE_MALL uint16
|
||||
OPEN_STATE_SHOP_TYPE_RECOMMANDED uint16
|
||||
OPEN_STATE_SHOP_TYPE_GENESISCRYSTAL uint16
|
||||
OPEN_STATE_SHOP_TYPE_GIFTPACKAGE uint16
|
||||
OPEN_STATE_SHOP_TYPE_PAIMON uint16
|
||||
OPEN_STATE_SHOP_TYPE_CITY uint16
|
||||
OPEN_STATE_SHOP_TYPE_BLACKSMITH uint16
|
||||
OPEN_STATE_SHOP_TYPE_GROCERY uint16
|
||||
OPEN_STATE_SHOP_TYPE_FOOD uint16
|
||||
OPEN_STATE_SHOP_TYPE_SEA_LAMP uint16
|
||||
OPEN_STATE_SHOP_TYPE_VIRTUAL_SHOP uint16
|
||||
OPEN_STATE_SHOP_TYPE_LIYUE_GROCERY uint16
|
||||
OPEN_STATE_SHOP_TYPE_LIYUE_SOUVENIR uint16
|
||||
OPEN_STATE_SHOP_TYPE_LIYUE_RESTAURANT uint16
|
||||
OPEN_STATE_SHOP_TYPE_INAZUMA_SOUVENIR uint16
|
||||
OPEN_STATE_SHOP_TYPE_NPC_TOMOKI uint16
|
||||
OPEN_ADVENTURE_MANUAL uint16
|
||||
OPEN_ADVENTURE_MANUAL_CITY_MENGDE uint16
|
||||
OPEN_ADVENTURE_MANUAL_CITY_LIYUE uint16
|
||||
OPEN_ADVENTURE_MANUAL_MONSTER uint16
|
||||
OPEN_ADVENTURE_MANUAL_BOSS_DUNGEON uint16
|
||||
OPEN_STATE_ACTIVITY_SEALAMP uint16
|
||||
OPEN_STATE_ACTIVITY_SEALAMP_TAB2 uint16
|
||||
OPEN_STATE_ACTIVITY_SEALAMP_TAB3 uint16
|
||||
OPEN_STATE_BATTLE_PASS uint16
|
||||
OPEN_STATE_BATTLE_PASS_ENTRY uint16
|
||||
OPEN_STATE_ACTIVITY_CRUCIBLE uint16
|
||||
OPEN_STATE_ACTIVITY_NEWBEEBOUNS_OPEN uint16
|
||||
OPEN_STATE_ACTIVITY_NEWBEEBOUNS_CLOSE uint16
|
||||
OPEN_STATE_ACTIVITY_ENTRY_OPEN uint16
|
||||
OPEN_STATE_MENGDE_INFUSEDCRYSTAL uint16
|
||||
OPEN_STATE_LIYUE_INFUSEDCRYSTAL uint16
|
||||
OPEN_STATE_SNOW_MOUNTAIN_ELDER_TREE uint16
|
||||
OPEN_STATE_MIRACLE_RING uint16
|
||||
OPEN_STATE_COOP_LINE uint16
|
||||
OPEN_STATE_INAZUMA_INFUSEDCRYSTAL uint16
|
||||
OPEN_STATE_FISH uint16
|
||||
OPEN_STATE_GUIDE_SUMO_TEAM_SKILL uint16
|
||||
OPEN_STATE_GUIDE_FISH_RECIPE uint16
|
||||
OPEN_STATE_HOME uint16
|
||||
OPEN_STATE_ACTIVITY_HOMEWORLD uint16
|
||||
OPEN_STATE_ADEPTIABODE uint16
|
||||
OPEN_STATE_HOME_AVATAR uint16
|
||||
OPEN_STATE_HOME_EDIT uint16
|
||||
OPEN_STATE_HOME_EDIT_TIPS uint16
|
||||
OPEN_STATE_RELIQUARY_DECOMPOSE uint16
|
||||
OPEN_STATE_ACTIVITY_H5 uint16
|
||||
OPEN_STATE_ORAIONOKAMI uint16
|
||||
OPEN_STATE_GUIDE_CHESS_MISSION_CHECK uint16
|
||||
OPEN_STATE_GUIDE_CHESS_BUILD uint16
|
||||
OPEN_STATE_GUIDE_CHESS_WIND_TOWER_CIRCLE uint16
|
||||
OPEN_STATE_GUIDE_CHESS_CARD_SELECT uint16
|
||||
OPEN_STATE_INAZUMA_MAINQUEST_FINISHED uint16
|
||||
OPEN_STATE_PAIMON_LVINFO uint16
|
||||
OPEN_STATE_TELEPORT_HUD uint16
|
||||
OPEN_STATE_GUIDE_MAP_UNLOCK uint16
|
||||
OPEN_STATE_GUIDE_PAIMON_LVINFO uint16
|
||||
OPEN_STATE_GUIDE_AMBORTRANSPORT uint16
|
||||
OPEN_STATE_GUIDE_FLY_SECOND uint16
|
||||
OPEN_STATE_GUIDE_KAEYA_CLUE uint16
|
||||
OPEN_STATE_CAPTURE_CODEX uint16
|
||||
OPEN_STATE_ACTIVITY_FISH_OPEN uint16
|
||||
OPEN_STATE_ACTIVITY_FISH_CLOSE uint16
|
||||
OPEN_STATE_GUIDE_ROGUE_MAP uint16
|
||||
OPEN_STATE_GUIDE_ROGUE_RUNE uint16
|
||||
OPEN_STATE_GUIDE_BARTENDER_FORMULA uint16
|
||||
OPEN_STATE_GUIDE_BARTENDER_MIX uint16
|
||||
OPEN_STATE_GUIDE_BARTENDER_CUP uint16
|
||||
OPEN_STATE_GUIDE_MAIL_FAVORITES uint16
|
||||
OPEN_STATE_GUIDE_POTION_CONFIGURE uint16
|
||||
OPEN_STATE_GUIDE_LANV2_FIREWORK uint16
|
||||
OPEN_STATE_LOADINGTIPS_ENKANOMIYA uint16
|
||||
OPEN_STATE_MICHIAE_CASKET uint16
|
||||
OPEN_STATE_MAIL_COLLECT_UNLOCK_RED_POINT uint16
|
||||
OPEN_STATE_LUMEN_STONE uint16
|
||||
OPEN_STATE_GUIDE_CRYSTALLINK_BUFF uint16
|
||||
}
|
||||
|
||||
func InitOpenStateConst() {
|
||||
OpenStateConst = new(OpenState)
|
||||
|
||||
OpenStateConst.OPEN_STATE_NONE = 0
|
||||
OpenStateConst.OPEN_STATE_PAIMON = 1
|
||||
OpenStateConst.OPEN_STATE_PAIMON_NAVIGATION = 2
|
||||
OpenStateConst.OPEN_STATE_AVATAR_PROMOTE = 3
|
||||
OpenStateConst.OPEN_STATE_AVATAR_TALENT = 4
|
||||
OpenStateConst.OPEN_STATE_WEAPON_PROMOTE = 5
|
||||
OpenStateConst.OPEN_STATE_WEAPON_AWAKEN = 6
|
||||
OpenStateConst.OPEN_STATE_QUEST_REMIND = 7
|
||||
OpenStateConst.OPEN_STATE_GAME_GUIDE = 8
|
||||
OpenStateConst.OPEN_STATE_COOK = 9
|
||||
OpenStateConst.OPEN_STATE_WEAPON_UPGRADE = 10
|
||||
OpenStateConst.OPEN_STATE_RELIQUARY_UPGRADE = 11
|
||||
OpenStateConst.OPEN_STATE_RELIQUARY_PROMOTE = 12
|
||||
OpenStateConst.OPEN_STATE_WEAPON_PROMOTE_GUIDE = 13
|
||||
OpenStateConst.OPEN_STATE_WEAPON_CHANGE_GUIDE = 14
|
||||
OpenStateConst.OPEN_STATE_PLAYER_LVUP_GUIDE = 15
|
||||
OpenStateConst.OPEN_STATE_FRESHMAN_GUIDE = 16
|
||||
OpenStateConst.OPEN_STATE_SKIP_FRESHMAN_GUIDE = 17
|
||||
OpenStateConst.OPEN_STATE_GUIDE_MOVE_CAMERA = 18
|
||||
OpenStateConst.OPEN_STATE_GUIDE_SCALE_CAMERA = 19
|
||||
OpenStateConst.OPEN_STATE_GUIDE_KEYBOARD = 20
|
||||
OpenStateConst.OPEN_STATE_GUIDE_MOVE = 21
|
||||
OpenStateConst.OPEN_STATE_GUIDE_JUMP = 22
|
||||
OpenStateConst.OPEN_STATE_GUIDE_SPRINT = 23
|
||||
OpenStateConst.OPEN_STATE_GUIDE_MAP = 24
|
||||
OpenStateConst.OPEN_STATE_GUIDE_ATTACK = 25
|
||||
OpenStateConst.OPEN_STATE_GUIDE_FLY = 26
|
||||
OpenStateConst.OPEN_STATE_GUIDE_TALENT = 27
|
||||
OpenStateConst.OPEN_STATE_GUIDE_RELIC = 28
|
||||
OpenStateConst.OPEN_STATE_GUIDE_RELIC_PROM = 29
|
||||
OpenStateConst.OPEN_STATE_COMBINE = 30
|
||||
OpenStateConst.OPEN_STATE_GACHA = 31
|
||||
OpenStateConst.OPEN_STATE_GUIDE_GACHA = 32
|
||||
OpenStateConst.OPEN_STATE_GUIDE_TEAM = 33
|
||||
OpenStateConst.OPEN_STATE_GUIDE_PROUD = 34
|
||||
OpenStateConst.OPEN_STATE_GUIDE_AVATAR_PROMOTE = 35
|
||||
OpenStateConst.OPEN_STATE_GUIDE_ADVENTURE_CARD = 36
|
||||
OpenStateConst.OPEN_STATE_FORGE = 37
|
||||
OpenStateConst.OPEN_STATE_GUIDE_BAG = 38
|
||||
OpenStateConst.OPEN_STATE_EXPEDITION = 39
|
||||
OpenStateConst.OPEN_STATE_GUIDE_ADVENTURE_DAILYTASK = 40
|
||||
OpenStateConst.OPEN_STATE_GUIDE_ADVENTURE_DUNGEON = 41
|
||||
OpenStateConst.OPEN_STATE_TOWER = 42
|
||||
OpenStateConst.OPEN_STATE_WORLD_STAMINA = 43
|
||||
OpenStateConst.OPEN_STATE_TOWER_FIRST_ENTER = 44
|
||||
OpenStateConst.OPEN_STATE_RESIN = 45
|
||||
OpenStateConst.OPEN_STATE_LIMIT_REGION_FRESHMEAT = 47
|
||||
OpenStateConst.OPEN_STATE_LIMIT_REGION_GLOBAL = 48
|
||||
OpenStateConst.OPEN_STATE_MULTIPLAYER = 49
|
||||
OpenStateConst.OPEN_STATE_GUIDE_MOUSEPC = 50
|
||||
OpenStateConst.OPEN_STATE_GUIDE_MULTIPLAYER = 51
|
||||
OpenStateConst.OPEN_STATE_GUIDE_DUNGEONREWARD = 52
|
||||
OpenStateConst.OPEN_STATE_GUIDE_BLOSSOM = 53
|
||||
OpenStateConst.OPEN_STATE_AVATAR_FASHION = 54
|
||||
OpenStateConst.OPEN_STATE_PHOTOGRAPH = 55
|
||||
OpenStateConst.OPEN_STATE_GUIDE_KSLQUEST = 56
|
||||
OpenStateConst.OPEN_STATE_PERSONAL_LINE = 57
|
||||
OpenStateConst.OPEN_STATE_GUIDE_PERSONAL_LINE = 58
|
||||
OpenStateConst.OPEN_STATE_GUIDE_APPEARANCE = 59
|
||||
OpenStateConst.OPEN_STATE_GUIDE_PROCESS = 60
|
||||
OpenStateConst.OPEN_STATE_GUIDE_PERSONAL_LINE_KEY = 61
|
||||
OpenStateConst.OPEN_STATE_GUIDE_WIDGET = 62
|
||||
OpenStateConst.OPEN_STATE_GUIDE_ACTIVITY_SKILL_ASTER = 63
|
||||
OpenStateConst.OPEN_STATE_GUIDE_COLDCLIMATE = 64
|
||||
OpenStateConst.OPEN_STATE_DERIVATIVE_MALL = 65
|
||||
OpenStateConst.OPEN_STATE_GUIDE_EXITMULTIPLAYER = 66
|
||||
OpenStateConst.OPEN_STATE_GUIDE_THEATREMACHANICUS_BUILD = 67
|
||||
OpenStateConst.OPEN_STATE_GUIDE_THEATREMACHANICUS_REBUILD = 68
|
||||
OpenStateConst.OPEN_STATE_GUIDE_THEATREMACHANICUS_CARD = 69
|
||||
OpenStateConst.OPEN_STATE_GUIDE_THEATREMACHANICUS_MONSTER = 70
|
||||
OpenStateConst.OPEN_STATE_GUIDE_THEATREMACHANICUS_MISSION_CHECK = 71
|
||||
OpenStateConst.OPEN_STATE_GUIDE_THEATREMACHANICUS_BUILD_SELECT = 72
|
||||
OpenStateConst.OPEN_STATE_GUIDE_THEATREMACHANICUS_CHALLENGE_START = 73
|
||||
OpenStateConst.OPEN_STATE_GUIDE_CONVERT = 74
|
||||
OpenStateConst.OPEN_STATE_GUIDE_THEATREMACHANICUS_MULTIPLAYER = 75
|
||||
OpenStateConst.OPEN_STATE_GUIDE_COOP_TASK = 76
|
||||
OpenStateConst.OPEN_STATE_GUIDE_HOMEWORLD_ADEPTIABODE = 77
|
||||
OpenStateConst.OPEN_STATE_GUIDE_HOMEWORLD_DEPLOY = 78
|
||||
OpenStateConst.OPEN_STATE_GUIDE_CHANNELLERSLAB_EQUIP = 79
|
||||
OpenStateConst.OPEN_STATE_GUIDE_CHANNELLERSLAB_MP_SOLUTION = 80
|
||||
OpenStateConst.OPEN_STATE_GUIDE_CHANNELLERSLAB_POWER = 81
|
||||
OpenStateConst.OPEN_STATE_GUIDE_HIDEANDSEEK_SKILL = 82
|
||||
OpenStateConst.OPEN_STATE_GUIDE_HOMEWORLD_MAPLIST = 83
|
||||
OpenStateConst.OPEN_STATE_GUIDE_RELICRESOLVE = 84
|
||||
OpenStateConst.OPEN_STATE_GUIDE_GGUIDE = 85
|
||||
OpenStateConst.OPEN_STATE_GUIDE_GGUIDE_HINT = 86
|
||||
OpenStateConst.OPEN_STATE_CITY_REPUATION_MENGDE = 800
|
||||
OpenStateConst.OPEN_STATE_CITY_REPUATION_LIYUE = 801
|
||||
OpenStateConst.OPEN_STATE_CITY_REPUATION_UI_HINT = 802
|
||||
OpenStateConst.OPEN_STATE_CITY_REPUATION_INAZUMA = 803
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_MALL = 900
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_RECOMMANDED = 901
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_GENESISCRYSTAL = 902
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_GIFTPACKAGE = 903
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_PAIMON = 1001
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_CITY = 1002
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_BLACKSMITH = 1003
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_GROCERY = 1004
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_FOOD = 1005
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_SEA_LAMP = 1006
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_VIRTUAL_SHOP = 1007
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_LIYUE_GROCERY = 1008
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_LIYUE_SOUVENIR = 1009
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_LIYUE_RESTAURANT = 1010
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_INAZUMA_SOUVENIR = 1011
|
||||
OpenStateConst.OPEN_STATE_SHOP_TYPE_NPC_TOMOKI = 1012
|
||||
OpenStateConst.OPEN_ADVENTURE_MANUAL = 1100
|
||||
OpenStateConst.OPEN_ADVENTURE_MANUAL_CITY_MENGDE = 1101
|
||||
OpenStateConst.OPEN_ADVENTURE_MANUAL_CITY_LIYUE = 1102
|
||||
OpenStateConst.OPEN_ADVENTURE_MANUAL_MONSTER = 1103
|
||||
OpenStateConst.OPEN_ADVENTURE_MANUAL_BOSS_DUNGEON = 1104
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_SEALAMP = 1200
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_SEALAMP_TAB2 = 1201
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_SEALAMP_TAB3 = 1202
|
||||
OpenStateConst.OPEN_STATE_BATTLE_PASS = 1300
|
||||
OpenStateConst.OPEN_STATE_BATTLE_PASS_ENTRY = 1301
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_CRUCIBLE = 1400
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_NEWBEEBOUNS_OPEN = 1401
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_NEWBEEBOUNS_CLOSE = 1402
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_ENTRY_OPEN = 1403
|
||||
OpenStateConst.OPEN_STATE_MENGDE_INFUSEDCRYSTAL = 1404
|
||||
OpenStateConst.OPEN_STATE_LIYUE_INFUSEDCRYSTAL = 1405
|
||||
OpenStateConst.OPEN_STATE_SNOW_MOUNTAIN_ELDER_TREE = 1406
|
||||
OpenStateConst.OPEN_STATE_MIRACLE_RING = 1407
|
||||
OpenStateConst.OPEN_STATE_COOP_LINE = 1408
|
||||
OpenStateConst.OPEN_STATE_INAZUMA_INFUSEDCRYSTAL = 1409
|
||||
OpenStateConst.OPEN_STATE_FISH = 1410
|
||||
OpenStateConst.OPEN_STATE_GUIDE_SUMO_TEAM_SKILL = 1411
|
||||
OpenStateConst.OPEN_STATE_GUIDE_FISH_RECIPE = 1412
|
||||
OpenStateConst.OPEN_STATE_HOME = 1500
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_HOMEWORLD = 1501
|
||||
OpenStateConst.OPEN_STATE_ADEPTIABODE = 1502
|
||||
OpenStateConst.OPEN_STATE_HOME_AVATAR = 1503
|
||||
OpenStateConst.OPEN_STATE_HOME_EDIT = 1504
|
||||
OpenStateConst.OPEN_STATE_HOME_EDIT_TIPS = 1505
|
||||
OpenStateConst.OPEN_STATE_RELIQUARY_DECOMPOSE = 1600
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_H5 = 1700
|
||||
OpenStateConst.OPEN_STATE_ORAIONOKAMI = 2000
|
||||
OpenStateConst.OPEN_STATE_GUIDE_CHESS_MISSION_CHECK = 2001
|
||||
OpenStateConst.OPEN_STATE_GUIDE_CHESS_BUILD = 2002
|
||||
OpenStateConst.OPEN_STATE_GUIDE_CHESS_WIND_TOWER_CIRCLE = 2003
|
||||
OpenStateConst.OPEN_STATE_GUIDE_CHESS_CARD_SELECT = 2004
|
||||
OpenStateConst.OPEN_STATE_INAZUMA_MAINQUEST_FINISHED = 2005
|
||||
OpenStateConst.OPEN_STATE_PAIMON_LVINFO = 2100
|
||||
OpenStateConst.OPEN_STATE_TELEPORT_HUD = 2101
|
||||
OpenStateConst.OPEN_STATE_GUIDE_MAP_UNLOCK = 2102
|
||||
OpenStateConst.OPEN_STATE_GUIDE_PAIMON_LVINFO = 2103
|
||||
OpenStateConst.OPEN_STATE_GUIDE_AMBORTRANSPORT = 2104
|
||||
OpenStateConst.OPEN_STATE_GUIDE_FLY_SECOND = 2105
|
||||
OpenStateConst.OPEN_STATE_GUIDE_KAEYA_CLUE = 2106
|
||||
OpenStateConst.OPEN_STATE_CAPTURE_CODEX = 2107
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_FISH_OPEN = 2200
|
||||
OpenStateConst.OPEN_STATE_ACTIVITY_FISH_CLOSE = 2201
|
||||
OpenStateConst.OPEN_STATE_GUIDE_ROGUE_MAP = 2205
|
||||
OpenStateConst.OPEN_STATE_GUIDE_ROGUE_RUNE = 2206
|
||||
OpenStateConst.OPEN_STATE_GUIDE_BARTENDER_FORMULA = 2210
|
||||
OpenStateConst.OPEN_STATE_GUIDE_BARTENDER_MIX = 2211
|
||||
OpenStateConst.OPEN_STATE_GUIDE_BARTENDER_CUP = 2212
|
||||
OpenStateConst.OPEN_STATE_GUIDE_MAIL_FAVORITES = 2400
|
||||
OpenStateConst.OPEN_STATE_GUIDE_POTION_CONFIGURE = 2401
|
||||
OpenStateConst.OPEN_STATE_GUIDE_LANV2_FIREWORK = 2402
|
||||
OpenStateConst.OPEN_STATE_LOADINGTIPS_ENKANOMIYA = 2403
|
||||
OpenStateConst.OPEN_STATE_MICHIAE_CASKET = 2500
|
||||
OpenStateConst.OPEN_STATE_MAIL_COLLECT_UNLOCK_RED_POINT = 2501
|
||||
OpenStateConst.OPEN_STATE_LUMEN_STONE = 2600
|
||||
OpenStateConst.OPEN_STATE_GUIDE_CRYSTALLINK_BUFF = 2601
|
||||
}
|
||||
95
service/game-hk4e/constant/player_prop.go
Normal file
95
service/game-hk4e/constant/player_prop.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package constant
|
||||
|
||||
var PlayerPropertyConst *PlayerProperty
|
||||
|
||||
type PlayerProperty struct {
|
||||
PROP_EXP uint16 // 角色经验
|
||||
PROP_BREAK_LEVEL uint16 // 角色突破等阶
|
||||
PROP_SATIATION_VAL uint16 // 角色饱食度
|
||||
PROP_SATIATION_PENALTY_TIME uint16 // 角色饱食度溢出
|
||||
PROP_LEVEL uint16 // 角色等级
|
||||
PROP_LAST_CHANGE_AVATAR_TIME uint16 // 上一次改变角色的时间 暂不确定
|
||||
PROP_MAX_SPRING_VOLUME uint16 // 七天神像最大恢复血量 0-8500000
|
||||
PROP_CUR_SPRING_VOLUME uint16 // 七天神像当前血量 0-PROP_MAX_SPRING_VOLUME
|
||||
PROP_IS_SPRING_AUTO_USE uint16 // 是否开启靠近自动回血 0 1
|
||||
PROP_SPRING_AUTO_USE_PERCENT uint16 // 自动回血百分比 0-100
|
||||
PROP_IS_FLYABLE uint16 // 禁止使用风之翼 0 1
|
||||
PROP_IS_WEATHER_LOCKED uint16 // 游戏内天气锁定 暂不确定
|
||||
PROP_IS_GAME_TIME_LOCKED uint16 // 游戏内时间锁定 暂不确定
|
||||
PROP_IS_TRANSFERABLE uint16 // 是否禁止传送 0 1
|
||||
PROP_MAX_STAMINA uint16 // 最大体力 0-24000
|
||||
PROP_CUR_PERSIST_STAMINA uint16 // 当前体力 0-PROP_MAX_STAMINA
|
||||
PROP_CUR_TEMPORARY_STAMINA uint16 // 当前临时体力 暂不确定
|
||||
PROP_PLAYER_LEVEL uint16 // 冒险等级
|
||||
PROP_PLAYER_EXP uint16 // 冒险经验
|
||||
PROP_PLAYER_HCOIN uint16 // 原石 可以为负数
|
||||
PROP_PLAYER_SCOIN uint16 // 摩拉
|
||||
PROP_PLAYER_MP_SETTING_TYPE uint16 // 多人游戏世界权限 0禁止加入 1直接加入 2需要申请
|
||||
PROP_IS_MP_MODE_AVAILABLE uint16 // 玩家当前的世界是否可加入 0 1 例如任务中就不可加入
|
||||
PROP_PLAYER_WORLD_LEVEL uint16 // 世界等级 0-8
|
||||
PROP_PLAYER_RESIN uint16 // 树脂 0-2000
|
||||
PROP_PLAYER_WAIT_SUB_HCOIN uint16 // 暂存的原石 暂不确定
|
||||
PROP_PLAYER_WAIT_SUB_SCOIN uint16 // 暂存的摩拉 暂不确定
|
||||
PROP_IS_ONLY_MP_WITH_PS_PLAYER uint16 // 当前玩家多人世界里是否有PS主机玩家 0 1
|
||||
PROP_PLAYER_MCOIN uint16 // 创世结晶 可以为负数
|
||||
PROP_PLAYER_WAIT_SUB_MCOIN uint16 // 暂存的创世结晶 暂不确定
|
||||
PROP_PLAYER_LEGENDARY_KEY uint16 // 传说任务钥匙
|
||||
PROP_IS_HAS_FIRST_SHARE uint16 // 是否拥有抽卡结果首次分享奖励 暂不确定
|
||||
PROP_PLAYER_FORGE_POINT uint16 // 锻造相关
|
||||
PROP_CUR_CLIMATE_METER uint16 // 天气相关
|
||||
PROP_CUR_CLIMATE_TYPE uint16 // 天气相关
|
||||
PROP_CUR_CLIMATE_AREA_ID uint16 // 天气相关
|
||||
PROP_CUR_CLIMATE_AREA_CLIMATE_TYPE uint16 // 天气相关
|
||||
PROP_PLAYER_WORLD_LEVEL_LIMIT uint16 // 降低世界等级到此等级 暂不确定
|
||||
PROP_PLAYER_WORLD_LEVEL_ADJUST_CD uint16 // 降低世界等级的CD
|
||||
PROP_PLAYER_LEGENDARY_DAILY_TASK_NUM uint16 // 传说每日任务数量 暂不确定
|
||||
PROP_PLAYER_HOME_COIN uint16 // 洞天宝钱
|
||||
PROP_PLAYER_WAIT_SUB_HOME_COIN uint16 // 暂存的洞天宝钱 暂不确定
|
||||
}
|
||||
|
||||
func InitPlayerPropertyConst() {
|
||||
PlayerPropertyConst = new(PlayerProperty)
|
||||
|
||||
PlayerPropertyConst.PROP_EXP = 1001
|
||||
PlayerPropertyConst.PROP_BREAK_LEVEL = 1002
|
||||
PlayerPropertyConst.PROP_SATIATION_VAL = 1003
|
||||
PlayerPropertyConst.PROP_SATIATION_PENALTY_TIME = 1004
|
||||
PlayerPropertyConst.PROP_LEVEL = 4001
|
||||
PlayerPropertyConst.PROP_LAST_CHANGE_AVATAR_TIME = 10001
|
||||
PlayerPropertyConst.PROP_MAX_SPRING_VOLUME = 10002
|
||||
PlayerPropertyConst.PROP_CUR_SPRING_VOLUME = 10003
|
||||
PlayerPropertyConst.PROP_IS_SPRING_AUTO_USE = 10004
|
||||
PlayerPropertyConst.PROP_SPRING_AUTO_USE_PERCENT = 10005
|
||||
PlayerPropertyConst.PROP_IS_FLYABLE = 10006
|
||||
PlayerPropertyConst.PROP_IS_WEATHER_LOCKED = 10007
|
||||
PlayerPropertyConst.PROP_IS_GAME_TIME_LOCKED = 10008
|
||||
PlayerPropertyConst.PROP_IS_TRANSFERABLE = 10009
|
||||
PlayerPropertyConst.PROP_MAX_STAMINA = 10010
|
||||
PlayerPropertyConst.PROP_CUR_PERSIST_STAMINA = 10011
|
||||
PlayerPropertyConst.PROP_CUR_TEMPORARY_STAMINA = 10012
|
||||
PlayerPropertyConst.PROP_PLAYER_LEVEL = 10013
|
||||
PlayerPropertyConst.PROP_PLAYER_EXP = 10014
|
||||
PlayerPropertyConst.PROP_PLAYER_HCOIN = 10015
|
||||
PlayerPropertyConst.PROP_PLAYER_SCOIN = 10016
|
||||
PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE = 10017
|
||||
PlayerPropertyConst.PROP_IS_MP_MODE_AVAILABLE = 10018
|
||||
PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL = 10019
|
||||
PlayerPropertyConst.PROP_PLAYER_RESIN = 10020
|
||||
PlayerPropertyConst.PROP_PLAYER_WAIT_SUB_HCOIN = 10022
|
||||
PlayerPropertyConst.PROP_PLAYER_WAIT_SUB_SCOIN = 10023
|
||||
PlayerPropertyConst.PROP_IS_ONLY_MP_WITH_PS_PLAYER = 10024
|
||||
PlayerPropertyConst.PROP_PLAYER_MCOIN = 10025
|
||||
PlayerPropertyConst.PROP_PLAYER_WAIT_SUB_MCOIN = 10026
|
||||
PlayerPropertyConst.PROP_PLAYER_LEGENDARY_KEY = 10027
|
||||
PlayerPropertyConst.PROP_IS_HAS_FIRST_SHARE = 10028
|
||||
PlayerPropertyConst.PROP_PLAYER_FORGE_POINT = 10029
|
||||
PlayerPropertyConst.PROP_CUR_CLIMATE_METER = 10035
|
||||
PlayerPropertyConst.PROP_CUR_CLIMATE_TYPE = 10036
|
||||
PlayerPropertyConst.PROP_CUR_CLIMATE_AREA_ID = 10037
|
||||
PlayerPropertyConst.PROP_CUR_CLIMATE_AREA_CLIMATE_TYPE = 10038
|
||||
PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL_LIMIT = 10039
|
||||
PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL_ADJUST_CD = 10040
|
||||
PlayerPropertyConst.PROP_PLAYER_LEGENDARY_DAILY_TASK_NUM = 10041
|
||||
PlayerPropertyConst.PROP_PLAYER_HOME_COIN = 10042
|
||||
PlayerPropertyConst.PROP_PLAYER_WAIT_SUB_HOME_COIN = 10043
|
||||
}
|
||||
25
service/game-hk4e/constant/scene_type.go
Normal file
25
service/game-hk4e/constant/scene_type.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package constant
|
||||
|
||||
var SceneTypeConst *SceneType
|
||||
|
||||
type SceneType struct {
|
||||
SCENE_NONE uint16
|
||||
SCENE_WORLD uint16
|
||||
SCENE_DUNGEON uint16
|
||||
SCENE_ROOM uint16
|
||||
SCENE_HOME_WORLD uint16
|
||||
SCENE_HOME_ROOM uint16
|
||||
SCENE_ACTIVITY uint16
|
||||
}
|
||||
|
||||
func InitSceneTypeConst() {
|
||||
SceneTypeConst = new(SceneType)
|
||||
|
||||
SceneTypeConst.SCENE_NONE = 0
|
||||
SceneTypeConst.SCENE_WORLD = 1
|
||||
SceneTypeConst.SCENE_DUNGEON = 2
|
||||
SceneTypeConst.SCENE_ROOM = 3
|
||||
SceneTypeConst.SCENE_HOME_WORLD = 4
|
||||
SceneTypeConst.SCENE_HOME_ROOM = 5
|
||||
SceneTypeConst.SCENE_ACTIVITY = 6
|
||||
}
|
||||
34
service/game-hk4e/dao/dao.go
Normal file
34
service/game-hk4e/dao/dao.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/logger"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type Dao struct {
|
||||
client *mongo.Client
|
||||
db *mongo.Database
|
||||
}
|
||||
|
||||
func NewDao() (r *Dao) {
|
||||
r = new(Dao)
|
||||
clientOptions := options.Client().ApplyURI(config.CONF.Database.Url)
|
||||
client, err := mongo.Connect(context.TODO(), clientOptions)
|
||||
if err != nil {
|
||||
logger.LOG.Error("mongo connect error: %v", err)
|
||||
return nil
|
||||
}
|
||||
r.client = client
|
||||
r.db = client.Database("game_hk4e")
|
||||
return r
|
||||
}
|
||||
|
||||
func (d *Dao) CloseDao() {
|
||||
err := d.client.Disconnect(context.TODO())
|
||||
if err != nil {
|
||||
logger.LOG.Error("mongo close error: %v", err)
|
||||
}
|
||||
}
|
||||
107
service/game-hk4e/dao/player_dao.go
Normal file
107
service/game-hk4e/dao/player_dao.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"game-hk4e/model"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
func (d *Dao) InsertPlayer(player *model.Player) error {
|
||||
db := d.db.Collection("player")
|
||||
_, err := db.InsertOne(context.TODO(), player)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dao) InsertPlayerList(playerList []*model.Player) error {
|
||||
if len(playerList) == 0 {
|
||||
return nil
|
||||
}
|
||||
db := d.db.Collection("player")
|
||||
modelOperateList := make([]mongo.WriteModel, 0)
|
||||
for _, player := range playerList {
|
||||
modelOperate := mongo.NewInsertOneModel().SetDocument(player)
|
||||
modelOperateList = append(modelOperateList, modelOperate)
|
||||
}
|
||||
_, err := db.BulkWrite(context.TODO(), modelOperateList)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dao) DeletePlayer(playerID uint32) error {
|
||||
db := d.db.Collection("player")
|
||||
_, err := db.DeleteOne(context.TODO(), bson.D{{"playerID", playerID}})
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dao) DeletePlayerList(playerIDList []uint32) error {
|
||||
if len(playerIDList) == 0 {
|
||||
return nil
|
||||
}
|
||||
db := d.db.Collection("player")
|
||||
modelOperateList := make([]mongo.WriteModel, 0)
|
||||
for _, playerID := range playerIDList {
|
||||
modelOperate := mongo.NewDeleteOneModel().SetFilter(bson.D{{"playerID", playerID}})
|
||||
modelOperateList = append(modelOperateList, modelOperate)
|
||||
}
|
||||
_, err := db.BulkWrite(context.TODO(), modelOperateList)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dao) UpdatePlayer(player *model.Player) error {
|
||||
db := d.db.Collection("player")
|
||||
_, err := db.UpdateOne(
|
||||
context.TODO(),
|
||||
bson.D{{"playerID", player.PlayerID}},
|
||||
bson.D{{"$set", player}},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dao) UpdatePlayerList(playerList []*model.Player) error {
|
||||
if len(playerList) == 0 {
|
||||
return nil
|
||||
}
|
||||
db := d.db.Collection("player")
|
||||
modelOperateList := make([]mongo.WriteModel, 0)
|
||||
for _, player := range playerList {
|
||||
modelOperate := mongo.NewUpdateOneModel().SetFilter(bson.D{{"playerID", player.PlayerID}}).SetUpdate(bson.D{{"$set", player}})
|
||||
modelOperateList = append(modelOperateList, modelOperate)
|
||||
}
|
||||
_, err := db.BulkWrite(context.TODO(), modelOperateList)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Dao) QueryPlayerByID(playerID uint32) (*model.Player, error) {
|
||||
db := d.db.Collection("player")
|
||||
result := db.FindOne(
|
||||
context.TODO(),
|
||||
bson.D{{"playerID", playerID}},
|
||||
)
|
||||
item := new(model.Player)
|
||||
err := result.Decode(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (d *Dao) QueryPlayerList() ([]*model.Player, error) {
|
||||
db := d.db.Collection("player")
|
||||
find, err := db.Find(
|
||||
context.TODO(),
|
||||
bson.D{},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]*model.Player, 0)
|
||||
for find.Next(context.TODO()) {
|
||||
item := new(model.Player)
|
||||
err = find.Decode(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, item)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
211
service/game-hk4e/game/aoi/aoi.go
Normal file
211
service/game-hk4e/game/aoi/aoi.go
Normal file
@@ -0,0 +1,211 @@
|
||||
package aoi
|
||||
|
||||
import (
|
||||
"flswld.com/logger"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// aoi管理模块
|
||||
type AoiManager struct {
|
||||
// 区域边界坐标
|
||||
minX int16
|
||||
maxX int16
|
||||
minY int16
|
||||
maxY int16
|
||||
minZ int16
|
||||
maxZ int16
|
||||
numX int16 // x方向格子的数量
|
||||
numY int16 // y方向的格子数量
|
||||
numZ int16 // z方向的格子数量
|
||||
gridMap map[uint32]*Grid // 当前区域中都有哪些格子 key:gid value:格子对象
|
||||
}
|
||||
|
||||
// 初始化aoi区域
|
||||
func NewAoiManager(minX, maxX, numX, minY, maxY, numY, minZ, maxZ, numZ int16) (r *AoiManager) {
|
||||
r = new(AoiManager)
|
||||
r.minX = minX
|
||||
r.maxX = maxX
|
||||
r.minY = minY
|
||||
r.maxY = maxY
|
||||
r.numX = numX
|
||||
r.numY = numY
|
||||
r.minZ = minZ
|
||||
r.maxZ = maxZ
|
||||
r.numZ = numZ
|
||||
r.gridMap = make(map[uint32]*Grid)
|
||||
logger.LOG.Info("start init aoi area grid, num: %v", uint32(numX)*uint32(numY)*uint32(numZ))
|
||||
// 初始化aoi区域中所有的格子
|
||||
for x := int16(0); x < numX; x++ {
|
||||
for y := int16(0); y < numY; y++ {
|
||||
for z := int16(0); z < numZ; z++ {
|
||||
// 利用格子坐标得到格子id gid从0开始按xzy的顺序增长
|
||||
gid := uint32(y)*(uint32(numX)*uint32(numZ)) + uint32(z)*uint32(numX) + uint32(x)
|
||||
// 初始化一个格子放在aoi中的map里 key是当前格子的id
|
||||
grid := NewGrid(
|
||||
gid,
|
||||
r.minX+x*r.GridXLen(),
|
||||
r.minX+(x+1)*r.GridXLen(),
|
||||
r.minY+y*r.GridYLen(),
|
||||
r.minY+(y+1)*r.GridYLen(),
|
||||
r.minZ+z*r.GridZLen(),
|
||||
r.minZ+(z+1)*r.GridZLen(),
|
||||
)
|
||||
r.gridMap[gid] = grid
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.LOG.Info("init aoi area grid finish")
|
||||
return r
|
||||
}
|
||||
|
||||
// 每个格子在x轴方向的长度
|
||||
func (a *AoiManager) GridXLen() int16 {
|
||||
return (a.maxX - a.minX) / a.numX
|
||||
}
|
||||
|
||||
// 每个格子在y轴方向的长度
|
||||
func (a *AoiManager) GridYLen() int16 {
|
||||
return (a.maxY - a.minY) / a.numY
|
||||
}
|
||||
|
||||
// 每个格子在z轴方向的长度
|
||||
func (a *AoiManager) GridZLen() int16 {
|
||||
return (a.maxZ - a.minZ) / a.numZ
|
||||
}
|
||||
|
||||
// 通过坐标获取对应的格子id
|
||||
func (a *AoiManager) GetGidByPos(x, y, z float32) uint32 {
|
||||
gx := (int16(x) - a.minX) / a.GridXLen()
|
||||
gy := (int16(y) - a.minY) / a.GridYLen()
|
||||
gz := (int16(z) - a.minZ) / a.GridZLen()
|
||||
return uint32(gy)*(uint32(a.numX)*uint32(a.numZ)) + uint32(gz)*uint32(a.numX) + uint32(gx)
|
||||
}
|
||||
|
||||
// 判断坐标是否存在于aoi区域内
|
||||
func (a *AoiManager) IsValidAoiPos(x, y, z float32) bool {
|
||||
if (int16(x) > a.minX && int16(x) < a.maxX) &&
|
||||
(int16(y) > a.minY && int16(y) < a.maxY) &&
|
||||
(int16(z) > a.minZ && int16(z) < a.maxZ) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 打印信息方法
|
||||
func (a *AoiManager) DebugString() string {
|
||||
s := fmt.Sprintf("AoiMgr: minX: %d, maxX: %d, numX: %d, minY: %d, maxY: %d, numY: %d, minZ: %d, maxZ: %d, numZ: %d\n",
|
||||
a.minX, a.maxX, a.numX, a.minY, a.maxY, a.numY, a.minZ, a.maxZ, a.numZ)
|
||||
s += "gridList in AoiMgr:\n"
|
||||
for _, grid := range a.gridMap {
|
||||
s += fmt.Sprintln(grid.DebugString())
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// 根据格子的gid得到当前周边的格子信息
|
||||
func (a *AoiManager) GetSurrGridListByGid(gid uint32) (gridList []*Grid) {
|
||||
gridList = make([]*Grid, 0)
|
||||
// 判断grid是否存在
|
||||
grid, exist := a.gridMap[gid]
|
||||
if !exist {
|
||||
return gridList
|
||||
}
|
||||
// 添加自己
|
||||
gridList = append(gridList, grid)
|
||||
// 根据gid得到当前格子所在的x轴编号
|
||||
idx := int16(gid % (uint32(a.numX) * uint32(a.numZ)) % uint32(a.numX))
|
||||
// 判断当前格子左边是否还有格子
|
||||
if idx > 0 {
|
||||
gridList = append(gridList, a.gridMap[gid-1])
|
||||
}
|
||||
// 判断当前格子右边是否还有格子
|
||||
if idx < a.numX-1 {
|
||||
gridList = append(gridList, a.gridMap[gid+1])
|
||||
}
|
||||
// 将x轴当前的格子都取出进行遍历 再分别得到每个格子的平面上下是否有格子
|
||||
// 得到当前x轴的格子id集合
|
||||
gidListX := make([]uint32, 0)
|
||||
for _, v := range gridList {
|
||||
gidListX = append(gidListX, v.gid)
|
||||
}
|
||||
// 遍历x轴格子
|
||||
for _, v := range gidListX {
|
||||
// 计算该格子的idz
|
||||
idz := int16(v % (uint32(a.numX) * uint32(a.numZ)) / uint32(a.numX))
|
||||
// 判断当前格子平面上方是否还有格子
|
||||
if idz > 0 {
|
||||
gridList = append(gridList, a.gridMap[v-uint32(a.numX)])
|
||||
}
|
||||
// 判断当前格子平面下方是否还有格子
|
||||
if idz < a.numZ-1 {
|
||||
gridList = append(gridList, a.gridMap[v+uint32(a.numX)])
|
||||
}
|
||||
}
|
||||
// 将xoz平面当前的格子都取出进行遍历 再分别得到每个格子的空间上下是否有格子
|
||||
// 得到当前xoz平面的格子id集合
|
||||
gidListXOZ := make([]uint32, 0)
|
||||
for _, v := range gridList {
|
||||
gidListXOZ = append(gidListXOZ, v.gid)
|
||||
}
|
||||
// 遍历xoz平面格子
|
||||
for _, v := range gidListXOZ {
|
||||
// 计算该格子的idy
|
||||
idy := int16(v / (uint32(a.numX) * uint32(a.numZ)))
|
||||
// 判断当前格子空间上方是否还有格子
|
||||
if idy > 0 {
|
||||
gridList = append(gridList, a.gridMap[v-uint32(a.numX)*uint32(a.numZ)])
|
||||
}
|
||||
// 判断当前格子空间下方是否还有格子
|
||||
if idy < a.numY-1 {
|
||||
gridList = append(gridList, a.gridMap[v+uint32(a.numX)*uint32(a.numZ)])
|
||||
}
|
||||
}
|
||||
return gridList
|
||||
}
|
||||
|
||||
// 通过坐标得到周边格子内的全部entityId
|
||||
func (a *AoiManager) GetEntityIdListByPos(x, y, z float32) (entityIdList []uint32) {
|
||||
// 根据坐标得到当前坐标属于哪个格子id
|
||||
gid := a.GetGidByPos(x, y, z)
|
||||
// 根据格子id得到周边格子的信息
|
||||
gridList := a.GetSurrGridListByGid(gid)
|
||||
entityIdList = make([]uint32, 0)
|
||||
for _, v := range gridList {
|
||||
tmp := v.GetEntityIdList()
|
||||
entityIdList = append(entityIdList, tmp...)
|
||||
//logger.LOG.Debug("Grid: gid: %d, tmp len: %v", v.gid, len(tmp))
|
||||
}
|
||||
return entityIdList
|
||||
}
|
||||
|
||||
// 通过gid获取当前格子的全部entityId
|
||||
func (a *AoiManager) GetEntityIdListByGid(gid uint32) (entityIdList []uint32) {
|
||||
grid := a.gridMap[gid]
|
||||
entityIdList = grid.GetEntityIdList()
|
||||
return entityIdList
|
||||
}
|
||||
|
||||
// 添加一个entityId到一个格子中
|
||||
func (a *AoiManager) AddEntityIdToGrid(entityId uint32, gid uint32) {
|
||||
grid := a.gridMap[gid]
|
||||
grid.AddEntityId(entityId)
|
||||
}
|
||||
|
||||
// 移除一个格子中的entityId
|
||||
func (a *AoiManager) RemoveEntityIdFromGrid(entityId uint32, gid uint32) {
|
||||
grid := a.gridMap[gid]
|
||||
grid.RemoveEntityId(entityId)
|
||||
}
|
||||
|
||||
// 通过坐标添加一个entityId到一个格子中
|
||||
func (a *AoiManager) AddEntityIdToGridByPos(entityId uint32, x, y, z float32) {
|
||||
gid := a.GetGidByPos(x, y, z)
|
||||
a.AddEntityIdToGrid(entityId, gid)
|
||||
}
|
||||
|
||||
// 通过坐标把一个entityId从对应的格子中删除
|
||||
func (a *AoiManager) RemoveEntityIdFromGridByPos(entityId uint32, x, y, z float32) {
|
||||
gid := a.GetGidByPos(x, y, z)
|
||||
a.RemoveEntityIdFromGrid(entityId, gid)
|
||||
}
|
||||
30
service/game-hk4e/game/aoi/aoi_test.go
Normal file
30
service/game-hk4e/game/aoi/aoi_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package aoi
|
||||
|
||||
import (
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/logger"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAoiManagerGetSurrGridListByGid(t *testing.T) {
|
||||
filePath := "./application.toml"
|
||||
config.InitConfig(filePath)
|
||||
logger.InitLogger()
|
||||
aoiManager := NewAoiManager(
|
||||
-150, 150, 3,
|
||||
-150, 150, 3,
|
||||
-150, 150, 3,
|
||||
)
|
||||
logger.LOG.Debug("aoiManager: %s", aoiManager.DebugString())
|
||||
for k := range aoiManager.gridMap {
|
||||
// 得到当前格子周边的九宫格
|
||||
gridList := aoiManager.GetSurrGridListByGid(k)
|
||||
// 得到九宫格所有的id
|
||||
logger.LOG.Debug("gid: %d gridList len: %d", k, len(gridList))
|
||||
gidList := make([]uint32, 0, len(gridList))
|
||||
for _, grid := range gridList {
|
||||
gidList = append(gidList, grid.gid)
|
||||
}
|
||||
logger.LOG.Debug("Grid: gid: %d, surr grid gid list: %v", k, gidList)
|
||||
}
|
||||
}
|
||||
63
service/game-hk4e/game/aoi/grid.go
Normal file
63
service/game-hk4e/game/aoi/grid.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package aoi
|
||||
|
||||
import (
|
||||
"flswld.com/logger"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 地图格子
|
||||
type Grid struct {
|
||||
gid uint32 // 格子id
|
||||
// 格子边界坐标
|
||||
minX int16
|
||||
maxX int16
|
||||
minY int16
|
||||
maxY int16
|
||||
minZ int16
|
||||
maxZ int16
|
||||
entityIdMap map[uint32]bool // k:entityId v:是否存在
|
||||
}
|
||||
|
||||
// 初始化格子
|
||||
func NewGrid(gid uint32, minX, maxX, minY, maxY, minZ, maxZ int16) (r *Grid) {
|
||||
r = new(Grid)
|
||||
r.gid = gid
|
||||
r.minX = minX
|
||||
r.maxX = maxX
|
||||
r.minY = minY
|
||||
r.maxY = maxY
|
||||
r.minZ = minZ
|
||||
r.maxZ = maxZ
|
||||
r.entityIdMap = make(map[uint32]bool)
|
||||
return r
|
||||
}
|
||||
|
||||
// 向格子中添加一个实体id
|
||||
func (g *Grid) AddEntityId(entityId uint32) {
|
||||
g.entityIdMap[entityId] = true
|
||||
}
|
||||
|
||||
// 从格子中删除一个实体id
|
||||
func (g *Grid) RemoveEntityId(entityId uint32) {
|
||||
_, exist := g.entityIdMap[entityId]
|
||||
if exist {
|
||||
delete(g.entityIdMap, entityId)
|
||||
} else {
|
||||
logger.LOG.Error("remove entity id but it not exist, entityId: %v", entityId)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取格子中所有实体id
|
||||
func (g *Grid) GetEntityIdList() (entityIdList []uint32) {
|
||||
entityIdList = make([]uint32, 0)
|
||||
for k := range g.entityIdMap {
|
||||
entityIdList = append(entityIdList, k)
|
||||
}
|
||||
return entityIdList
|
||||
}
|
||||
|
||||
// 打印信息方法
|
||||
func (g *Grid) DebugString() string {
|
||||
return fmt.Sprintf("Grid: gid: %d, minX: %d, maxX: %d, minY: %d, maxY: %d, minZ: %d, maxZ: %d, entityIdMap: %v",
|
||||
g.gid, g.minX, g.maxX, g.minY, g.maxY, g.minZ, g.maxZ, g.entityIdMap)
|
||||
}
|
||||
112
service/game-hk4e/game/game_manager.go
Normal file
112
service/game-hk4e/game/game_manager.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/common/utils/alg"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/dao"
|
||||
"game-hk4e/model"
|
||||
"game-hk4e/rpc"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type GameManager struct {
|
||||
dao *dao.Dao
|
||||
rpcManager *rpc.RpcManager
|
||||
netMsgInput chan *proto.NetMsg
|
||||
netMsgOutput chan *proto.NetMsg
|
||||
snowflake *alg.SnowflakeWorker
|
||||
// 本地事件队列管理器
|
||||
localEventManager *LocalEventManager
|
||||
// 接口路由管理器
|
||||
routeManager *RouteManager
|
||||
// 用户管理器
|
||||
userManager *UserManager
|
||||
// 世界管理器
|
||||
worldManager *WorldManager
|
||||
// 游戏服务器tick
|
||||
tickManager *TickManager
|
||||
}
|
||||
|
||||
func NewGameManager(dao *dao.Dao, rpcManager *rpc.RpcManager, netMsgInput chan *proto.NetMsg, netMsgOutput chan *proto.NetMsg) (r *GameManager) {
|
||||
r = new(GameManager)
|
||||
r.dao = dao
|
||||
r.rpcManager = rpcManager
|
||||
r.netMsgInput = netMsgInput
|
||||
r.netMsgOutput = netMsgOutput
|
||||
r.snowflake = alg.NewSnowflakeWorker(1)
|
||||
r.localEventManager = NewLocalEventManager(r)
|
||||
r.routeManager = NewRouteManager(r)
|
||||
r.userManager = NewUserManager(dao, r.localEventManager.localEventChan)
|
||||
r.worldManager = NewWorldManager(r.snowflake)
|
||||
r.tickManager = NewTickManager(r)
|
||||
|
||||
r.worldManager.worldStatic.InitTerrain()
|
||||
r.worldManager.worldStatic.Pathfinding()
|
||||
r.worldManager.worldStatic.ConvPathVectorListToAiMoveVectorList()
|
||||
|
||||
// 大世界的主人
|
||||
r.OnRegOk(false, &proto.SetPlayerBornDataReq{AvatarId: 10000007, NickName: "大世界的主人"}, 1, 0)
|
||||
bigWorldOwner := r.userManager.GetOnlineUser(1)
|
||||
bigWorldOwner.SceneLoadState = model.SceneEnterDone
|
||||
bigWorldOwner.DbState = model.DbNormal
|
||||
r.worldManager.InitBigWorld(bigWorldOwner)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (g *GameManager) Start() {
|
||||
g.routeManager.InitRoute()
|
||||
g.userManager.StartAutoSaveUser()
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case netMsg := <-g.netMsgOutput:
|
||||
// 接收客户端消息
|
||||
g.routeManager.RouteHandle(netMsg)
|
||||
case <-g.tickManager.ticker.C:
|
||||
// 游戏服务器定时帧
|
||||
g.tickManager.OnGameServerTick()
|
||||
case localEvent := <-g.localEventManager.localEventChan:
|
||||
// 处理本地事件
|
||||
g.localEventManager.LocalEventHandle(localEvent)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (g *GameManager) Stop() {
|
||||
g.worldManager.worldStatic.SaveTerrain()
|
||||
}
|
||||
|
||||
// 发送消息给客户端
|
||||
func (g *GameManager) SendMsg(apiId uint16, userId uint32, clientSeq uint32, payloadMsg pb.Message) {
|
||||
if userId < 100000000 {
|
||||
return
|
||||
}
|
||||
netMsg := new(proto.NetMsg)
|
||||
netMsg.UserId = userId
|
||||
netMsg.EventId = proto.NormalMsg
|
||||
netMsg.ApiId = apiId
|
||||
netMsg.ClientSeq = clientSeq
|
||||
// 在这里直接序列化成二进制数据 防止发送的消息内包含各种游戏数据指针 而造成并发读写的问题
|
||||
payloadMessageData, err := pb.Marshal(payloadMsg)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse payload msg to bin error: %v", err)
|
||||
return
|
||||
}
|
||||
netMsg.PayloadMessageData = payloadMessageData
|
||||
g.netMsgInput <- netMsg
|
||||
}
|
||||
|
||||
func (g *GameManager) ReconnectPlayer(userId uint32) {
|
||||
g.SendMsg(proto.ApiClientReconnectNotify, userId, 0, new(proto.ClientReconnectNotify))
|
||||
}
|
||||
|
||||
func (g *GameManager) DisconnectPlayer(userId uint32) {
|
||||
g.SendMsg(proto.ApiServerDisconnectClientNotify, userId, 0, new(proto.ServerDisconnectClientNotify))
|
||||
}
|
||||
|
||||
func (g *GameManager) KickPlayer(userId uint32) {
|
||||
g.rpcManager.SendKickPlayerToHk4eGateway(userId)
|
||||
}
|
||||
34
service/game-hk4e/game/local_event_manager.go
Normal file
34
service/game-hk4e/game/local_event_manager.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package game
|
||||
|
||||
const (
|
||||
LoadLoginUserFromDbFinish = iota
|
||||
CheckUserExistOnRegFromDbFinish
|
||||
)
|
||||
|
||||
type LocalEvent struct {
|
||||
EventId int
|
||||
Msg any
|
||||
}
|
||||
|
||||
type LocalEventManager struct {
|
||||
localEventChan chan *LocalEvent
|
||||
gameManager *GameManager
|
||||
}
|
||||
|
||||
func NewLocalEventManager(gameManager *GameManager) (r *LocalEventManager) {
|
||||
r = new(LocalEventManager)
|
||||
r.localEventChan = make(chan *LocalEvent, 1000)
|
||||
r.gameManager = gameManager
|
||||
return r
|
||||
}
|
||||
|
||||
func (l *LocalEventManager) LocalEventHandle(localEvent *LocalEvent) {
|
||||
switch localEvent.EventId {
|
||||
case LoadLoginUserFromDbFinish:
|
||||
playerLoginInfo := localEvent.Msg.(*PlayerLoginInfo)
|
||||
l.gameManager.OnLoginOk(playerLoginInfo.UserId, playerLoginInfo.Player, playerLoginInfo.ClientSeq)
|
||||
case CheckUserExistOnRegFromDbFinish:
|
||||
playerRegInfo := localEvent.Msg.(*PlayerRegInfo)
|
||||
l.gameManager.OnRegOk(playerRegInfo.Exist, playerRegInfo.Req, playerRegInfo.UserId, playerRegInfo.ClientSeq)
|
||||
}
|
||||
}
|
||||
103
service/game-hk4e/game/msg_common_handler.go
Normal file
103
service/game-hk4e/game/msg_common_handler.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (g *GameManager) PlayerSetPauseReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user pause, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.PlayerSetPauseReq)
|
||||
isPaused := req.IsPaused
|
||||
|
||||
player.Pause = isPaused
|
||||
|
||||
// PacketPlayerSetPauseRsp
|
||||
playerSetPauseRsp := new(proto.PlayerSetPauseRsp)
|
||||
g.SendMsg(proto.ApiPlayerSetPauseRsp, userId, player.ClientSeq, playerSetPauseRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) TowerAllDataReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get tower all data, user id: %v", userId)
|
||||
|
||||
// PacketTowerAllDataRsp
|
||||
towerAllDataRsp := new(proto.TowerAllDataRsp)
|
||||
towerAllDataRsp.TowerScheduleId = 29
|
||||
towerAllDataRsp.TowerFloorRecordList = []*proto.TowerFloorRecord{{FloorId: 1001}}
|
||||
towerAllDataRsp.CurLevelRecord = &proto.TowerCurLevelRecord{IsEmpty: true}
|
||||
towerAllDataRsp.NextScheduleChangeTime = 4294967295
|
||||
towerAllDataRsp.FloorOpenTimeMap = make(map[uint32]uint32)
|
||||
towerAllDataRsp.FloorOpenTimeMap[1024] = 1630486800
|
||||
towerAllDataRsp.FloorOpenTimeMap[1025] = 1630486800
|
||||
towerAllDataRsp.FloorOpenTimeMap[1026] = 1630486800
|
||||
towerAllDataRsp.FloorOpenTimeMap[1027] = 1630486800
|
||||
towerAllDataRsp.ScheduleStartTime = 1630486800
|
||||
g.SendMsg(proto.ApiTowerAllDataRsp, userId, player.ClientSeq, towerAllDataRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) EntityAiSyncNotify(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user entity ai sync, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.EntityAiSyncNotify)
|
||||
|
||||
if len(req.LocalAvatarAlertedMonsterList) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// PacketEntityAiSyncNotify
|
||||
entityAiSyncNotify := new(proto.EntityAiSyncNotify)
|
||||
entityAiSyncNotify.InfoList = make([]*proto.AiSyncInfo, 0)
|
||||
for _, monsterId := range req.LocalAvatarAlertedMonsterList {
|
||||
entityAiSyncNotify.InfoList = append(entityAiSyncNotify.InfoList, &proto.AiSyncInfo{
|
||||
EntityId: monsterId,
|
||||
HasPathToTarget: true,
|
||||
IsSelfKilling: false,
|
||||
})
|
||||
}
|
||||
g.SendMsg(proto.ApiEntityAiSyncNotify, userId, player.ClientSeq, entityAiSyncNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) ClientTimeNotify(userId uint32, clientTime uint32) {
|
||||
player := g.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
logger.LOG.Debug("client time notify, user id: %v, time: %v", userId, clientTime)
|
||||
player.ClientTime = clientTime
|
||||
}
|
||||
|
||||
func (g *GameManager) ClientRttNotify(userId uint32, clientRtt uint32) {
|
||||
player := g.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
logger.LOG.Debug("client rtt notify, user id: %v, rtt: %v", userId, clientRtt)
|
||||
player.ClientRTT = clientRtt
|
||||
}
|
||||
|
||||
func (g *GameManager) ServerAnnounceNotify(announceId uint32, announceMsg string) {
|
||||
for _, onlinePlayer := range g.userManager.GetAllOnlineUserList() {
|
||||
serverAnnounceNotify := new(proto.ServerAnnounceNotify)
|
||||
now := uint32(time.Now().Unix())
|
||||
serverAnnounceNotify.AnnounceDataList = []*proto.AnnounceData{{
|
||||
ConfigId: announceId,
|
||||
BeginTime: now + 1,
|
||||
EndTime: now + 2,
|
||||
CenterSystemText: announceMsg,
|
||||
CenterSystemFrequency: 1,
|
||||
}}
|
||||
g.SendMsg(proto.ApiServerAnnounceNotify, onlinePlayer.PlayerID, 0, serverAnnounceNotify)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) ServerAnnounceRevokeNotify(announceId uint32) {
|
||||
for _, onlinePlayer := range g.userManager.GetAllOnlineUserList() {
|
||||
serverAnnounceRevokeNotify := new(proto.ServerAnnounceRevokeNotify)
|
||||
serverAnnounceRevokeNotify.ConfigIdList = []uint32{announceId}
|
||||
g.SendMsg(proto.ApiServerAnnounceRevokeNotify, onlinePlayer.PlayerID, 0, serverAnnounceRevokeNotify)
|
||||
}
|
||||
}
|
||||
116
service/game-hk4e/game/route_manager.go
Normal file
116
service/game-hk4e/game/route_manager.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type HandlerFunc func(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message)
|
||||
|
||||
type RouteManager struct {
|
||||
gameManager *GameManager
|
||||
// k:apiId v:HandlerFunc
|
||||
handlerFuncRouteMap map[uint16]HandlerFunc
|
||||
}
|
||||
|
||||
func NewRouteManager(gameManager *GameManager) (r *RouteManager) {
|
||||
r = new(RouteManager)
|
||||
r.gameManager = gameManager
|
||||
r.handlerFuncRouteMap = make(map[uint16]HandlerFunc)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *RouteManager) registerRouter(apiId uint16, handlerFunc HandlerFunc) {
|
||||
r.handlerFuncRouteMap[apiId] = handlerFunc
|
||||
}
|
||||
|
||||
func (r *RouteManager) doRoute(apiId uint16, userId uint32, clientSeq uint32, payloadMsg pb.Message) {
|
||||
handlerFunc, ok := r.handlerFuncRouteMap[apiId]
|
||||
if !ok {
|
||||
logger.LOG.Error("no route for msg, apiId: %v", apiId)
|
||||
return
|
||||
}
|
||||
player := r.gameManager.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
player.ClientSeq = clientSeq
|
||||
handlerFunc(userId, player, clientSeq, payloadMsg)
|
||||
}
|
||||
|
||||
func (r *RouteManager) InitRoute() {
|
||||
r.registerRouter(proto.ApiPlayerSetPauseReq, r.gameManager.PlayerSetPauseReq)
|
||||
r.registerRouter(proto.ApiEnterSceneReadyReq, r.gameManager.EnterSceneReadyReq)
|
||||
r.registerRouter(proto.ApiPathfindingEnterSceneReq, r.gameManager.PathfindingEnterSceneReq)
|
||||
r.registerRouter(proto.ApiGetScenePointReq, r.gameManager.GetScenePointReq)
|
||||
r.registerRouter(proto.ApiGetSceneAreaReq, r.gameManager.GetSceneAreaReq)
|
||||
r.registerRouter(proto.ApiSceneInitFinishReq, r.gameManager.SceneInitFinishReq)
|
||||
r.registerRouter(proto.ApiEnterSceneDoneReq, r.gameManager.EnterSceneDoneReq)
|
||||
r.registerRouter(proto.ApiEnterWorldAreaReq, r.gameManager.EnterWorldAreaReq)
|
||||
r.registerRouter(proto.ApiPostEnterSceneReq, r.gameManager.PostEnterSceneReq)
|
||||
r.registerRouter(proto.ApiTowerAllDataReq, r.gameManager.TowerAllDataReq)
|
||||
r.registerRouter(proto.ApiSceneTransToPointReq, r.gameManager.SceneTransToPointReq)
|
||||
r.registerRouter(proto.ApiMarkMapReq, r.gameManager.MarkMapReq)
|
||||
r.registerRouter(proto.ApiChangeAvatarReq, r.gameManager.ChangeAvatarReq)
|
||||
r.registerRouter(proto.ApiSetUpAvatarTeamReq, r.gameManager.SetUpAvatarTeamReq)
|
||||
r.registerRouter(proto.ApiChooseCurAvatarTeamReq, r.gameManager.ChooseCurAvatarTeamReq)
|
||||
r.registerRouter(proto.ApiGetGachaInfoReq, r.gameManager.GetGachaInfoReq)
|
||||
r.registerRouter(proto.ApiDoGachaReq, r.gameManager.DoGachaReq)
|
||||
r.registerRouter(proto.ApiQueryPathReq, r.gameManager.QueryPathReq)
|
||||
r.registerRouter(proto.ApiCombatInvocationsNotify, r.gameManager.CombatInvocationsNotify)
|
||||
r.registerRouter(proto.ApiAbilityInvocationsNotify, r.gameManager.AbilityInvocationsNotify)
|
||||
r.registerRouter(proto.ApiClientAbilityInitFinishNotify, r.gameManager.ClientAbilityInitFinishNotify)
|
||||
r.registerRouter(proto.ApiEntityAiSyncNotify, r.gameManager.EntityAiSyncNotify)
|
||||
r.registerRouter(proto.ApiWearEquipReq, r.gameManager.WearEquipReq)
|
||||
r.registerRouter(proto.ApiChangeGameTimeReq, r.gameManager.ChangeGameTimeReq)
|
||||
r.registerRouter(proto.ApiGetPlayerSocialDetailReq, r.gameManager.GetPlayerSocialDetailReq)
|
||||
r.registerRouter(proto.ApiSetPlayerBirthdayReq, r.gameManager.SetPlayerBirthdayReq)
|
||||
r.registerRouter(proto.ApiSetNameCardReq, r.gameManager.SetNameCardReq)
|
||||
r.registerRouter(proto.ApiSetPlayerSignatureReq, r.gameManager.SetPlayerSignatureReq)
|
||||
r.registerRouter(proto.ApiSetPlayerNameReq, r.gameManager.SetPlayerNameReq)
|
||||
r.registerRouter(proto.ApiSetPlayerHeadImageReq, r.gameManager.SetPlayerHeadImageReq)
|
||||
r.registerRouter(proto.ApiGetAllUnlockNameCardReq, r.gameManager.GetAllUnlockNameCardReq)
|
||||
r.registerRouter(proto.ApiGetPlayerFriendListReq, r.gameManager.GetPlayerFriendListReq)
|
||||
r.registerRouter(proto.ApiGetPlayerAskFriendListReq, r.gameManager.GetPlayerAskFriendListReq)
|
||||
r.registerRouter(proto.ApiAskAddFriendReq, r.gameManager.AskAddFriendReq)
|
||||
r.registerRouter(proto.ApiDealAddFriendReq, r.gameManager.DealAddFriendReq)
|
||||
r.registerRouter(proto.ApiGetOnlinePlayerListReq, r.gameManager.GetOnlinePlayerListReq)
|
||||
r.registerRouter(proto.ApiPlayerApplyEnterMpReq, r.gameManager.PlayerApplyEnterMpReq)
|
||||
r.registerRouter(proto.ApiPlayerApplyEnterMpResultReq, r.gameManager.PlayerApplyEnterMpResultReq)
|
||||
r.registerRouter(proto.ApiPlayerGetForceQuitBanInfoReq, r.gameManager.PlayerGetForceQuitBanInfoReq)
|
||||
r.registerRouter(proto.ApiGetShopmallDataReq, r.gameManager.GetShopmallDataReq)
|
||||
r.registerRouter(proto.ApiGetShopReq, r.gameManager.GetShopReq)
|
||||
r.registerRouter(proto.ApiBuyGoodsReq, r.gameManager.BuyGoodsReq)
|
||||
r.registerRouter(proto.ApiMcoinExchangeHcoinReq, r.gameManager.McoinExchangeHcoinReq)
|
||||
r.registerRouter(proto.ApiAvatarChangeCostumeReq, r.gameManager.AvatarChangeCostumeReq)
|
||||
r.registerRouter(proto.ApiAvatarWearFlycloakReq, r.gameManager.AvatarWearFlycloakReq)
|
||||
r.registerRouter(proto.ApiPullRecentChatReq, r.gameManager.PullRecentChatReq)
|
||||
r.registerRouter(proto.ApiPullPrivateChatReq, r.gameManager.PullPrivateChatReq)
|
||||
r.registerRouter(proto.ApiPrivateChatReq, r.gameManager.PrivateChatReq)
|
||||
r.registerRouter(proto.ApiReadPrivateChatReq, r.gameManager.ReadPrivateChatReq)
|
||||
r.registerRouter(proto.ApiPlayerChatReq, r.gameManager.PlayerChatReq)
|
||||
r.registerRouter(proto.ApiBackMyWorldReq, r.gameManager.BackMyWorldReq)
|
||||
r.registerRouter(proto.ApiChangeWorldToSingleModeReq, r.gameManager.ChangeWorldToSingleModeReq)
|
||||
r.registerRouter(proto.ApiSceneKickPlayerReq, r.gameManager.SceneKickPlayerReq)
|
||||
r.registerRouter(proto.ApiChangeMpTeamAvatarReq, r.gameManager.ChangeMpTeamAvatarReq)
|
||||
}
|
||||
|
||||
func (r *RouteManager) RouteHandle(netMsg *proto.NetMsg) {
|
||||
switch netMsg.EventId {
|
||||
case proto.NormalMsg:
|
||||
r.doRoute(netMsg.ApiId, netMsg.UserId, netMsg.ClientSeq, netMsg.PayloadMessage)
|
||||
case proto.UserRegNotify:
|
||||
r.gameManager.OnReg(netMsg.UserId, netMsg.ClientSeq, netMsg.PayloadMessage)
|
||||
case proto.UserLoginNotify:
|
||||
r.gameManager.OnLogin(netMsg.UserId, netMsg.ClientSeq)
|
||||
case proto.UserOfflineNotify:
|
||||
r.gameManager.OnUserOffline(netMsg.UserId)
|
||||
case proto.ClientRttNotify:
|
||||
r.gameManager.ClientRttNotify(netMsg.UserId, netMsg.ClientRtt)
|
||||
case proto.ClientTimeNotify:
|
||||
r.gameManager.ClientTimeNotify(netMsg.UserId, netMsg.ClientTime)
|
||||
}
|
||||
}
|
||||
312
service/game-hk4e/game/tick_manager.go
Normal file
312
service/game-hk4e/game/tick_manager.go
Normal file
@@ -0,0 +1,312 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/common/utils/random"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TickManager struct {
|
||||
ticker *time.Ticker
|
||||
tickCount uint64
|
||||
gameManager *GameManager
|
||||
}
|
||||
|
||||
func NewTickManager(gameManager *GameManager) (r *TickManager) {
|
||||
r = new(TickManager)
|
||||
r.ticker = time.NewTicker(time.Millisecond * 100)
|
||||
logger.LOG.Info("game server tick start at: %v", time.Now().UnixMilli())
|
||||
r.gameManager = gameManager
|
||||
return r
|
||||
}
|
||||
|
||||
func (t *TickManager) OnGameServerTick() {
|
||||
t.tickCount++
|
||||
now := time.Now().UnixMilli()
|
||||
t.onTick100MilliSecond(now)
|
||||
if t.tickCount%(10*1) == 0 {
|
||||
t.onTickSecond(now)
|
||||
}
|
||||
if t.tickCount%(10*5) == 0 {
|
||||
t.onTick5Second(now)
|
||||
}
|
||||
if t.tickCount%(10*10) == 0 {
|
||||
t.onTick10Second(now)
|
||||
}
|
||||
if t.tickCount%(10*60) == 0 {
|
||||
t.onTickMinute(now)
|
||||
}
|
||||
if t.tickCount%(10*60*10) == 0 {
|
||||
t.onTick10Minute(now)
|
||||
}
|
||||
if t.tickCount%(10*3600) == 0 {
|
||||
t.onTickHour(now)
|
||||
}
|
||||
if t.tickCount%(10*3600*24) == 0 {
|
||||
t.onTickDay(now)
|
||||
}
|
||||
if t.tickCount%(10*3600*24*7) == 0 {
|
||||
t.onTickWeek(now)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TickManager) onTickWeek(now int64) {
|
||||
logger.LOG.Info("on tick week, time: %v", now)
|
||||
}
|
||||
|
||||
func (t *TickManager) onTickDay(now int64) {
|
||||
logger.LOG.Info("on tick day, time: %v", now)
|
||||
}
|
||||
|
||||
func (t *TickManager) onTickHour(now int64) {
|
||||
logger.LOG.Info("on tick hour, time: %v", now)
|
||||
}
|
||||
|
||||
func (t *TickManager) onTick10Minute(now int64) {
|
||||
for _, world := range t.gameManager.worldManager.worldMap {
|
||||
for _, player := range world.playerMap {
|
||||
// 蓝球粉球
|
||||
t.gameManager.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 223, ChangeCount: 1}}, true, 0)
|
||||
t.gameManager.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 224, ChangeCount: 1}}, true, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TickManager) onTickMinute(now int64) {
|
||||
t.gameManager.ServerAnnounceNotify(100, "test123")
|
||||
for _, world := range t.gameManager.worldManager.worldMap {
|
||||
for _, player := range world.playerMap {
|
||||
// 随机物品
|
||||
allItemDataConfig := t.gameManager.GetAllItemDataConfig()
|
||||
count := random.GetRandomInt32(0, 4)
|
||||
i := int32(0)
|
||||
for itemId := range allItemDataConfig {
|
||||
itemDataConfig := allItemDataConfig[itemId]
|
||||
// TODO 3.0.0REL版本中 发送某些无效家具 可能会导致客户端背包家具界面卡死
|
||||
if itemDataConfig.ItemEnumType == constant.ItemTypeConst.ITEM_FURNITURE {
|
||||
continue
|
||||
}
|
||||
num := random.GetRandomInt32(1, 9)
|
||||
t.gameManager.AddUserItem(player.PlayerID, []*UserItem{{ItemId: uint32(itemId), ChangeCount: uint32(num)}}, true, 0)
|
||||
i++
|
||||
if i > count {
|
||||
break
|
||||
}
|
||||
}
|
||||
t.gameManager.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 102, ChangeCount: 30}}, true, 0)
|
||||
t.gameManager.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 201, ChangeCount: 10}}, true, 0)
|
||||
t.gameManager.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 202, ChangeCount: 100}}, true, 0)
|
||||
t.gameManager.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 203, ChangeCount: 10}}, true, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TickManager) onTick10Second(now int64) {
|
||||
for _, world := range t.gameManager.worldManager.worldMap {
|
||||
if !world.IsBigWorld() && (world.multiplayer || !world.owner.Pause) {
|
||||
// 刷怪
|
||||
scene := world.GetSceneById(3)
|
||||
monsterEntityCount := 0
|
||||
for _, entity := range scene.entityMap {
|
||||
if entity.entityType == uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_MONSTER) {
|
||||
monsterEntityCount++
|
||||
}
|
||||
}
|
||||
if monsterEntityCount < 30 {
|
||||
monsterEntityId := t.createMonster(scene)
|
||||
bigWorldOwner := t.gameManager.userManager.GetOnlineUser(1)
|
||||
t.gameManager.AddSceneEntityNotify(bigWorldOwner, proto.VisionType_VISION_TYPE_BORN, []uint32{monsterEntityId}, true)
|
||||
}
|
||||
}
|
||||
for _, player := range world.playerMap {
|
||||
if world.multiplayer || !world.owner.Pause {
|
||||
// 改面板
|
||||
team := player.TeamConfig.GetActiveTeam()
|
||||
for _, avatarId := range team.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
avatar := player.AvatarMap[avatarId]
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_ATTACK)] = 1000000
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CRITICAL)] = 1.0
|
||||
t.gameManager.UpdateUserAvatarFightProp(player.PlayerID, avatarId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TickManager) onTick5Second(now int64) {
|
||||
for _, world := range t.gameManager.worldManager.worldMap {
|
||||
if world.IsBigWorld() {
|
||||
for applyUid := range world.owner.CoopApplyMap {
|
||||
t.gameManager.UserDealEnterWorld(world.owner, applyUid, true)
|
||||
}
|
||||
}
|
||||
for _, player := range world.playerMap {
|
||||
if world.multiplayer {
|
||||
// PacketWorldPlayerLocationNotify
|
||||
worldPlayerLocationNotify := new(proto.WorldPlayerLocationNotify)
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
playerWorldLocationInfo := &proto.PlayerWorldLocationInfo{
|
||||
SceneId: worldPlayer.SceneId,
|
||||
PlayerLoc: &proto.PlayerLocationInfo{
|
||||
Uid: worldPlayer.PlayerID,
|
||||
Pos: &proto.Vector{
|
||||
X: float32(worldPlayer.Pos.X),
|
||||
Y: float32(worldPlayer.Pos.Y),
|
||||
Z: float32(worldPlayer.Pos.Z),
|
||||
},
|
||||
Rot: &proto.Vector{
|
||||
X: float32(worldPlayer.Rot.X),
|
||||
Y: float32(worldPlayer.Rot.Y),
|
||||
Z: float32(worldPlayer.Rot.Z),
|
||||
},
|
||||
},
|
||||
}
|
||||
worldPlayerLocationNotify.PlayerWorldLocList = append(worldPlayerLocationNotify.PlayerWorldLocList, playerWorldLocationInfo)
|
||||
}
|
||||
t.gameManager.SendMsg(proto.ApiWorldPlayerLocationNotify, player.PlayerID, 0, worldPlayerLocationNotify)
|
||||
|
||||
// PacketScenePlayerLocationNotify
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
scenePlayerLocationNotify := new(proto.ScenePlayerLocationNotify)
|
||||
scenePlayerLocationNotify.SceneId = player.SceneId
|
||||
for _, scenePlayer := range scene.playerMap {
|
||||
playerLocationInfo := &proto.PlayerLocationInfo{
|
||||
Uid: scenePlayer.PlayerID,
|
||||
Pos: &proto.Vector{
|
||||
X: float32(scenePlayer.Pos.X),
|
||||
Y: float32(scenePlayer.Pos.Y),
|
||||
Z: float32(scenePlayer.Pos.Z),
|
||||
},
|
||||
Rot: &proto.Vector{
|
||||
X: float32(scenePlayer.Rot.X),
|
||||
Y: float32(scenePlayer.Rot.Y),
|
||||
Z: float32(scenePlayer.Rot.Z),
|
||||
},
|
||||
}
|
||||
scenePlayerLocationNotify.PlayerLocList = append(scenePlayerLocationNotify.PlayerLocList, playerLocationInfo)
|
||||
}
|
||||
t.gameManager.SendMsg(proto.ApiScenePlayerLocationNotify, player.PlayerID, 0, scenePlayerLocationNotify)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TickManager) onTickSecond(now int64) {
|
||||
for _, world := range t.gameManager.worldManager.worldMap {
|
||||
for _, player := range world.playerMap {
|
||||
// PacketWorldPlayerRTTNotify
|
||||
worldPlayerRTTNotify := new(proto.WorldPlayerRTTNotify)
|
||||
worldPlayerRTTNotify.PlayerRttList = make([]*proto.PlayerRTTInfo, 0)
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
playerRTTInfo := &proto.PlayerRTTInfo{Uid: worldPlayer.PlayerID, Rtt: worldPlayer.ClientRTT}
|
||||
worldPlayerRTTNotify.PlayerRttList = append(worldPlayerRTTNotify.PlayerRttList, playerRTTInfo)
|
||||
}
|
||||
t.gameManager.SendMsg(proto.ApiWorldPlayerRTTNotify, player.PlayerID, 0, worldPlayerRTTNotify)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TickManager) onTick100MilliSecond(now int64) {
|
||||
// AttackHandler
|
||||
for _, world := range t.gameManager.worldManager.worldMap {
|
||||
for _, scene := range world.sceneMap {
|
||||
scene.AttackHandler(t.gameManager)
|
||||
}
|
||||
}
|
||||
|
||||
bigWorldOwner := t.gameManager.userManager.GetOnlineUser(1)
|
||||
bigWorld := t.gameManager.worldManager.GetBigWorld()
|
||||
bigWorldScene := bigWorld.GetSceneById(3)
|
||||
|
||||
if len(bigWorldScene.playerMap) < 2 {
|
||||
return
|
||||
}
|
||||
if t.gameManager.worldManager.worldStatic.aiMoveCurrIndex >= len(t.gameManager.worldManager.worldStatic.aiMoveVectorList)-1 {
|
||||
return
|
||||
}
|
||||
t.gameManager.worldManager.worldStatic.aiMoveCurrIndex++
|
||||
|
||||
entityMoveInfo := new(proto.EntityMoveInfo)
|
||||
activeAvatarId := bigWorldOwner.TeamConfig.GetActiveAvatarId()
|
||||
playerTeamEntity := bigWorldScene.GetPlayerTeamEntity(bigWorldOwner.PlayerID)
|
||||
entityMoveInfo.EntityId = playerTeamEntity.avatarEntityMap[activeAvatarId]
|
||||
entityMoveInfo.SceneTime = uint32(bigWorldScene.GetSceneTime())
|
||||
entityMoveInfo.ReliableSeq = uint32(bigWorldScene.GetSceneTime() / 100 * 100)
|
||||
entityMoveInfo.IsReliable = true
|
||||
oldPos := model.Vector{
|
||||
X: bigWorldOwner.Pos.X,
|
||||
Y: bigWorldOwner.Pos.Y,
|
||||
Z: bigWorldOwner.Pos.Z,
|
||||
}
|
||||
newPos := t.gameManager.worldManager.worldStatic.aiMoveVectorList[t.gameManager.worldManager.worldStatic.aiMoveCurrIndex]
|
||||
rotY := math.Atan2(newPos.X-oldPos.X, newPos.Z-oldPos.Z) / math.Pi * 180.0
|
||||
if rotY < 0.0 {
|
||||
rotY += 360.0
|
||||
}
|
||||
entityMoveInfo.MotionInfo = &proto.MotionInfo{
|
||||
Pos: &proto.Vector{
|
||||
X: float32(newPos.X),
|
||||
Y: float32(newPos.Y),
|
||||
Z: float32(newPos.Z),
|
||||
},
|
||||
Rot: &proto.Vector{
|
||||
X: 0.0,
|
||||
Y: float32(rotY),
|
||||
Z: 0.0,
|
||||
},
|
||||
Speed: &proto.Vector{
|
||||
X: float32((newPos.X - oldPos.X) * 10.0),
|
||||
Y: float32((newPos.Y - oldPos.Y) * 10.0),
|
||||
Z: float32((newPos.Z - oldPos.Z) * 10.0),
|
||||
},
|
||||
State: proto.MotionState_MOTION_STATE_RUN,
|
||||
RefPos: new(proto.Vector),
|
||||
}
|
||||
data, err := pb.Marshal(entityMoveInfo)
|
||||
if err != nil {
|
||||
logger.LOG.Error("build combat invocations entity move info error: %v", err)
|
||||
return
|
||||
}
|
||||
combatInvocationsNotify := new(proto.CombatInvocationsNotify)
|
||||
combatInvocationsNotify.InvokeList = []*proto.CombatInvokeEntry{{
|
||||
CombatData: data,
|
||||
ForwardType: proto.ForwardType_FORWARD_TYPE_TO_ALL_EXCEPT_CUR,
|
||||
ArgumentType: proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_ENTITY_MOVE,
|
||||
}}
|
||||
t.gameManager.CombatInvocationsNotify(bigWorldOwner.PlayerID, bigWorldOwner, 0, combatInvocationsNotify)
|
||||
}
|
||||
|
||||
func (t *TickManager) createMonster(scene *Scene) uint32 {
|
||||
pos := &model.Vector{
|
||||
X: 2747,
|
||||
Y: 194,
|
||||
Z: -1719,
|
||||
}
|
||||
fpm := map[uint32]float32{
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP): float32(72.91699),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_PHYSICAL_SUB_HURT): float32(0.1),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_DEFENSE): float32(505.0),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_ATTACK): float32(45.679916),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_ICE_SUB_HURT): float32(0.1),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_ATTACK): float32(45.679916),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_MAX_HP): float32(72.91699),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_FIRE_SUB_HURT): float32(0.1),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_ELEC_SUB_HURT): float32(0.1),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_WIND_SUB_HURT): float32(0.1),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_ROCK_SUB_HURT): float32(0.1),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_GRASS_SUB_HURT): float32(0.1),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_WATER_SUB_HURT): float32(0.1),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_HP): float32(72.91699),
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_DEFENSE): float32(505.0),
|
||||
}
|
||||
entityId := scene.CreateEntityMonster(pos, 1, fpm)
|
||||
return entityId
|
||||
}
|
||||
322
service/game-hk4e/game/user_avatar.go
Normal file
322
service/game-hk4e/game/user_avatar.go
Normal file
@@ -0,0 +1,322 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/common/utils/object"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func (g *GameManager) GetAllAvatarDataConfig() map[int32]*gdc.AvatarData {
|
||||
allAvatarDataConfig := make(map[int32]*gdc.AvatarData)
|
||||
for avatarId, avatarData := range gdc.CONF.AvatarDataMap {
|
||||
if avatarId < 10000002 || avatarId >= 11000000 {
|
||||
// 跳过无效角色
|
||||
continue
|
||||
}
|
||||
if avatarId == 10000005 || avatarId == 10000007 {
|
||||
// 跳过主角
|
||||
continue
|
||||
}
|
||||
allAvatarDataConfig[avatarId] = avatarData
|
||||
}
|
||||
return allAvatarDataConfig
|
||||
}
|
||||
|
||||
func (g *GameManager) AddUserAvatar(userId uint32, avatarId uint32) {
|
||||
player := g.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
player.AddAvatar(avatarId)
|
||||
|
||||
// 添加初始武器
|
||||
avatarDataConfig := gdc.CONF.AvatarDataMap[int32(avatarId)]
|
||||
weaponId := g.AddUserWeapon(player.PlayerID, uint32(avatarDataConfig.InitialWeapon))
|
||||
|
||||
// 角色装上初始武器
|
||||
g.WearUserAvatarEquip(player.PlayerID, avatarId, weaponId)
|
||||
|
||||
// TODO 真的有必要存在吗
|
||||
g.UpdateUserAvatarFightProp(player.PlayerID, avatarId)
|
||||
|
||||
// PacketAvatarAddNotify
|
||||
avatar := player.AvatarMap[avatarId]
|
||||
avatarAddNotify := new(proto.AvatarAddNotify)
|
||||
avatarAddNotify.Avatar = g.PacketAvatarInfo(avatar)
|
||||
avatarAddNotify.IsInTeam = false
|
||||
g.SendMsg(proto.ApiAvatarAddNotify, userId, player.ClientSeq, avatarAddNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) WearEquipReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user wear equip, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.WearEquipReq)
|
||||
avatarGuid := req.AvatarGuid
|
||||
equipGuid := req.EquipGuid
|
||||
avatar := player.GameObjectGuidMap[avatarGuid].(*model.Avatar)
|
||||
weapon := player.GameObjectGuidMap[equipGuid].(*model.Weapon)
|
||||
g.WearUserAvatarEquip(player.PlayerID, avatar.AvatarId, weapon.WeaponId)
|
||||
|
||||
// PacketWearEquipRsp
|
||||
wearEquipRsp := new(proto.WearEquipRsp)
|
||||
wearEquipRsp.AvatarGuid = avatarGuid
|
||||
wearEquipRsp.EquipGuid = equipGuid
|
||||
g.SendMsg(proto.ApiWearEquipRsp, userId, player.ClientSeq, wearEquipRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) WearUserAvatarEquip(userId uint32, avatarId uint32, weaponId uint64) {
|
||||
player := g.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
avatar := player.AvatarMap[avatarId]
|
||||
weapon := player.WeaponMap[weaponId]
|
||||
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID)
|
||||
team := player.TeamConfig.GetActiveTeam()
|
||||
|
||||
if weapon.AvatarId != 0 {
|
||||
// 武器在别的角色身上
|
||||
weakAvatarId := weapon.AvatarId
|
||||
weakWeaponId := weaponId
|
||||
strongAvatarId := avatarId
|
||||
strongWeaponId := avatar.EquipWeapon.WeaponId
|
||||
player.TakeOffWeapon(weakAvatarId, weakWeaponId)
|
||||
player.TakeOffWeapon(strongAvatarId, strongWeaponId)
|
||||
player.WearWeapon(weakAvatarId, strongWeaponId)
|
||||
player.WearWeapon(strongAvatarId, weakWeaponId)
|
||||
|
||||
weakAvatar := player.AvatarMap[weakAvatarId]
|
||||
weakWeapon := player.WeaponMap[weakAvatar.EquipWeapon.WeaponId]
|
||||
|
||||
for _, aid := range team.AvatarIdList {
|
||||
if aid == 0 {
|
||||
break
|
||||
}
|
||||
if aid == weakAvatar.AvatarId {
|
||||
playerTeamEntity.weaponEntityMap[weakWeapon.WeaponId] = scene.CreateEntityWeapon()
|
||||
}
|
||||
}
|
||||
|
||||
// PacketAvatarEquipChangeNotify
|
||||
avatarEquipChangeNotify := g.PacketAvatarEquipChangeNotify(weakAvatar, weakWeapon, playerTeamEntity.weaponEntityMap[weakWeapon.WeaponId])
|
||||
g.SendMsg(proto.ApiAvatarEquipChangeNotify, userId, player.ClientSeq, avatarEquipChangeNotify)
|
||||
} else if avatar.EquipWeapon != nil {
|
||||
// 角色当前有武器
|
||||
player.TakeOffWeapon(avatarId, avatar.EquipWeapon.WeaponId)
|
||||
player.WearWeapon(avatarId, weaponId)
|
||||
} else {
|
||||
// 是新角色还没有武器
|
||||
player.WearWeapon(avatarId, weaponId)
|
||||
}
|
||||
|
||||
for _, aid := range team.AvatarIdList {
|
||||
if aid == 0 {
|
||||
break
|
||||
}
|
||||
if aid == avatarId {
|
||||
playerTeamEntity.weaponEntityMap[weaponId] = scene.CreateEntityWeapon()
|
||||
}
|
||||
}
|
||||
|
||||
// PacketAvatarEquipChangeNotify
|
||||
avatarEquipChangeNotify := g.PacketAvatarEquipChangeNotify(avatar, weapon, playerTeamEntity.weaponEntityMap[weaponId])
|
||||
g.SendMsg(proto.ApiAvatarEquipChangeNotify, userId, player.ClientSeq, avatarEquipChangeNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) AvatarChangeCostumeReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change avatar costume, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.AvatarChangeCostumeReq)
|
||||
avatarGuid := req.AvatarGuid
|
||||
costumeId := req.CostumeId
|
||||
|
||||
exist := false
|
||||
for _, v := range player.CostumeList {
|
||||
if v == costumeId {
|
||||
exist = true
|
||||
}
|
||||
}
|
||||
if costumeId == 0 {
|
||||
exist = true
|
||||
}
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
|
||||
avatar := player.GameObjectGuidMap[avatarGuid].(*model.Avatar)
|
||||
avatar.Costume = req.CostumeId
|
||||
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
|
||||
// PacketAvatarChangeCostumeNotify
|
||||
avatarChangeCostumeNotify := new(proto.AvatarChangeCostumeNotify)
|
||||
avatarChangeCostumeNotify.EntityInfo = g.PacketSceneEntityInfoAvatar(scene, player, avatar.AvatarId)
|
||||
for _, scenePlayer := range scene.playerMap {
|
||||
g.SendMsg(proto.ApiAvatarChangeCostumeNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, avatarChangeCostumeNotify)
|
||||
}
|
||||
|
||||
// PacketAvatarChangeCostumeRsp
|
||||
avatarChangeCostumeRsp := new(proto.AvatarChangeCostumeRsp)
|
||||
avatarChangeCostumeRsp.AvatarGuid = req.AvatarGuid
|
||||
avatarChangeCostumeRsp.CostumeId = req.CostumeId
|
||||
g.SendMsg(proto.ApiAvatarChangeCostumeRsp, userId, player.ClientSeq, avatarChangeCostumeRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) AvatarWearFlycloakReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change avatar fly cloak, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.AvatarWearFlycloakReq)
|
||||
avatarGuid := req.AvatarGuid
|
||||
flycloakId := req.FlycloakId
|
||||
|
||||
exist := false
|
||||
for _, v := range player.FlyCloakList {
|
||||
if v == flycloakId {
|
||||
exist = true
|
||||
}
|
||||
}
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
|
||||
avatar := player.GameObjectGuidMap[avatarGuid].(*model.Avatar)
|
||||
avatar.FlyCloak = req.FlycloakId
|
||||
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
|
||||
// PacketAvatarFlycloakChangeNotify
|
||||
avatarFlycloakChangeNotify := new(proto.AvatarFlycloakChangeNotify)
|
||||
avatarFlycloakChangeNotify.AvatarGuid = avatarGuid
|
||||
avatarFlycloakChangeNotify.FlycloakId = flycloakId
|
||||
for _, scenePlayer := range scene.playerMap {
|
||||
g.SendMsg(proto.ApiAvatarFlycloakChangeNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, avatarFlycloakChangeNotify)
|
||||
}
|
||||
|
||||
// PacketAvatarWearFlycloakRsp
|
||||
avatarWearFlycloakRsp := new(proto.AvatarWearFlycloakRsp)
|
||||
avatarWearFlycloakRsp.AvatarGuid = req.AvatarGuid
|
||||
avatarWearFlycloakRsp.FlycloakId = req.FlycloakId
|
||||
g.SendMsg(proto.ApiAvatarWearFlycloakRsp, userId, player.ClientSeq, avatarWearFlycloakRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketAvatarEquipChangeNotify(avatar *model.Avatar, weapon *model.Weapon, entityId uint32) *proto.AvatarEquipChangeNotify {
|
||||
itemDataConfig := gdc.CONF.ItemDataMap[int32(weapon.ItemId)]
|
||||
avatarEquipChangeNotify := new(proto.AvatarEquipChangeNotify)
|
||||
avatarEquipChangeNotify.AvatarGuid = avatar.Guid
|
||||
avatarEquipChangeNotify.EquipType = uint32(itemDataConfig.EquipEnumType)
|
||||
avatarEquipChangeNotify.ItemId = weapon.ItemId
|
||||
avatarEquipChangeNotify.EquipGuid = weapon.Guid
|
||||
avatarEquipChangeNotify.Weapon = &proto.SceneWeaponInfo{
|
||||
EntityId: entityId,
|
||||
GadgetId: uint32(gdc.CONF.ItemDataMap[int32(weapon.ItemId)].GadgetId),
|
||||
ItemId: weapon.ItemId,
|
||||
Guid: weapon.Guid,
|
||||
Level: uint32(weapon.Level),
|
||||
AbilityInfo: new(proto.AbilitySyncStateInfo),
|
||||
}
|
||||
return avatarEquipChangeNotify
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketAvatarEquipTakeOffNotify(avatar *model.Avatar, weapon *model.Weapon) *proto.AvatarEquipChangeNotify {
|
||||
itemDataConfig := gdc.CONF.ItemDataMap[int32(weapon.ItemId)]
|
||||
avatarEquipChangeNotify := new(proto.AvatarEquipChangeNotify)
|
||||
avatarEquipChangeNotify.AvatarGuid = avatar.Guid
|
||||
avatarEquipChangeNotify.EquipType = uint32(itemDataConfig.EquipEnumType)
|
||||
return avatarEquipChangeNotify
|
||||
}
|
||||
|
||||
func (g *GameManager) UpdateUserAvatarFightProp(userId uint32, avatarId uint32) {
|
||||
player := g.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
avatarFightPropNotify := new(proto.AvatarFightPropNotify)
|
||||
avatar := player.AvatarMap[avatarId]
|
||||
avatarFightPropNotify.AvatarGuid = avatar.Guid
|
||||
avatarFightPropNotify.FightPropMap = avatar.FightPropMap
|
||||
g.SendMsg(proto.ApiAvatarFightPropNotify, userId, player.ClientSeq, avatarFightPropNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketAvatarInfo(avatar *model.Avatar) *proto.AvatarInfo {
|
||||
isFocus := false
|
||||
//if avatar.AvatarId == 10000005 || avatar.AvatarId == 10000007 {
|
||||
// isFocus = true
|
||||
//}
|
||||
pbAvatar := &proto.AvatarInfo{
|
||||
IsFocus: isFocus,
|
||||
AvatarId: avatar.AvatarId,
|
||||
Guid: avatar.Guid,
|
||||
PropMap: map[uint32]*proto.PropValue{
|
||||
uint32(constant.PlayerPropertyConst.PROP_LEVEL): {
|
||||
Type: uint32(constant.PlayerPropertyConst.PROP_LEVEL),
|
||||
Val: int64(avatar.Level),
|
||||
Value: &proto.PropValue_Ival{Ival: int64(avatar.Level)},
|
||||
},
|
||||
uint32(constant.PlayerPropertyConst.PROP_EXP): {
|
||||
Type: uint32(constant.PlayerPropertyConst.PROP_EXP),
|
||||
Val: int64(avatar.Exp),
|
||||
Value: &proto.PropValue_Ival{Ival: int64(avatar.Exp)},
|
||||
},
|
||||
uint32(constant.PlayerPropertyConst.PROP_BREAK_LEVEL): {
|
||||
Type: uint32(constant.PlayerPropertyConst.PROP_BREAK_LEVEL),
|
||||
Val: int64(avatar.Promote),
|
||||
Value: &proto.PropValue_Ival{Ival: int64(avatar.Promote)},
|
||||
},
|
||||
uint32(constant.PlayerPropertyConst.PROP_SATIATION_VAL): {
|
||||
Type: uint32(constant.PlayerPropertyConst.PROP_SATIATION_VAL),
|
||||
Val: 0,
|
||||
Value: &proto.PropValue_Ival{Ival: 0},
|
||||
},
|
||||
uint32(constant.PlayerPropertyConst.PROP_SATIATION_PENALTY_TIME): {
|
||||
Type: uint32(constant.PlayerPropertyConst.PROP_SATIATION_PENALTY_TIME),
|
||||
Val: 0,
|
||||
Value: &proto.PropValue_Ival{Ival: 0},
|
||||
},
|
||||
},
|
||||
LifeState: 1,
|
||||
EquipGuidList: object.ConvMapToList(avatar.EquipGuidList),
|
||||
FightPropMap: nil,
|
||||
SkillDepotId: avatar.SkillDepotId,
|
||||
FetterInfo: &proto.AvatarFetterInfo{
|
||||
ExpLevel: uint32(avatar.FetterLevel),
|
||||
ExpNumber: avatar.FetterExp,
|
||||
// FetterList 不知道是啥 该角色在配置表里的所有FetterId
|
||||
// TODO 资料解锁条目
|
||||
FetterList: nil,
|
||||
RewardedFetterLevelList: []uint32{10},
|
||||
},
|
||||
SkillLevelMap: nil,
|
||||
AvatarType: 1,
|
||||
WearingFlycloakId: avatar.FlyCloak,
|
||||
CostumeId: avatar.Costume,
|
||||
BornTime: uint32(avatar.BornTime),
|
||||
}
|
||||
pbAvatar.FightPropMap = avatar.FightPropMap
|
||||
for _, v := range avatar.FetterList {
|
||||
pbAvatar.FetterInfo.FetterList = append(pbAvatar.FetterInfo.FetterList, &proto.FetterData{
|
||||
FetterId: v,
|
||||
FetterState: uint32(constant.FetterStateConst.FINISH),
|
||||
})
|
||||
}
|
||||
// 解锁全部资料
|
||||
for _, v := range gdc.CONF.AvatarFetterDataMap[int32(avatar.AvatarId)] {
|
||||
pbAvatar.FetterInfo.FetterList = append(pbAvatar.FetterInfo.FetterList, &proto.FetterData{
|
||||
FetterId: uint32(v),
|
||||
FetterState: uint32(constant.FetterStateConst.FINISH),
|
||||
})
|
||||
}
|
||||
pbAvatar.SkillLevelMap = make(map[uint32]uint32)
|
||||
for k, v := range avatar.SkillLevelMap {
|
||||
pbAvatar.SkillLevelMap[k] = v
|
||||
}
|
||||
return pbAvatar
|
||||
}
|
||||
254
service/game-hk4e/game/user_chat.go
Normal file
254
service/game-hk4e/game/user_chat.go
Normal file
@@ -0,0 +1,254 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (g *GameManager) PullRecentChatReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user pull recent chat, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.PullRecentChatReq)
|
||||
// 经研究发现 原神现网环境 客户端仅拉取最新的5条未读聊天消息 所以人太多的话小姐姐不回你消息是有原因的
|
||||
// 因此 阿米你这样做真的合适吗 不过现在代码到了我手上我想怎么写就怎么写 我才不会重蹈覆辙
|
||||
_ = req.PullNum
|
||||
|
||||
retMsgList := make([]*proto.ChatInfo, 0)
|
||||
for _, msgList := range player.ChatMsgMap {
|
||||
for _, chatMsg := range msgList {
|
||||
// 反手就是一个遍历
|
||||
if chatMsg.IsRead {
|
||||
continue
|
||||
}
|
||||
retMsgList = append(retMsgList, g.ConvChatMsgToChatInfo(chatMsg))
|
||||
}
|
||||
}
|
||||
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
if world.multiplayer {
|
||||
chatList := world.GetChatList()
|
||||
count := len(chatList)
|
||||
if count > 10 {
|
||||
count = 10
|
||||
}
|
||||
for i := len(chatList) - count; i < len(chatList); i++ {
|
||||
// PacketPlayerChatNotify
|
||||
playerChatNotify := new(proto.PlayerChatNotify)
|
||||
playerChatNotify.ChannelId = 0
|
||||
playerChatNotify.ChatInfo = chatList[i]
|
||||
g.SendMsg(proto.ApiPlayerChatNotify, player.PlayerID, 0, playerChatNotify)
|
||||
}
|
||||
}
|
||||
|
||||
// PacketPullRecentChatRsp
|
||||
pullRecentChatRsp := new(proto.PullRecentChatRsp)
|
||||
pullRecentChatRsp.ChatInfo = retMsgList
|
||||
g.SendMsg(proto.ApiPullRecentChatRsp, player.PlayerID, 0, pullRecentChatRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) PullPrivateChatReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user pull private chat, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.PullPrivateChatReq)
|
||||
targetUid := req.TargetUid
|
||||
pullNum := req.PullNum
|
||||
fromSequence := req.FromSequence
|
||||
|
||||
msgList, exist := player.ChatMsgMap[targetUid]
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
if pullNum+fromSequence > uint32(len(msgList)) {
|
||||
pullNum = uint32(len(msgList)) - fromSequence
|
||||
}
|
||||
recentMsgList := msgList[fromSequence : fromSequence+pullNum]
|
||||
retMsgList := make([]*proto.ChatInfo, 0)
|
||||
for _, chatMsg := range recentMsgList {
|
||||
retMsgList = append(retMsgList, g.ConvChatMsgToChatInfo(chatMsg))
|
||||
}
|
||||
|
||||
// PacketPullPrivateChatRsp
|
||||
pullPrivateChatRsp := new(proto.PullPrivateChatRsp)
|
||||
pullPrivateChatRsp.ChatInfo = retMsgList
|
||||
g.SendMsg(proto.ApiPullPrivateChatRsp, player.PlayerID, 0, pullPrivateChatRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) PrivateChatReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user send private chat, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.PrivateChatReq)
|
||||
targetUid := req.TargetUid
|
||||
content := req.Content
|
||||
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := g.userManager.LoadTempOfflineUserSync(targetUid)
|
||||
if targetPlayer == nil {
|
||||
return
|
||||
}
|
||||
chatInfo := &proto.ChatInfo{
|
||||
Time: uint32(time.Now().Unix()),
|
||||
Sequence: 101,
|
||||
ToUid: targetPlayer.PlayerID,
|
||||
Uid: player.PlayerID,
|
||||
IsRead: false,
|
||||
Content: nil,
|
||||
}
|
||||
switch content.(type) {
|
||||
case *proto.PrivateChatReq_Text:
|
||||
text := content.(*proto.PrivateChatReq_Text).Text
|
||||
if len(text) == 0 {
|
||||
return
|
||||
}
|
||||
chatInfo.Content = &proto.ChatInfo_Text{
|
||||
Text: text,
|
||||
}
|
||||
case *proto.PrivateChatReq_Icon:
|
||||
icon := content.(*proto.PrivateChatReq_Icon).Icon
|
||||
chatInfo.Content = &proto.ChatInfo_Icon{
|
||||
Icon: icon,
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
// 消息加入自己的队列
|
||||
msgList, exist := player.ChatMsgMap[targetPlayer.PlayerID]
|
||||
if !exist {
|
||||
msgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
msgList = append(msgList, g.ConvChatInfoToChatMsg(chatInfo))
|
||||
player.ChatMsgMap[targetPlayer.PlayerID] = msgList
|
||||
// 消息加入目标玩家的队列
|
||||
msgList, exist = targetPlayer.ChatMsgMap[player.PlayerID]
|
||||
if !exist {
|
||||
msgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
msgList = append(msgList, g.ConvChatInfoToChatMsg(chatInfo))
|
||||
targetPlayer.ChatMsgMap[player.PlayerID] = msgList
|
||||
|
||||
if targetPlayer.Online {
|
||||
// PacketPrivateChatNotify
|
||||
privateChatNotify := new(proto.PrivateChatNotify)
|
||||
privateChatNotify.ChatInfo = chatInfo
|
||||
g.SendMsg(proto.ApiPrivateChatNotify, targetPlayer.PlayerID, 0, privateChatNotify)
|
||||
}
|
||||
|
||||
// PacketPrivateChatNotify
|
||||
privateChatNotify := new(proto.PrivateChatNotify)
|
||||
privateChatNotify.ChatInfo = chatInfo
|
||||
g.SendMsg(proto.ApiPrivateChatNotify, player.PlayerID, 0, privateChatNotify)
|
||||
|
||||
// PacketPrivateChatRsp
|
||||
privateChatRsp := new(proto.PrivateChatRsp)
|
||||
g.SendMsg(proto.ApiPrivateChatRsp, player.PlayerID, 0, privateChatRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) ReadPrivateChatReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user read private chat, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.ReadPrivateChatReq)
|
||||
targetUid := req.TargetUid
|
||||
|
||||
msgList, exist := player.ChatMsgMap[targetUid]
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
for index, chatMsg := range msgList {
|
||||
chatMsg.IsRead = true
|
||||
msgList[index] = chatMsg
|
||||
}
|
||||
player.ChatMsgMap[targetUid] = msgList
|
||||
|
||||
// PacketReadPrivateChatRsp
|
||||
readPrivateChatRsp := new(proto.ReadPrivateChatRsp)
|
||||
g.SendMsg(proto.ApiReadPrivateChatRsp, player.PlayerID, 0, readPrivateChatRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) PlayerChatReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user multiplayer chat, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.PlayerChatReq)
|
||||
channelId := req.ChannelId
|
||||
chatInfo := req.ChatInfo
|
||||
|
||||
sendChatInfo := &proto.ChatInfo{
|
||||
Time: uint32(time.Now().Unix()),
|
||||
Uid: player.PlayerID,
|
||||
Content: nil,
|
||||
}
|
||||
switch chatInfo.Content.(type) {
|
||||
case *proto.ChatInfo_Text:
|
||||
text := chatInfo.Content.(*proto.ChatInfo_Text).Text
|
||||
if len(text) == 0 {
|
||||
return
|
||||
}
|
||||
sendChatInfo.Content = &proto.ChatInfo_Text{
|
||||
Text: text,
|
||||
}
|
||||
case *proto.ChatInfo_Icon:
|
||||
icon := chatInfo.Content.(*proto.ChatInfo_Icon).Icon
|
||||
sendChatInfo.Content = &proto.ChatInfo_Icon{
|
||||
Icon: icon,
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
world.AddChat(sendChatInfo)
|
||||
|
||||
// PacketPlayerChatNotify
|
||||
playerChatNotify := new(proto.PlayerChatNotify)
|
||||
playerChatNotify.ChannelId = channelId
|
||||
playerChatNotify.ChatInfo = sendChatInfo
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
g.SendMsg(proto.ApiPlayerChatNotify, worldPlayer.PlayerID, 0, playerChatNotify)
|
||||
}
|
||||
|
||||
// PacketPlayerChatRsp
|
||||
playerChatRsp := new(proto.PlayerChatRsp)
|
||||
g.SendMsg(proto.ApiPlayerChatRsp, player.PlayerID, 0, playerChatRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) ConvChatInfoToChatMsg(chatInfo *proto.ChatInfo) (chatMsg *model.ChatMsg) {
|
||||
chatMsg = &model.ChatMsg{
|
||||
Time: chatInfo.Time,
|
||||
ToUid: chatInfo.ToUid,
|
||||
Uid: chatInfo.Uid,
|
||||
IsRead: chatInfo.IsRead,
|
||||
MsgType: 0,
|
||||
Text: "",
|
||||
Icon: 0,
|
||||
}
|
||||
switch chatInfo.Content.(type) {
|
||||
case *proto.ChatInfo_Text:
|
||||
chatMsg.MsgType = model.ChatMsgTypeText
|
||||
chatMsg.Text = chatInfo.Content.(*proto.ChatInfo_Text).Text
|
||||
case *proto.ChatInfo_Icon:
|
||||
chatMsg.MsgType = model.ChatMsgTypeIcon
|
||||
chatMsg.Icon = chatInfo.Content.(*proto.ChatInfo_Icon).Icon
|
||||
default:
|
||||
}
|
||||
return chatMsg
|
||||
}
|
||||
|
||||
func (g *GameManager) ConvChatMsgToChatInfo(chatMsg *model.ChatMsg) (chatInfo *proto.ChatInfo) {
|
||||
chatInfo = &proto.ChatInfo{
|
||||
Time: chatMsg.Time,
|
||||
Sequence: 0,
|
||||
ToUid: chatMsg.ToUid,
|
||||
Uid: chatMsg.Uid,
|
||||
IsRead: chatMsg.IsRead,
|
||||
Content: nil,
|
||||
}
|
||||
switch chatMsg.MsgType {
|
||||
case model.ChatMsgTypeText:
|
||||
chatInfo.Content = &proto.ChatInfo_Text{
|
||||
Text: chatMsg.Text,
|
||||
}
|
||||
case model.ChatMsgTypeIcon:
|
||||
chatInfo.Content = &proto.ChatInfo_Icon{
|
||||
Icon: chatMsg.Icon,
|
||||
}
|
||||
default:
|
||||
}
|
||||
return chatInfo
|
||||
}
|
||||
402
service/game-hk4e/game/user_combat.go
Normal file
402
service/game-hk4e/game/user_combat.go
Normal file
@@ -0,0 +1,402 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func (g *GameManager) CombatInvocationsNotify(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
//logger.LOG.Debug("user combat invocations, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.CombatInvocationsNotify)
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
if world == nil {
|
||||
return
|
||||
}
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
invokeHandler := NewInvokeHandler[proto.CombatInvokeEntry]()
|
||||
for _, entry := range req.InvokeList {
|
||||
//logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID)
|
||||
switch entry.ArgumentType {
|
||||
case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT:
|
||||
scene.AddAttack(&Attack{
|
||||
combatInvokeEntry: entry,
|
||||
uid: player.PlayerID,
|
||||
})
|
||||
case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_ENTITY_MOVE:
|
||||
entityMoveInfo := new(proto.EntityMoveInfo)
|
||||
err := pb.Unmarshal(entry.CombatData, entityMoveInfo)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse combat invocations entity move info error: %v", err)
|
||||
continue
|
||||
}
|
||||
motionInfo := entityMoveInfo.MotionInfo
|
||||
if motionInfo.Pos == nil || motionInfo.Rot == nil {
|
||||
continue
|
||||
}
|
||||
activeAvatarId := player.TeamConfig.GetActiveAvatarId()
|
||||
playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID)
|
||||
playerActiveAvatarEntityId := playerTeamEntity.avatarEntityMap[activeAvatarId]
|
||||
if entityMoveInfo.EntityId == playerActiveAvatarEntityId {
|
||||
// 玩家在移动
|
||||
ok := world.aoiManager.IsValidAoiPos(motionInfo.Pos.X, motionInfo.Pos.Y, motionInfo.Pos.Z)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// aoi
|
||||
oldGid := world.aoiManager.GetGidByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z))
|
||||
newGid := world.aoiManager.GetGidByPos(motionInfo.Pos.X, motionInfo.Pos.Y, motionInfo.Pos.Z)
|
||||
if oldGid != newGid {
|
||||
// 跨越了格子
|
||||
oldGridList := world.aoiManager.GetSurrGridListByGid(oldGid)
|
||||
oldEntityIdMap := make(map[uint32]bool)
|
||||
for _, grid := range oldGridList {
|
||||
tmp := grid.GetEntityIdList()
|
||||
for _, v := range tmp {
|
||||
oldEntityIdMap[v] = true
|
||||
}
|
||||
}
|
||||
newGridList := world.aoiManager.GetSurrGridListByGid(newGid)
|
||||
newEntityIdMap := make(map[uint32]bool)
|
||||
for _, grid := range newGridList {
|
||||
tmp := grid.GetEntityIdList()
|
||||
for _, v := range tmp {
|
||||
newEntityIdMap[v] = true
|
||||
}
|
||||
}
|
||||
delEntityIdList := make([]uint32, 0)
|
||||
delUidList := make([]uint32, 0)
|
||||
for oldEntityId := range oldEntityIdMap {
|
||||
_, exist := newEntityIdMap[oldEntityId]
|
||||
if exist {
|
||||
continue
|
||||
}
|
||||
delEntityIdList = append(delEntityIdList, oldEntityId)
|
||||
entity := scene.GetEntity(oldEntityId)
|
||||
if entity == nil {
|
||||
continue
|
||||
}
|
||||
if entity.avatarEntity != nil {
|
||||
delUidList = append(delUidList, entity.avatarEntity.uid)
|
||||
}
|
||||
}
|
||||
addEntityIdList := make([]uint32, 0)
|
||||
addUidList := make([]uint32, 0)
|
||||
for newEntityId := range newEntityIdMap {
|
||||
_, exist := oldEntityIdMap[newEntityId]
|
||||
if exist {
|
||||
continue
|
||||
}
|
||||
addEntityIdList = append(addEntityIdList, newEntityId)
|
||||
entity := scene.GetEntity(newEntityId)
|
||||
if entity == nil {
|
||||
continue
|
||||
}
|
||||
if entity.avatarEntity != nil {
|
||||
addUidList = append(addUidList, entity.avatarEntity.uid)
|
||||
}
|
||||
}
|
||||
// 发送已消失格子里的实体消失通知
|
||||
g.RemoveSceneEntityNotifyToPlayer(player, delEntityIdList)
|
||||
// 发送新出现格子里的实体出现通知
|
||||
g.AddSceneEntityNotify(player, proto.VisionType_VISION_TYPE_BORN, addEntityIdList, false)
|
||||
// 更新玩家的位置信息
|
||||
player.Pos.X = float64(motionInfo.Pos.X)
|
||||
player.Pos.Y = float64(motionInfo.Pos.Y)
|
||||
player.Pos.Z = float64(motionInfo.Pos.Z)
|
||||
// 更新玩家所在格子
|
||||
world.aoiManager.RemoveEntityIdFromGrid(playerActiveAvatarEntityId, oldGid)
|
||||
world.aoiManager.AddEntityIdToGrid(playerActiveAvatarEntityId, newGid)
|
||||
// 其他玩家
|
||||
for _, uid := range delUidList {
|
||||
otherPlayer := g.userManager.GetOnlineUser(uid)
|
||||
g.RemoveSceneEntityNotifyToPlayer(otherPlayer, []uint32{playerActiveAvatarEntityId})
|
||||
}
|
||||
for _, uid := range addUidList {
|
||||
otherPlayer := g.userManager.GetOnlineUser(uid)
|
||||
g.AddSceneEntityNotify(otherPlayer, proto.VisionType_VISION_TYPE_BORN, []uint32{playerActiveAvatarEntityId}, false)
|
||||
}
|
||||
}
|
||||
// 把队伍中的其他非活跃角色也同步进行移动
|
||||
team := player.TeamConfig.GetActiveTeam()
|
||||
for _, avatarId := range team.AvatarIdList {
|
||||
// 跳过当前的活跃角色
|
||||
if avatarId == activeAvatarId {
|
||||
continue
|
||||
}
|
||||
entityId := playerTeamEntity.avatarEntityMap[avatarId]
|
||||
entity := scene.GetEntity(entityId)
|
||||
if entity == nil {
|
||||
continue
|
||||
}
|
||||
entity.pos.X = float64(motionInfo.Pos.X)
|
||||
entity.pos.Y = float64(motionInfo.Pos.Y)
|
||||
entity.pos.Z = float64(motionInfo.Pos.Z)
|
||||
entity.rot.X = float64(motionInfo.Rot.X)
|
||||
entity.rot.Y = float64(motionInfo.Rot.Y)
|
||||
entity.rot.Z = float64(motionInfo.Rot.Z)
|
||||
}
|
||||
// 更新玩家的位置信息
|
||||
player.Pos.X = float64(motionInfo.Pos.X)
|
||||
player.Pos.Y = float64(motionInfo.Pos.Y)
|
||||
player.Pos.Z = float64(motionInfo.Pos.Z)
|
||||
player.Rot.X = float64(motionInfo.Rot.X)
|
||||
player.Rot.Y = float64(motionInfo.Rot.Y)
|
||||
player.Rot.Z = float64(motionInfo.Rot.Z)
|
||||
// TODO 采集大地图地形数据
|
||||
if world.IsBigWorld() && scene.id == 3 && player.PlayerID != 1 {
|
||||
if motionInfo.State == proto.MotionState_MOTION_STATE_WALK ||
|
||||
motionInfo.State == proto.MotionState_MOTION_STATE_RUN ||
|
||||
motionInfo.State == proto.MotionState_MOTION_STATE_DASH ||
|
||||
motionInfo.State == proto.MotionState_MOTION_STATE_CLIMB {
|
||||
logger.LOG.Debug("set terr motionInfo: %v", motionInfo)
|
||||
exist := g.worldManager.worldStatic.GetTerrain(int16(motionInfo.Pos.X), int16(motionInfo.Pos.Y), int16(motionInfo.Pos.Z))
|
||||
g.worldManager.worldStatic.SetTerrain(int16(motionInfo.Pos.X), int16(motionInfo.Pos.Y), int16(motionInfo.Pos.Z))
|
||||
if !exist {
|
||||
// TODO 薄荷标记
|
||||
// 只给附近aoi区域的玩家广播消息
|
||||
surrPlayerList := make([]*model.Player, 0)
|
||||
entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z))
|
||||
for _, entityId := range entityIdList {
|
||||
entity := scene.GetEntity(entityId)
|
||||
if entity == nil {
|
||||
continue
|
||||
}
|
||||
if entity.avatarEntity != nil {
|
||||
otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid)
|
||||
surrPlayerList = append(surrPlayerList, otherPlayer)
|
||||
}
|
||||
}
|
||||
pos := &model.Vector{
|
||||
X: float64(int16(motionInfo.Pos.X)),
|
||||
Y: float64(int16(motionInfo.Pos.Y)),
|
||||
Z: float64(int16(motionInfo.Pos.Z)),
|
||||
}
|
||||
gadgetEntityId := scene.CreateEntityGadget(pos, 3003009)
|
||||
for _, otherPlayer := range surrPlayerList {
|
||||
g.AddSceneEntityNotify(otherPlayer, proto.VisionType_VISION_TYPE_BORN, []uint32{gadgetEntityId}, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 更新场景实体的位置信息
|
||||
sceneEntity := scene.GetEntity(entityMoveInfo.EntityId)
|
||||
if sceneEntity != nil {
|
||||
sceneEntity.pos = &model.Vector{
|
||||
X: float64(motionInfo.Pos.X),
|
||||
Y: float64(motionInfo.Pos.Y),
|
||||
Z: float64(motionInfo.Pos.Z),
|
||||
}
|
||||
sceneEntity.rot = &model.Vector{
|
||||
X: float64(motionInfo.Rot.X),
|
||||
Y: float64(motionInfo.Rot.Y),
|
||||
Z: float64(motionInfo.Rot.Z),
|
||||
}
|
||||
sceneEntity.moveState = uint16(motionInfo.State)
|
||||
sceneEntity.lastMoveSceneTimeMs = entityMoveInfo.SceneTime
|
||||
sceneEntity.lastMoveReliableSeq = entityMoveInfo.ReliableSeq
|
||||
//logger.LOG.Debug("entity move, id: %v, pos: %v, uid: %v", sceneEntity.id, sceneEntity.pos, player.PlayerID)
|
||||
}
|
||||
invokeHandler.addEntry(entry.ForwardType, entry)
|
||||
default:
|
||||
invokeHandler.addEntry(entry.ForwardType, entry)
|
||||
}
|
||||
}
|
||||
|
||||
// 只给附近aoi区域的玩家广播消息
|
||||
surrPlayerList := make([]*model.Player, 0)
|
||||
entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z))
|
||||
for _, entityId := range entityIdList {
|
||||
entity := scene.GetEntity(entityId)
|
||||
if entity == nil {
|
||||
continue
|
||||
}
|
||||
if entity.avatarEntity != nil {
|
||||
otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid)
|
||||
surrPlayerList = append(surrPlayerList, otherPlayer)
|
||||
}
|
||||
}
|
||||
|
||||
// PacketCombatInvocationsNotify
|
||||
if invokeHandler.AllLen() > 0 {
|
||||
combatInvocationsNotify := new(proto.CombatInvocationsNotify)
|
||||
combatInvocationsNotify.InvokeList = invokeHandler.entryListForwardAll
|
||||
for _, v := range surrPlayerList {
|
||||
g.SendMsg(proto.ApiCombatInvocationsNotify, v.PlayerID, v.ClientSeq, combatInvocationsNotify)
|
||||
}
|
||||
}
|
||||
if invokeHandler.AllExceptCurLen() > 0 {
|
||||
combatInvocationsNotify := new(proto.CombatInvocationsNotify)
|
||||
combatInvocationsNotify.InvokeList = invokeHandler.entryListForwardAllExceptCur
|
||||
for _, v := range surrPlayerList {
|
||||
if player.PlayerID == v.PlayerID {
|
||||
continue
|
||||
}
|
||||
g.SendMsg(proto.ApiCombatInvocationsNotify, v.PlayerID, v.ClientSeq, combatInvocationsNotify)
|
||||
}
|
||||
}
|
||||
if invokeHandler.HostLen() > 0 {
|
||||
combatInvocationsNotify := new(proto.CombatInvocationsNotify)
|
||||
combatInvocationsNotify.InvokeList = invokeHandler.entryListForwardHost
|
||||
g.SendMsg(proto.ApiCombatInvocationsNotify, world.owner.PlayerID, world.owner.ClientSeq, combatInvocationsNotify)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) AbilityInvocationsNotify(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
//logger.LOG.Debug("user ability invocations, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.AbilityInvocationsNotify)
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
if world == nil {
|
||||
return
|
||||
}
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
invokeHandler := NewInvokeHandler[proto.AbilityInvokeEntry]()
|
||||
for _, entry := range req.Invokes {
|
||||
//logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID)
|
||||
invokeHandler.addEntry(entry.ForwardType, entry)
|
||||
}
|
||||
|
||||
// 只给附近aoi区域的玩家广播消息
|
||||
surrPlayerList := make([]*model.Player, 0)
|
||||
entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z))
|
||||
for _, entityId := range entityIdList {
|
||||
entity := scene.GetEntity(entityId)
|
||||
if entity == nil {
|
||||
continue
|
||||
}
|
||||
if entity.avatarEntity != nil {
|
||||
otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid)
|
||||
surrPlayerList = append(surrPlayerList, otherPlayer)
|
||||
}
|
||||
}
|
||||
|
||||
// PacketAbilityInvocationsNotify
|
||||
if invokeHandler.AllLen() > 0 {
|
||||
abilityInvocationsNotify := new(proto.AbilityInvocationsNotify)
|
||||
abilityInvocationsNotify.Invokes = invokeHandler.entryListForwardAll
|
||||
for _, v := range surrPlayerList {
|
||||
g.SendMsg(proto.ApiAbilityInvocationsNotify, v.PlayerID, v.ClientSeq, abilityInvocationsNotify)
|
||||
}
|
||||
}
|
||||
if invokeHandler.AllExceptCurLen() > 0 {
|
||||
abilityInvocationsNotify := new(proto.AbilityInvocationsNotify)
|
||||
abilityInvocationsNotify.Invokes = invokeHandler.entryListForwardAllExceptCur
|
||||
for _, v := range surrPlayerList {
|
||||
if player.PlayerID == v.PlayerID {
|
||||
continue
|
||||
}
|
||||
g.SendMsg(proto.ApiAbilityInvocationsNotify, v.PlayerID, v.ClientSeq, abilityInvocationsNotify)
|
||||
}
|
||||
}
|
||||
if invokeHandler.HostLen() > 0 {
|
||||
abilityInvocationsNotify := new(proto.AbilityInvocationsNotify)
|
||||
abilityInvocationsNotify.Invokes = invokeHandler.entryListForwardHost
|
||||
g.SendMsg(proto.ApiAbilityInvocationsNotify, world.owner.PlayerID, world.owner.ClientSeq, abilityInvocationsNotify)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) ClientAbilityInitFinishNotify(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
//logger.LOG.Debug("user client ability ok, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.ClientAbilityInitFinishNotify)
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
if world == nil {
|
||||
return
|
||||
}
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
invokeHandler := NewInvokeHandler[proto.AbilityInvokeEntry]()
|
||||
for _, entry := range req.Invokes {
|
||||
//logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID)
|
||||
invokeHandler.addEntry(entry.ForwardType, entry)
|
||||
}
|
||||
|
||||
// 只给附近aoi区域的玩家广播消息
|
||||
surrPlayerList := make([]*model.Player, 0)
|
||||
entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z))
|
||||
for _, entityId := range entityIdList {
|
||||
entity := scene.GetEntity(entityId)
|
||||
if entity == nil {
|
||||
continue
|
||||
}
|
||||
if entity.avatarEntity != nil {
|
||||
otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid)
|
||||
surrPlayerList = append(surrPlayerList, otherPlayer)
|
||||
}
|
||||
}
|
||||
|
||||
// PacketClientAbilityInitFinishNotify
|
||||
if invokeHandler.AllLen() > 0 {
|
||||
clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify)
|
||||
clientAbilityInitFinishNotify.Invokes = invokeHandler.entryListForwardAll
|
||||
for _, v := range surrPlayerList {
|
||||
g.SendMsg(proto.ApiClientAbilityInitFinishNotify, v.PlayerID, v.ClientSeq, clientAbilityInitFinishNotify)
|
||||
}
|
||||
}
|
||||
if invokeHandler.AllExceptCurLen() > 0 {
|
||||
clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify)
|
||||
clientAbilityInitFinishNotify.Invokes = invokeHandler.entryListForwardAllExceptCur
|
||||
for _, v := range surrPlayerList {
|
||||
if player.PlayerID == v.PlayerID {
|
||||
continue
|
||||
}
|
||||
g.SendMsg(proto.ApiClientAbilityInitFinishNotify, v.PlayerID, v.ClientSeq, clientAbilityInitFinishNotify)
|
||||
}
|
||||
}
|
||||
if invokeHandler.HostLen() > 0 {
|
||||
clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify)
|
||||
clientAbilityInitFinishNotify.Invokes = invokeHandler.entryListForwardHost
|
||||
g.SendMsg(proto.ApiClientAbilityInitFinishNotify, world.owner.PlayerID, world.owner.ClientSeq, clientAbilityInitFinishNotify)
|
||||
}
|
||||
}
|
||||
|
||||
type InvokeType interface {
|
||||
proto.AbilityInvokeEntry | proto.CombatInvokeEntry
|
||||
}
|
||||
|
||||
type InvokeHandler[T InvokeType] struct {
|
||||
entryListForwardAll []*T
|
||||
entryListForwardAllExceptCur []*T
|
||||
entryListForwardHost []*T
|
||||
}
|
||||
|
||||
func NewInvokeHandler[T InvokeType]() (r *InvokeHandler[T]) {
|
||||
r = new(InvokeHandler[T])
|
||||
r.InitInvokeHandler()
|
||||
return r
|
||||
}
|
||||
|
||||
func (i *InvokeHandler[T]) InitInvokeHandler() {
|
||||
i.entryListForwardAll = make([]*T, 0)
|
||||
i.entryListForwardAllExceptCur = make([]*T, 0)
|
||||
i.entryListForwardHost = make([]*T, 0)
|
||||
}
|
||||
|
||||
func (i *InvokeHandler[T]) addEntry(forward proto.ForwardType, entry *T) {
|
||||
switch forward {
|
||||
case proto.ForwardType_FORWARD_TYPE_TO_ALL:
|
||||
i.entryListForwardAll = append(i.entryListForwardAll, entry)
|
||||
case proto.ForwardType_FORWARD_TYPE_TO_ALL_EXCEPT_CUR:
|
||||
fallthrough
|
||||
case proto.ForwardType_FORWARD_TYPE_TO_ALL_EXIST_EXCEPT_CUR:
|
||||
i.entryListForwardAllExceptCur = append(i.entryListForwardAllExceptCur, entry)
|
||||
case proto.ForwardType_FORWARD_TYPE_TO_HOST:
|
||||
i.entryListForwardHost = append(i.entryListForwardHost, entry)
|
||||
default:
|
||||
if forward != proto.ForwardType_FORWARD_TYPE_ONLY_SERVER {
|
||||
logger.LOG.Error("forward: %v, entry: %v", forward, entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (i *InvokeHandler[T]) AllLen() int {
|
||||
return len(i.entryListForwardAll)
|
||||
}
|
||||
|
||||
func (i *InvokeHandler[T]) AllExceptCurLen() int {
|
||||
return len(i.entryListForwardAllExceptCur)
|
||||
}
|
||||
|
||||
func (i *InvokeHandler[T]) HostLen() int {
|
||||
return len(i.entryListForwardHost)
|
||||
}
|
||||
610
service/game-hk4e/game/user_gacha.go
Normal file
610
service/game-hk4e/game/user_gacha.go
Normal file
@@ -0,0 +1,610 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/common/utils/random"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/model"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserInfo struct {
|
||||
UserId uint32 `json:"userId"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
// 获取卡池信息
|
||||
func (g *GameManager) GetGachaInfoReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get gacha info, userId: %v", userId)
|
||||
serverAddr := config.CONF.Hk4e.GachaHistoryServer
|
||||
getGachaInfoRsp := new(proto.GetGachaInfoRsp)
|
||||
getGachaInfoRsp.GachaRandom = 12345
|
||||
userInfo := &UserInfo{
|
||||
UserId: userId,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour * time.Duration(1))),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
},
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS512, userInfo)
|
||||
jwtStr, err := token.SignedString([]byte("flswld"))
|
||||
if err != nil {
|
||||
logger.LOG.Error("generate jwt error: %v", err)
|
||||
jwtStr = "default.jwt.token"
|
||||
}
|
||||
getGachaInfoRsp.GachaInfoList = []*proto.GachaInfo{
|
||||
// 温迪
|
||||
{
|
||||
GachaType: 300,
|
||||
ScheduleId: 823,
|
||||
BeginTime: 0,
|
||||
EndTime: 2051193600,
|
||||
GachaSortId: 9998,
|
||||
GachaPrefabPath: "GachaShowPanel_A019",
|
||||
GachaPreviewPrefabPath: "UI_Tab_GachaShowPanel_A019",
|
||||
TitleTextmap: "UI_GACHA_SHOW_PANEL_A019_TITLE",
|
||||
LeftGachaTimes: 2147483647,
|
||||
GachaTimesLimit: 2147483647,
|
||||
CostItemId: 223,
|
||||
CostItemNum: 1,
|
||||
TenCostItemId: 223,
|
||||
TenCostItemNum: 10,
|
||||
GachaRecordUrl: serverAddr + "/gm/gacha?gachaType=300&jwt=" + jwtStr,
|
||||
GachaRecordUrlOversea: serverAddr + "/gm/gacha?gachaType=300&jwt=" + jwtStr,
|
||||
GachaProbUrl: serverAddr + "/gm/gacha/details?scheduleId=823&jwt=" + jwtStr,
|
||||
GachaProbUrlOversea: serverAddr + "/gm/gacha/details?scheduleId=823&jwt=" + jwtStr,
|
||||
GachaUpInfoList: []*proto.GachaUpInfo{
|
||||
{
|
||||
ItemParentType: 1,
|
||||
ItemIdList: []uint32{1022},
|
||||
},
|
||||
{
|
||||
ItemParentType: 2,
|
||||
ItemIdList: []uint32{1023, 1031, 1014},
|
||||
},
|
||||
},
|
||||
DisplayUp4ItemList: []uint32{1023},
|
||||
DisplayUp5ItemList: []uint32{1022},
|
||||
WishItemId: 0,
|
||||
WishProgress: 0,
|
||||
WishMaxProgress: 0,
|
||||
IsNewWish: false,
|
||||
},
|
||||
// 可莉
|
||||
{
|
||||
GachaType: 400,
|
||||
ScheduleId: 833,
|
||||
BeginTime: 0,
|
||||
EndTime: 2051193600,
|
||||
GachaSortId: 9998,
|
||||
GachaPrefabPath: "GachaShowPanel_A018",
|
||||
GachaPreviewPrefabPath: "UI_Tab_GachaShowPanel_A018",
|
||||
TitleTextmap: "UI_GACHA_SHOW_PANEL_A018_TITLE",
|
||||
LeftGachaTimes: 2147483647,
|
||||
GachaTimesLimit: 2147483647,
|
||||
CostItemId: 223,
|
||||
CostItemNum: 1,
|
||||
TenCostItemId: 223,
|
||||
TenCostItemNum: 10,
|
||||
GachaRecordUrl: serverAddr + "/gm/gacha?gachaType=400&jwt=" + jwtStr,
|
||||
GachaRecordUrlOversea: serverAddr + "/gm/gacha?gachaType=400&jwt=" + jwtStr,
|
||||
GachaProbUrl: serverAddr + "/gm/gacha/details?scheduleId=833&jwt=" + jwtStr,
|
||||
GachaProbUrlOversea: serverAddr + "/gm/gacha/details?scheduleId=833&jwt=" + jwtStr,
|
||||
GachaUpInfoList: []*proto.GachaUpInfo{
|
||||
{
|
||||
ItemParentType: 1,
|
||||
ItemIdList: []uint32{1029},
|
||||
},
|
||||
{
|
||||
ItemParentType: 2,
|
||||
ItemIdList: []uint32{1025, 1034, 1043},
|
||||
},
|
||||
},
|
||||
DisplayUp4ItemList: []uint32{1025},
|
||||
DisplayUp5ItemList: []uint32{1029},
|
||||
WishItemId: 0,
|
||||
WishProgress: 0,
|
||||
WishMaxProgress: 0,
|
||||
IsNewWish: false,
|
||||
},
|
||||
// 阿莫斯之弓&天空之傲
|
||||
{
|
||||
GachaType: 431,
|
||||
ScheduleId: 1143,
|
||||
BeginTime: 0,
|
||||
EndTime: 2051193600,
|
||||
GachaSortId: 9997,
|
||||
GachaPrefabPath: "GachaShowPanel_A030",
|
||||
GachaPreviewPrefabPath: "UI_Tab_GachaShowPanel_A030",
|
||||
TitleTextmap: "UI_GACHA_SHOW_PANEL_A030_TITLE",
|
||||
LeftGachaTimes: 2147483647,
|
||||
GachaTimesLimit: 2147483647,
|
||||
CostItemId: 223,
|
||||
CostItemNum: 1,
|
||||
TenCostItemId: 223,
|
||||
TenCostItemNum: 10,
|
||||
GachaRecordUrl: serverAddr + "/gm/gacha?gachaType=431&jwt=" + jwtStr,
|
||||
GachaRecordUrlOversea: serverAddr + "/gm/gacha?gachaType=431&jwt=" + jwtStr,
|
||||
GachaProbUrl: serverAddr + "/gm/gacha/details?scheduleId=1143&jwt=" + jwtStr,
|
||||
GachaProbUrlOversea: serverAddr + "/gm/gacha/details?scheduleId=1143&jwt=" + jwtStr,
|
||||
GachaUpInfoList: []*proto.GachaUpInfo{
|
||||
{
|
||||
ItemParentType: 1,
|
||||
ItemIdList: []uint32{15502, 12501},
|
||||
},
|
||||
{
|
||||
ItemParentType: 2,
|
||||
ItemIdList: []uint32{11403, 12402, 13401, 14409, 15401},
|
||||
},
|
||||
},
|
||||
DisplayUp4ItemList: []uint32{11403},
|
||||
DisplayUp5ItemList: []uint32{15502, 12501},
|
||||
WishItemId: 0,
|
||||
WishProgress: 0,
|
||||
WishMaxProgress: 0,
|
||||
IsNewWish: false,
|
||||
},
|
||||
// 常驻
|
||||
{
|
||||
GachaType: 201,
|
||||
ScheduleId: 813,
|
||||
BeginTime: 0,
|
||||
EndTime: 2051193600,
|
||||
GachaSortId: 1000,
|
||||
GachaPrefabPath: "GachaShowPanel_A017",
|
||||
GachaPreviewPrefabPath: "UI_Tab_GachaShowPanel_A017",
|
||||
TitleTextmap: "UI_GACHA_SHOW_PANEL_A017_TITLE",
|
||||
LeftGachaTimes: 2147483647,
|
||||
GachaTimesLimit: 2147483647,
|
||||
CostItemId: 224,
|
||||
CostItemNum: 1,
|
||||
TenCostItemId: 224,
|
||||
TenCostItemNum: 10,
|
||||
GachaRecordUrl: serverAddr + "/gm/gacha?gachaType=201&jwt=" + jwtStr,
|
||||
GachaRecordUrlOversea: serverAddr + "/gm/gacha?gachaType=201&jwt=" + jwtStr,
|
||||
GachaProbUrl: serverAddr + "/gm/gacha/details?scheduleId=813&jwt=" + jwtStr,
|
||||
GachaProbUrlOversea: serverAddr + "/gm/gacha/details?scheduleId=813&jwt=" + jwtStr,
|
||||
GachaUpInfoList: []*proto.GachaUpInfo{
|
||||
{
|
||||
ItemParentType: 1,
|
||||
ItemIdList: []uint32{1003, 1016},
|
||||
},
|
||||
{
|
||||
ItemParentType: 2,
|
||||
ItemIdList: []uint32{1021, 1006, 1015},
|
||||
},
|
||||
},
|
||||
DisplayUp4ItemList: []uint32{1021},
|
||||
DisplayUp5ItemList: []uint32{1003, 1016},
|
||||
WishItemId: 0,
|
||||
WishProgress: 0,
|
||||
WishMaxProgress: 0,
|
||||
IsNewWish: false,
|
||||
},
|
||||
}
|
||||
|
||||
g.SendMsg(proto.ApiGetGachaInfoRsp, userId, player.ClientSeq, getGachaInfoRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) DoGachaReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user do gacha, userId: %v", userId)
|
||||
req := payloadMsg.(*proto.DoGachaReq)
|
||||
gachaScheduleId := req.GachaScheduleId
|
||||
gachaTimes := req.GachaTimes
|
||||
|
||||
gachaType := uint32(0)
|
||||
costItemId := uint32(0)
|
||||
switch gachaScheduleId {
|
||||
case 823:
|
||||
// 温迪
|
||||
gachaType = 300
|
||||
costItemId = 223
|
||||
case 833:
|
||||
// 可莉
|
||||
gachaType = 400
|
||||
costItemId = 223
|
||||
case 1143:
|
||||
// 阿莫斯之弓&天空之傲
|
||||
gachaType = 431
|
||||
costItemId = 223
|
||||
case 813:
|
||||
// 常驻
|
||||
gachaType = 201
|
||||
costItemId = 224
|
||||
}
|
||||
|
||||
// PacketDoGachaRsp
|
||||
doGachaRsp := new(proto.DoGachaRsp)
|
||||
doGachaRsp.GachaType = gachaType
|
||||
doGachaRsp.GachaScheduleId = gachaScheduleId
|
||||
doGachaRsp.GachaTimes = gachaTimes
|
||||
doGachaRsp.NewGachaRandom = 12345
|
||||
doGachaRsp.LeftGachaTimes = 2147483647
|
||||
doGachaRsp.GachaTimesLimit = 2147483647
|
||||
doGachaRsp.CostItemId = costItemId
|
||||
doGachaRsp.CostItemNum = 1
|
||||
doGachaRsp.TenCostItemId = costItemId
|
||||
doGachaRsp.TenCostItemNum = 10
|
||||
|
||||
// 先扣掉粉球或蓝球再进行抽卡
|
||||
g.CostUserItem(player.PlayerID, []*UserItem{
|
||||
{
|
||||
ItemId: costItemId,
|
||||
ChangeCount: gachaTimes,
|
||||
},
|
||||
})
|
||||
|
||||
doGachaRsp.GachaItemList = make([]*proto.GachaItem, 0)
|
||||
for i := uint32(0); i < gachaTimes; i++ {
|
||||
var ok bool
|
||||
var itemId uint32
|
||||
if gachaType == 400 {
|
||||
// 可莉
|
||||
ok, itemId = g.doGachaKlee()
|
||||
} else if gachaType == 300 {
|
||||
// 角色UP池
|
||||
ok, itemId = g.doGachaOnce(userId, gachaType, true, false)
|
||||
} else if gachaType == 431 {
|
||||
// 武器UP池
|
||||
ok, itemId = g.doGachaOnce(userId, gachaType, true, true)
|
||||
} else if gachaType == 201 {
|
||||
// 常驻
|
||||
ok, itemId = g.doGachaOnce(userId, gachaType, false, false)
|
||||
} else {
|
||||
ok, itemId = false, 0
|
||||
}
|
||||
if !ok {
|
||||
itemId = 11301
|
||||
}
|
||||
|
||||
// 添加抽卡获得的道具
|
||||
if itemId > 1000 && itemId < 2000 {
|
||||
avatarId := (itemId % 1000) + 10000000
|
||||
_, exist := player.AvatarMap[avatarId]
|
||||
if !exist {
|
||||
g.AddUserAvatar(player.PlayerID, avatarId)
|
||||
} else {
|
||||
constellationItemId := itemId + 100
|
||||
if player.GetItemCount(constellationItemId) < 6 {
|
||||
g.AddUserItem(player.PlayerID, []*UserItem{{ItemId: constellationItemId, ChangeCount: 1}}, false, 0)
|
||||
}
|
||||
}
|
||||
} else if itemId > 10000 && itemId < 20000 {
|
||||
g.AddUserWeapon(player.PlayerID, itemId)
|
||||
} else {
|
||||
g.AddUserItem(player.PlayerID, []*UserItem{{ItemId: itemId, ChangeCount: 1}}, false, 0)
|
||||
}
|
||||
|
||||
// 计算星尘星辉
|
||||
xc := uint32(random.GetRandomInt32(0, 10))
|
||||
xh := uint32(random.GetRandomInt32(0, 10))
|
||||
|
||||
gachaItem := new(proto.GachaItem)
|
||||
gachaItem.GachaItem_ = &proto.ItemParam{
|
||||
ItemId: itemId,
|
||||
Count: 1,
|
||||
}
|
||||
// 星尘
|
||||
if xc != 0 {
|
||||
g.AddUserItem(player.PlayerID, []*UserItem{{
|
||||
ItemId: 222,
|
||||
ChangeCount: xc,
|
||||
}}, false, 0)
|
||||
gachaItem.TokenItemList = []*proto.ItemParam{{
|
||||
ItemId: 222,
|
||||
Count: xc,
|
||||
}}
|
||||
}
|
||||
// 星辉
|
||||
if xh != 0 {
|
||||
g.AddUserItem(player.PlayerID, []*UserItem{{
|
||||
ItemId: 221,
|
||||
ChangeCount: xh,
|
||||
}}, false, 0)
|
||||
gachaItem.TransferItems = []*proto.GachaTransferItem{{
|
||||
Item: &proto.ItemParam{
|
||||
ItemId: 221,
|
||||
Count: xh,
|
||||
},
|
||||
}}
|
||||
}
|
||||
doGachaRsp.GachaItemList = append(doGachaRsp.GachaItemList, gachaItem)
|
||||
}
|
||||
|
||||
//logger.LOG.Debug("doGachaRsp: %v", doGachaRsp.String())
|
||||
g.SendMsg(proto.ApiDoGachaRsp, userId, player.ClientSeq, doGachaRsp)
|
||||
}
|
||||
|
||||
// 扣1给可莉刷烧烤酱
|
||||
func (g *GameManager) doGachaKlee() (bool, uint32) {
|
||||
allAvatarList := make([]uint32, 0)
|
||||
allAvatarDataConfig := g.GetAllAvatarDataConfig()
|
||||
for k, v := range allAvatarDataConfig {
|
||||
if v.QualityType == "QUALITY_ORANGE" || v.QualityType == "QUALITY_PURPLE" {
|
||||
allAvatarList = append(allAvatarList, uint32(k))
|
||||
}
|
||||
}
|
||||
allWeaponList := make([]uint32, 0)
|
||||
allWeaponDataConfig := g.GetAllWeaponDataConfig()
|
||||
for k, v := range allWeaponDataConfig {
|
||||
if v.RankLevel == 5 {
|
||||
allWeaponList = append(allWeaponList, uint32(k))
|
||||
}
|
||||
}
|
||||
allGoodList := make([]uint32, 0)
|
||||
// 全部角色
|
||||
allGoodList = append(allGoodList, allAvatarList...)
|
||||
// 全部5星武器
|
||||
allGoodList = append(allGoodList, allWeaponList...)
|
||||
// 原石 摩拉 粉球 蓝球
|
||||
allGoodList = append(allGoodList, 201, 202, 223, 224)
|
||||
// 苟利国家生死以
|
||||
allGoodList = append(allGoodList, 100081)
|
||||
rn := random.GetRandomInt32(0, int32(len(allGoodList)-1))
|
||||
itemId := allGoodList[rn]
|
||||
if itemId > 10000000 {
|
||||
itemId %= 1000
|
||||
itemId += 1000
|
||||
}
|
||||
return true, itemId
|
||||
}
|
||||
|
||||
const (
|
||||
Orange = iota
|
||||
Purple
|
||||
Blue
|
||||
Avatar
|
||||
Weapon
|
||||
)
|
||||
|
||||
const (
|
||||
StandardOrangeTimesFixThreshold uint32 = 74 // 标准池触发5星概率修正阈值的抽卡次数
|
||||
StandardOrangeTimesFixValue int32 = 600 // 标准池5星概率修正因子
|
||||
StandardPurpleTimesFixThreshold uint32 = 9 // 标准池触发4星概率修正阈值的抽卡次数
|
||||
StandardPurpleTimesFixValue int32 = 5100 // 标准池4星概率修正因子
|
||||
WeaponOrangeTimesFixThreshold uint32 = 63 // 武器池触发5星概率修正阈值的抽卡次数
|
||||
WeaponOrangeTimesFixValue int32 = 700 // 武器池5星概率修正因子
|
||||
WeaponPurpleTimesFixThreshold uint32 = 8 // 武器池触发4星概率修正阈值的抽卡次数
|
||||
WeaponPurpleTimesFixValue int32 = 6000 // 武器池4星概率修正因子
|
||||
)
|
||||
|
||||
// 单抽一次
|
||||
func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnable bool, weaponFix bool) (bool, uint32) {
|
||||
player := g.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return false, 0
|
||||
}
|
||||
|
||||
// 找到卡池对应的掉落组
|
||||
dropGroupDataConfig := gdc.CONF.DropGroupDataMap[int32(gachaType)]
|
||||
if dropGroupDataConfig == nil {
|
||||
logger.LOG.Error("drop group not found, drop id: %v", gachaType)
|
||||
return false, 0
|
||||
}
|
||||
|
||||
// 获取用户的卡池保底信息
|
||||
gachaPoolInfo := player.DropInfo.GachaPoolInfo[gachaType]
|
||||
if gachaPoolInfo == nil {
|
||||
logger.LOG.Error("user gacha pool info not found, gacha type: %v", gachaType)
|
||||
return false, 0
|
||||
}
|
||||
|
||||
// 保底计数+1
|
||||
gachaPoolInfo.OrangeTimes++
|
||||
gachaPoolInfo.PurpleTimes++
|
||||
|
||||
// 4星和5星概率修正
|
||||
OrangeTimesFixThreshold := uint32(0)
|
||||
OrangeTimesFixValue := int32(0)
|
||||
PurpleTimesFixThreshold := uint32(0)
|
||||
PurpleTimesFixValue := int32(0)
|
||||
if !weaponFix {
|
||||
OrangeTimesFixThreshold = StandardOrangeTimesFixThreshold
|
||||
OrangeTimesFixValue = StandardOrangeTimesFixValue
|
||||
PurpleTimesFixThreshold = StandardPurpleTimesFixThreshold
|
||||
PurpleTimesFixValue = StandardPurpleTimesFixValue
|
||||
} else {
|
||||
OrangeTimesFixThreshold = WeaponOrangeTimesFixThreshold
|
||||
OrangeTimesFixValue = WeaponOrangeTimesFixValue
|
||||
PurpleTimesFixThreshold = WeaponPurpleTimesFixThreshold
|
||||
PurpleTimesFixValue = WeaponPurpleTimesFixValue
|
||||
}
|
||||
if gachaPoolInfo.OrangeTimes >= OrangeTimesFixThreshold || gachaPoolInfo.PurpleTimes >= PurpleTimesFixThreshold {
|
||||
fixDropGroupDataConfig := new(gdc.DropGroupData)
|
||||
fixDropGroupDataConfig.DropId = dropGroupDataConfig.DropId
|
||||
fixDropGroupDataConfig.WeightAll = dropGroupDataConfig.WeightAll
|
||||
// 计算4星和5星权重修正值
|
||||
addOrangeWeight := int32(gachaPoolInfo.OrangeTimes-OrangeTimesFixThreshold+1) * OrangeTimesFixValue
|
||||
if addOrangeWeight < 0 {
|
||||
addOrangeWeight = 0
|
||||
}
|
||||
addPurpleWeight := int32(gachaPoolInfo.PurpleTimes-PurpleTimesFixThreshold+1) * PurpleTimesFixValue
|
||||
if addPurpleWeight < 0 {
|
||||
addPurpleWeight = 0
|
||||
}
|
||||
for _, drop := range dropGroupDataConfig.DropConfig {
|
||||
fixDrop := new(gdc.Drop)
|
||||
fixDrop.Result = drop.Result
|
||||
fixDrop.DropId = drop.DropId
|
||||
fixDrop.IsEnd = drop.IsEnd
|
||||
// 找到5/4/3星掉落组id 要求配置表的5/4/3星掉落组id规则固定为(卡池类型*10+1/2/3)
|
||||
orangeDropId := int32(gachaType*10 + 1)
|
||||
purpleDropId := int32(gachaType*10 + 2)
|
||||
blueDropId := int32(gachaType*10 + 3)
|
||||
// 权重修正
|
||||
if drop.Result == orangeDropId {
|
||||
fixDrop.Weight = drop.Weight + addOrangeWeight
|
||||
} else if drop.Result == purpleDropId {
|
||||
fixDrop.Weight = drop.Weight + addPurpleWeight
|
||||
} else if drop.Result == blueDropId {
|
||||
fixDrop.Weight = drop.Weight - addOrangeWeight - addPurpleWeight
|
||||
} else {
|
||||
logger.LOG.Error("invalid drop group id, does not match any case of orange/purple/blue, result group id: %v", drop.Result)
|
||||
fixDrop.Weight = drop.Weight
|
||||
}
|
||||
fixDropGroupDataConfig.DropConfig = append(fixDropGroupDataConfig.DropConfig, fixDrop)
|
||||
}
|
||||
dropGroupDataConfig = fixDropGroupDataConfig
|
||||
}
|
||||
|
||||
// 掉落
|
||||
ok, drop := g.doFullRandDrop(dropGroupDataConfig)
|
||||
if !ok {
|
||||
return false, 0
|
||||
}
|
||||
// 分析本次掉落结果的星级和类型
|
||||
itemColor := 0
|
||||
itemType := 0
|
||||
_ = itemType
|
||||
gachaItemId := uint32(drop.Result)
|
||||
if gachaItemId < 2000 {
|
||||
// 抽到角色
|
||||
itemType = Avatar
|
||||
avatarId := (gachaItemId % 1000) + 10000000
|
||||
allAvatarDataConfig := g.GetAllAvatarDataConfig()
|
||||
avatarDataConfig := allAvatarDataConfig[int32(avatarId)]
|
||||
if avatarDataConfig == nil {
|
||||
logger.LOG.Error("avatar data config not found, avatar id: %v", avatarId)
|
||||
return false, 0
|
||||
}
|
||||
if avatarDataConfig.QualityType == "QUALITY_ORANGE" {
|
||||
itemColor = Orange
|
||||
logger.LOG.Debug("[orange avatar], times: %v, gachaItemId: %v", gachaPoolInfo.OrangeTimes, gachaItemId)
|
||||
if gachaPoolInfo.OrangeTimes > 90 {
|
||||
logger.LOG.Error("[abnormal orange avatar], times: %v, gachaItemId: %v", gachaPoolInfo.OrangeTimes, gachaItemId)
|
||||
}
|
||||
} else if avatarDataConfig.QualityType == "QUALITY_PURPLE" {
|
||||
itemColor = Purple
|
||||
logger.LOG.Debug("[purple avatar], times: %v, gachaItemId: %v", gachaPoolInfo.PurpleTimes, gachaItemId)
|
||||
if gachaPoolInfo.PurpleTimes > 10 {
|
||||
logger.LOG.Error("[abnormal purple avatar], times: %v, gachaItemId: %v", gachaPoolInfo.PurpleTimes, gachaItemId)
|
||||
}
|
||||
} else {
|
||||
itemColor = Blue
|
||||
}
|
||||
} else {
|
||||
// 抽到武器
|
||||
itemType = Weapon
|
||||
allWeaponDataConfig := g.GetAllWeaponDataConfig()
|
||||
weaponDataConfig := allWeaponDataConfig[int32(gachaItemId)]
|
||||
if weaponDataConfig == nil {
|
||||
logger.LOG.Error("weapon item data config not found, item id: %v", gachaItemId)
|
||||
return false, 0
|
||||
}
|
||||
if weaponDataConfig.RankLevel == 5 {
|
||||
itemColor = Orange
|
||||
logger.LOG.Debug("[orange weapon], times: %v, gachaItemId: %v", gachaPoolInfo.OrangeTimes, gachaItemId)
|
||||
if gachaPoolInfo.OrangeTimes > 90 {
|
||||
logger.LOG.Error("[abnormal orange weapon], times: %v, gachaItemId: %v", gachaPoolInfo.OrangeTimes, gachaItemId)
|
||||
}
|
||||
} else if weaponDataConfig.RankLevel == 4 {
|
||||
itemColor = Purple
|
||||
logger.LOG.Debug("[purple weapon], times: %v, gachaItemId: %v", gachaPoolInfo.PurpleTimes, gachaItemId)
|
||||
if gachaPoolInfo.PurpleTimes > 10 {
|
||||
logger.LOG.Error("[abnormal purple weapon], times: %v, gachaItemId: %v", gachaPoolInfo.PurpleTimes, gachaItemId)
|
||||
}
|
||||
} else {
|
||||
itemColor = Blue
|
||||
}
|
||||
}
|
||||
// 后处理
|
||||
switch itemColor {
|
||||
case Orange:
|
||||
// 重置5星保底计数
|
||||
gachaPoolInfo.OrangeTimes = 0
|
||||
if mustGetUpEnable {
|
||||
// 找到UP的5星对应的掉落组id 要求配置表的UP的5星掉落组id规则固定为(卡池类型*100+12)
|
||||
upOrangeDropId := int32(gachaType*100 + 12)
|
||||
// 替换本次结果为5星大保底
|
||||
if gachaPoolInfo.MustGetUpOrange {
|
||||
logger.LOG.Debug("trigger must get up orange, user id: %v", userId)
|
||||
upOrangeDropGroupDataConfig := gdc.CONF.DropGroupDataMap[upOrangeDropId]
|
||||
if upOrangeDropGroupDataConfig == nil {
|
||||
logger.LOG.Error("drop group not found, drop id: %v", upOrangeDropId)
|
||||
return false, 0
|
||||
}
|
||||
upOrangeOk, upOrangeDrop := g.doFullRandDrop(upOrangeDropGroupDataConfig)
|
||||
if !upOrangeOk {
|
||||
return false, 0
|
||||
}
|
||||
gachaPoolInfo.MustGetUpOrange = false
|
||||
upOrangeGachaItemId := uint32(upOrangeDrop.Result)
|
||||
return upOrangeOk, upOrangeGachaItemId
|
||||
}
|
||||
// 触发5星大保底
|
||||
if drop.DropId != upOrangeDropId {
|
||||
gachaPoolInfo.MustGetUpOrange = true
|
||||
}
|
||||
}
|
||||
case Purple:
|
||||
// 重置4星保底计数
|
||||
gachaPoolInfo.PurpleTimes = 0
|
||||
if mustGetUpEnable {
|
||||
// 找到UP的4星对应的掉落组id 要求配置表的UP的4星掉落组id规则固定为(卡池类型*100+22)
|
||||
upPurpleDropId := int32(gachaType*100 + 22)
|
||||
// 替换本次结果为4星大保底
|
||||
if gachaPoolInfo.MustGetUpPurple {
|
||||
logger.LOG.Debug("trigger must get up purple, user id: %v", userId)
|
||||
upPurpleDropGroupDataConfig := gdc.CONF.DropGroupDataMap[upPurpleDropId]
|
||||
if upPurpleDropGroupDataConfig == nil {
|
||||
logger.LOG.Error("drop group not found, drop id: %v", upPurpleDropId)
|
||||
return false, 0
|
||||
}
|
||||
upPurpleOk, upPurpleDrop := g.doFullRandDrop(upPurpleDropGroupDataConfig)
|
||||
if !upPurpleOk {
|
||||
return false, 0
|
||||
}
|
||||
gachaPoolInfo.MustGetUpPurple = false
|
||||
upPurpleGachaItemId := uint32(upPurpleDrop.Result)
|
||||
return upPurpleOk, upPurpleGachaItemId
|
||||
}
|
||||
// 触发4星大保底
|
||||
if drop.DropId != upPurpleDropId {
|
||||
gachaPoolInfo.MustGetUpPurple = true
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
return ok, gachaItemId
|
||||
}
|
||||
|
||||
// 走一次完整流程的掉落组
|
||||
func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdc.DropGroupData) (bool, *gdc.Drop) {
|
||||
for {
|
||||
drop := g.doRandDropOnce(dropGroupDataConfig)
|
||||
if drop == nil {
|
||||
logger.LOG.Error("weight error, drop group config: %v", dropGroupDataConfig)
|
||||
return false, nil
|
||||
}
|
||||
if drop.IsEnd {
|
||||
// 成功抽到物品
|
||||
return true, drop
|
||||
}
|
||||
// 进行下一步掉落流程
|
||||
dropGroupDataConfig = gdc.CONF.DropGroupDataMap[drop.Result]
|
||||
if dropGroupDataConfig == nil {
|
||||
logger.LOG.Error("drop config tab exist error, invalid drop id: %v", drop.Result)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 进行单次随机掉落
|
||||
func (g *GameManager) doRandDropOnce(dropGroupDataConfig *gdc.DropGroupData) *gdc.Drop {
|
||||
randNum := random.GetRandomInt32(0, dropGroupDataConfig.WeightAll-1)
|
||||
sumWeight := int32(0)
|
||||
// 轮盘选择法
|
||||
for _, drop := range dropGroupDataConfig.DropConfig {
|
||||
sumWeight += drop.Weight
|
||||
if sumWeight > randNum {
|
||||
return drop
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
181
service/game-hk4e/game/user_item.go
Normal file
181
service/game-hk4e/game/user_item.go
Normal file
@@ -0,0 +1,181 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
)
|
||||
|
||||
type UserItem struct {
|
||||
ItemId uint32
|
||||
ChangeCount uint32
|
||||
}
|
||||
|
||||
func (g *GameManager) GetAllItemDataConfig() map[int32]*gdc.ItemData {
|
||||
allItemDataConfig := make(map[int32]*gdc.ItemData)
|
||||
for itemId, itemData := range gdc.CONF.ItemDataMap {
|
||||
if itemData.ItemEnumType == constant.ItemTypeConst.ITEM_WEAPON {
|
||||
// 排除武器
|
||||
continue
|
||||
}
|
||||
if itemData.ItemEnumType == constant.ItemTypeConst.ITEM_RELIQUARY {
|
||||
// 排除圣遗物
|
||||
continue
|
||||
}
|
||||
if itemId == 100086 ||
|
||||
itemId == 100087 ||
|
||||
(itemId >= 100100 && itemId <= 101000) ||
|
||||
(itemId >= 101106 && itemId <= 101110) ||
|
||||
itemId == 101306 ||
|
||||
(itemId >= 101500 && itemId <= 104000) ||
|
||||
itemId == 105001 ||
|
||||
itemId == 105004 ||
|
||||
(itemId >= 106000 && itemId <= 107000) ||
|
||||
itemId == 107011 ||
|
||||
itemId == 108000 ||
|
||||
(itemId >= 109000 && itemId <= 110000) ||
|
||||
(itemId >= 115000 && itemId <= 130000) ||
|
||||
(itemId >= 200200 && itemId <= 200899) ||
|
||||
itemId == 220050 ||
|
||||
itemId == 220054 {
|
||||
// 排除无效道具
|
||||
continue
|
||||
}
|
||||
allItemDataConfig[itemId] = itemData
|
||||
}
|
||||
return allItemDataConfig
|
||||
}
|
||||
|
||||
func (g *GameManager) AddUserItem(userId uint32, itemList []*UserItem, isHint bool, hintReason uint16) {
|
||||
player := g.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
for _, userItem := range itemList {
|
||||
player.AddItem(userItem.ItemId, userItem.ChangeCount)
|
||||
}
|
||||
|
||||
// PacketStoreItemChangeNotify
|
||||
storeItemChangeNotify := new(proto.StoreItemChangeNotify)
|
||||
storeItemChangeNotify.StoreType = proto.StoreType_STORE_TYPE_PACK
|
||||
for _, userItem := range itemList {
|
||||
pbItem := &proto.Item{
|
||||
ItemId: userItem.ItemId,
|
||||
Guid: player.GetItemGuid(userItem.ItemId),
|
||||
Detail: &proto.Item_Material{
|
||||
Material: &proto.Material{
|
||||
Count: player.GetItemCount(userItem.ItemId),
|
||||
},
|
||||
},
|
||||
}
|
||||
storeItemChangeNotify.ItemList = append(storeItemChangeNotify.ItemList, pbItem)
|
||||
}
|
||||
g.SendMsg(proto.ApiStoreItemChangeNotify, userId, player.ClientSeq, storeItemChangeNotify)
|
||||
|
||||
if isHint {
|
||||
if hintReason == 0 {
|
||||
hintReason = constant.ActionReasonConst.SubfieldDrop
|
||||
}
|
||||
// PacketItemAddHintNotify
|
||||
itemAddHintNotify := new(proto.ItemAddHintNotify)
|
||||
itemAddHintNotify.Reason = uint32(hintReason)
|
||||
for _, userItem := range itemList {
|
||||
itemAddHintNotify.ItemList = append(itemAddHintNotify.ItemList, &proto.ItemHint{
|
||||
ItemId: userItem.ItemId,
|
||||
Count: userItem.ChangeCount,
|
||||
IsNew: false,
|
||||
})
|
||||
}
|
||||
g.SendMsg(proto.ApiItemAddHintNotify, userId, player.ClientSeq, itemAddHintNotify)
|
||||
}
|
||||
|
||||
// PacketPlayerPropNotify
|
||||
playerPropNotify := new(proto.PlayerPropNotify)
|
||||
playerPropNotify.PropMap = make(map[uint32]*proto.PropValue)
|
||||
for _, userItem := range itemList {
|
||||
isVirtualItem, prop := player.GetVirtualItemProp(userItem.ItemId)
|
||||
if !isVirtualItem {
|
||||
continue
|
||||
}
|
||||
playerPropNotify.PropMap[uint32(prop)] = &proto.PropValue{
|
||||
Type: uint32(prop),
|
||||
Val: int64(player.PropertiesMap[prop]),
|
||||
Value: &proto.PropValue_Ival{
|
||||
Ival: int64(player.PropertiesMap[prop]),
|
||||
},
|
||||
}
|
||||
}
|
||||
if len(playerPropNotify.PropMap) > 0 {
|
||||
g.SendMsg(proto.ApiPlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) CostUserItem(userId uint32, itemList []*UserItem) {
|
||||
player := g.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
for _, userItem := range itemList {
|
||||
player.CostItem(userItem.ItemId, userItem.ChangeCount)
|
||||
}
|
||||
|
||||
// PacketStoreItemChangeNotify
|
||||
storeItemChangeNotify := new(proto.StoreItemChangeNotify)
|
||||
storeItemChangeNotify.StoreType = proto.StoreType_STORE_TYPE_PACK
|
||||
for _, userItem := range itemList {
|
||||
count := player.GetItemCount(userItem.ItemId)
|
||||
if count == 0 {
|
||||
continue
|
||||
}
|
||||
pbItem := &proto.Item{
|
||||
ItemId: userItem.ItemId,
|
||||
Guid: player.GetItemGuid(userItem.ItemId),
|
||||
Detail: &proto.Item_Material{
|
||||
Material: &proto.Material{
|
||||
Count: count,
|
||||
},
|
||||
},
|
||||
}
|
||||
storeItemChangeNotify.ItemList = append(storeItemChangeNotify.ItemList, pbItem)
|
||||
}
|
||||
if len(storeItemChangeNotify.ItemList) > 0 {
|
||||
g.SendMsg(proto.ApiStoreItemChangeNotify, userId, player.ClientSeq, storeItemChangeNotify)
|
||||
}
|
||||
|
||||
// PacketStoreItemDelNotify
|
||||
storeItemDelNotify := new(proto.StoreItemDelNotify)
|
||||
storeItemDelNotify.StoreType = proto.StoreType_STORE_TYPE_PACK
|
||||
for _, userItem := range itemList {
|
||||
count := player.GetItemCount(userItem.ItemId)
|
||||
if count > 0 {
|
||||
continue
|
||||
}
|
||||
storeItemDelNotify.GuidList = append(storeItemDelNotify.GuidList, player.GetItemGuid(userItem.ItemId))
|
||||
}
|
||||
if len(storeItemDelNotify.GuidList) > 0 {
|
||||
g.SendMsg(proto.ApiStoreItemDelNotify, userId, player.ClientSeq, storeItemDelNotify)
|
||||
}
|
||||
|
||||
// PacketPlayerPropNotify
|
||||
playerPropNotify := new(proto.PlayerPropNotify)
|
||||
playerPropNotify.PropMap = make(map[uint32]*proto.PropValue)
|
||||
for _, userItem := range itemList {
|
||||
isVirtualItem, prop := player.GetVirtualItemProp(userItem.ItemId)
|
||||
if !isVirtualItem {
|
||||
continue
|
||||
}
|
||||
playerPropNotify.PropMap[uint32(prop)] = &proto.PropValue{
|
||||
Type: uint32(prop),
|
||||
Val: int64(player.PropertiesMap[prop]),
|
||||
Value: &proto.PropValue_Ival{
|
||||
Ival: int64(player.PropertiesMap[prop]),
|
||||
},
|
||||
}
|
||||
}
|
||||
if len(playerPropNotify.PropMap) > 0 {
|
||||
g.SendMsg(proto.ApiPlayerPropNotify, userId, player.ClientSeq, playerPropNotify)
|
||||
}
|
||||
}
|
||||
375
service/game-hk4e/game/user_login.go
Normal file
375
service/game-hk4e/game/user_login.go
Normal file
@@ -0,0 +1,375 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/common/utils/reflection"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (g *GameManager) OnLogin(userId uint32, clientSeq uint32) {
|
||||
logger.LOG.Info("user login, user id: %v", userId)
|
||||
player, asyncWait := g.userManager.OnlineUser(userId, clientSeq)
|
||||
if !asyncWait {
|
||||
g.OnLoginOk(userId, player, clientSeq)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq uint32) {
|
||||
if player == nil {
|
||||
g.SendMsg(proto.ApiDoSetPlayerBornDataNotify, userId, clientSeq, new(proto.DoSetPlayerBornDataNotify))
|
||||
return
|
||||
}
|
||||
player.OnlineTime = uint32(time.Now().UnixMilli())
|
||||
player.Online = true
|
||||
|
||||
// TODO 3.0.0REL版本 目前存在当前队伍活跃角色非主角时 登录进不去场景的情况 所以暂时先把四号队伍作为仅存在主角的保留队伍
|
||||
team := player.TeamConfig.GetTeamByIndex(3)
|
||||
team.AvatarIdList = []uint32{player.MainCharAvatarId, 0, 0, 0}
|
||||
player.TeamConfig.CurrTeamIndex = 3
|
||||
player.TeamConfig.CurrAvatarIndex = 0
|
||||
|
||||
// 初始化
|
||||
player.InitAll()
|
||||
player.TeamConfig.UpdateTeam()
|
||||
// 创建世界
|
||||
world := g.worldManager.CreateWorld(player, false)
|
||||
world.AddPlayer(player, player.SceneId)
|
||||
player.WorldId = world.id
|
||||
|
||||
// TODO 薄荷标记
|
||||
if world.IsBigWorld() {
|
||||
bigWorld := world.GetSceneById(3)
|
||||
for pos := range g.worldManager.worldStatic.terrain {
|
||||
bigWorld.CreateEntityGadget(&model.Vector{
|
||||
X: float64(pos.X),
|
||||
Y: float64(pos.Y),
|
||||
Z: float64(pos.Z),
|
||||
}, 3003009)
|
||||
}
|
||||
}
|
||||
|
||||
// PacketPlayerDataNotify
|
||||
playerDataNotify := new(proto.PlayerDataNotify)
|
||||
playerDataNotify.NickName = player.NickName
|
||||
playerDataNotify.ServerTime = uint64(time.Now().UnixMilli())
|
||||
playerDataNotify.IsFirstLoginToday = true
|
||||
playerDataNotify.RegionId = player.RegionId
|
||||
playerDataNotify.PropMap = make(map[uint32]*proto.PropValue)
|
||||
for k, v := range player.PropertiesMap {
|
||||
propValue := new(proto.PropValue)
|
||||
propValue.Type = uint32(k)
|
||||
propValue.Value = &proto.PropValue_Ival{Ival: int64(v)}
|
||||
propValue.Val = int64(v)
|
||||
playerDataNotify.PropMap[uint32(k)] = propValue
|
||||
}
|
||||
g.SendMsg(proto.ApiPlayerDataNotify, userId, clientSeq, playerDataNotify)
|
||||
|
||||
// PacketStoreWeightLimitNotify
|
||||
storeWeightLimitNotify := new(proto.StoreWeightLimitNotify)
|
||||
storeWeightLimitNotify.StoreType = proto.StoreType_STORE_TYPE_PACK
|
||||
// TODO 原神背包容量限制 写到配置文件
|
||||
storeWeightLimitNotify.WeightLimit = 30000
|
||||
storeWeightLimitNotify.WeaponCountLimit = 2000
|
||||
storeWeightLimitNotify.ReliquaryCountLimit = 1500
|
||||
storeWeightLimitNotify.MaterialCountLimit = 2000
|
||||
storeWeightLimitNotify.FurnitureCountLimit = 2000
|
||||
g.SendMsg(proto.ApiStoreWeightLimitNotify, userId, clientSeq, storeWeightLimitNotify)
|
||||
|
||||
// PacketPlayerStoreNotify
|
||||
playerStoreNotify := new(proto.PlayerStoreNotify)
|
||||
playerStoreNotify.StoreType = proto.StoreType_STORE_TYPE_PACK
|
||||
playerStoreNotify.WeightLimit = 30000
|
||||
itemDataMapConfig := gdc.CONF.ItemDataMap
|
||||
for _, weapon := range player.WeaponMap {
|
||||
pbItem := &proto.Item{
|
||||
ItemId: weapon.ItemId,
|
||||
Guid: weapon.Guid,
|
||||
Detail: nil,
|
||||
}
|
||||
if itemDataMapConfig[int32(weapon.ItemId)].ItemEnumType != constant.ItemTypeConst.ITEM_WEAPON {
|
||||
continue
|
||||
}
|
||||
affixMap := make(map[uint32]uint32)
|
||||
for _, affixId := range weapon.AffixIdList {
|
||||
affixMap[affixId] = uint32(weapon.Refinement)
|
||||
}
|
||||
pbItem.Detail = &proto.Item_Equip{
|
||||
Equip: &proto.Equip{
|
||||
Detail: &proto.Equip_Weapon{
|
||||
Weapon: &proto.Weapon{
|
||||
Level: uint32(weapon.Level),
|
||||
Exp: weapon.Exp,
|
||||
PromoteLevel: uint32(weapon.Promote),
|
||||
AffixMap: affixMap,
|
||||
},
|
||||
},
|
||||
IsLocked: weapon.Lock,
|
||||
},
|
||||
}
|
||||
playerStoreNotify.ItemList = append(playerStoreNotify.ItemList, pbItem)
|
||||
}
|
||||
for _, reliquary := range player.ReliquaryMap {
|
||||
pbItem := &proto.Item{
|
||||
ItemId: reliquary.ItemId,
|
||||
Guid: reliquary.Guid,
|
||||
Detail: nil,
|
||||
}
|
||||
if itemDataMapConfig[int32(reliquary.ItemId)].ItemEnumType != constant.ItemTypeConst.ITEM_RELIQUARY {
|
||||
continue
|
||||
}
|
||||
pbItem.Detail = &proto.Item_Equip{
|
||||
Equip: &proto.Equip{
|
||||
Detail: &proto.Equip_Reliquary{
|
||||
Reliquary: &proto.Reliquary{
|
||||
Level: uint32(reliquary.Level),
|
||||
Exp: reliquary.Exp,
|
||||
PromoteLevel: uint32(reliquary.Promote),
|
||||
MainPropId: reliquary.MainPropId,
|
||||
// TODO 圣遗物副词条
|
||||
AppendPropIdList: nil,
|
||||
},
|
||||
},
|
||||
IsLocked: reliquary.Lock,
|
||||
},
|
||||
}
|
||||
playerStoreNotify.ItemList = append(playerStoreNotify.ItemList, pbItem)
|
||||
}
|
||||
for _, item := range player.ItemMap {
|
||||
pbItem := &proto.Item{
|
||||
ItemId: item.ItemId,
|
||||
Guid: item.Guid,
|
||||
Detail: nil,
|
||||
}
|
||||
itemDataConfig := itemDataMapConfig[int32(item.ItemId)]
|
||||
if itemDataConfig != nil && itemDataConfig.ItemEnumType == constant.ItemTypeConst.ITEM_FURNITURE {
|
||||
pbItem.Detail = &proto.Item_Furniture{
|
||||
Furniture: &proto.Furniture{
|
||||
Count: item.Count,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
pbItem.Detail = &proto.Item_Material{
|
||||
Material: &proto.Material{
|
||||
Count: item.Count,
|
||||
DeleteInfo: nil,
|
||||
},
|
||||
}
|
||||
}
|
||||
playerStoreNotify.ItemList = append(playerStoreNotify.ItemList, pbItem)
|
||||
}
|
||||
g.SendMsg(proto.ApiPlayerStoreNotify, userId, clientSeq, playerStoreNotify)
|
||||
|
||||
// PacketAvatarDataNotify
|
||||
avatarDataNotify := new(proto.AvatarDataNotify)
|
||||
chooseAvatarId := player.TeamConfig.GetActiveAvatarId()
|
||||
avatarDataNotify.CurAvatarTeamId = uint32(player.TeamConfig.GetActiveTeamId())
|
||||
avatarDataNotify.ChooseAvatarGuid = player.AvatarMap[chooseAvatarId].Guid
|
||||
avatarDataNotify.OwnedFlycloakList = player.FlyCloakList
|
||||
// 角色衣装
|
||||
avatarDataNotify.OwnedCostumeList = player.CostumeList
|
||||
for _, avatar := range player.AvatarMap {
|
||||
pbAvatar := g.PacketAvatarInfo(avatar)
|
||||
avatarDataNotify.AvatarList = append(avatarDataNotify.AvatarList, pbAvatar)
|
||||
}
|
||||
avatarDataNotify.AvatarTeamMap = make(map[uint32]*proto.AvatarTeam)
|
||||
for teamIndex, team := range player.TeamConfig.TeamList {
|
||||
var teamAvatarGuidList []uint64 = nil
|
||||
for _, avatarId := range team.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
teamAvatarGuidList = append(teamAvatarGuidList, player.AvatarMap[avatarId].Guid)
|
||||
}
|
||||
avatarDataNotify.AvatarTeamMap[uint32(teamIndex)+1] = &proto.AvatarTeam{
|
||||
AvatarGuidList: teamAvatarGuidList,
|
||||
TeamName: team.Name,
|
||||
}
|
||||
}
|
||||
g.SendMsg(proto.ApiAvatarDataNotify, userId, clientSeq, avatarDataNotify)
|
||||
|
||||
player.SceneLoadState = model.SceneNone
|
||||
|
||||
// PacketPlayerEnterSceneNotify
|
||||
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotify(player)
|
||||
g.SendMsg(proto.ApiPlayerEnterSceneNotify, userId, clientSeq, playerEnterSceneNotify)
|
||||
|
||||
// PacketOpenStateUpdateNotify
|
||||
openStateUpdateNotify := new(proto.OpenStateUpdateNotify)
|
||||
openStateConstMap := reflection.ConvStructToMap(constant.OpenStateConst)
|
||||
openStateUpdateNotify.OpenStateMap = make(map[uint32]uint32)
|
||||
for _, v := range openStateConstMap {
|
||||
openStateUpdateNotify.OpenStateMap[uint32(v.(uint16))] = 1
|
||||
}
|
||||
g.SendMsg(proto.ApiOpenStateUpdateNotify, userId, clientSeq, openStateUpdateNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) OnReg(userId uint32, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user reg, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.SetPlayerBornDataReq)
|
||||
logger.LOG.Debug("avatar id: %v, nickname: %v", req.AvatarId, req.NickName)
|
||||
|
||||
exist, asyncWait := g.userManager.CheckUserExistOnReg(userId, req, clientSeq)
|
||||
if !asyncWait {
|
||||
g.OnRegOk(exist, req, userId, clientSeq)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) OnRegOk(exist bool, req *proto.SetPlayerBornDataReq, userId uint32, clientSeq uint32) {
|
||||
if exist {
|
||||
logger.LOG.Error("recv reg req, but user is already exist, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
|
||||
nickName := req.NickName
|
||||
mainCharAvatarId := req.GetAvatarId()
|
||||
if mainCharAvatarId != 10000005 && mainCharAvatarId != 10000007 {
|
||||
logger.LOG.Error("invalid main char avatar id: %v", mainCharAvatarId)
|
||||
return
|
||||
}
|
||||
|
||||
player := g.CreatePlayer(userId, nickName, mainCharAvatarId)
|
||||
g.userManager.AddUser(player)
|
||||
|
||||
g.SendMsg(proto.ApiSetPlayerBornDataRsp, userId, clientSeq, new(proto.SetPlayerBornDataRsp))
|
||||
g.OnLogin(userId, clientSeq)
|
||||
}
|
||||
|
||||
func (g *GameManager) OnUserOffline(userId uint32) {
|
||||
logger.LOG.Info("user offline, user id: %v", userId)
|
||||
player := g.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
if world != nil {
|
||||
g.UserWorldRemovePlayer(world, player)
|
||||
}
|
||||
player.OfflineTime = uint32(time.Now().Unix())
|
||||
player.Online = false
|
||||
player.TotalOnlineTime += uint32(time.Now().UnixMilli()) - player.OnlineTime
|
||||
g.userManager.OfflineUser(player)
|
||||
}
|
||||
|
||||
func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvatarId uint32) *model.Player {
|
||||
player := new(model.Player)
|
||||
player.PlayerID = userId
|
||||
player.NickName = nickName
|
||||
player.Signature = "惟愿时光记忆,一路繁花千树。"
|
||||
player.MainCharAvatarId = mainCharAvatarId
|
||||
player.HeadImage = mainCharAvatarId
|
||||
player.NameCard = 210001
|
||||
player.NameCardList = make([]uint32, 0)
|
||||
player.NameCardList = append(player.NameCardList, 210001, 210042)
|
||||
|
||||
player.FriendList = make(map[uint32]bool)
|
||||
player.FriendApplyList = make(map[uint32]bool)
|
||||
|
||||
player.RegionId = 1
|
||||
player.SceneId = 3
|
||||
|
||||
player.PropertiesMap = make(map[uint16]uint32)
|
||||
// 初始化所有属性
|
||||
propList := reflection.ConvStructToMap(constant.PlayerPropertyConst)
|
||||
for fieldName, fieldValue := range propList {
|
||||
if fieldName == "PROP_EXP" ||
|
||||
fieldName == "PROP_BREAK_LEVEL" ||
|
||||
fieldName == "PROP_SATIATION_VAL" ||
|
||||
fieldName == "PROP_SATIATION_PENALTY_TIME" ||
|
||||
fieldName == "PROP_LEVEL" {
|
||||
continue
|
||||
}
|
||||
value := fieldValue.(uint16)
|
||||
player.PropertiesMap[value] = 0
|
||||
}
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL] = 1
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL] = 0
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_IS_SPRING_AUTO_USE] = 1
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_SPRING_AUTO_USE_PERCENT] = 100
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_IS_FLYABLE] = 1
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_IS_TRANSFERABLE] = 1
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_MAX_STAMINA] = 24000
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_CUR_PERSIST_STAMINA] = 24000
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_RESIN] = 160
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE] = 2
|
||||
player.PropertiesMap[constant.PlayerPropertyConst.PROP_IS_MP_MODE_AVAILABLE] = 1
|
||||
|
||||
player.FlyCloakList = make([]uint32, 0)
|
||||
player.FlyCloakList = append(player.FlyCloakList, 140001)
|
||||
player.FlyCloakList = append(player.FlyCloakList, 140002)
|
||||
player.FlyCloakList = append(player.FlyCloakList, 140003)
|
||||
player.FlyCloakList = append(player.FlyCloakList, 140004)
|
||||
player.FlyCloakList = append(player.FlyCloakList, 140005)
|
||||
player.FlyCloakList = append(player.FlyCloakList, 140006)
|
||||
player.FlyCloakList = append(player.FlyCloakList, 140007)
|
||||
player.FlyCloakList = append(player.FlyCloakList, 140008)
|
||||
player.FlyCloakList = append(player.FlyCloakList, 140009)
|
||||
player.FlyCloakList = append(player.FlyCloakList, 140010)
|
||||
|
||||
player.CostumeList = make([]uint32, 0)
|
||||
player.CostumeList = append(player.CostumeList, 200301)
|
||||
player.CostumeList = append(player.CostumeList, 201401)
|
||||
player.CostumeList = append(player.CostumeList, 202701)
|
||||
player.CostumeList = append(player.CostumeList, 204201)
|
||||
player.CostumeList = append(player.CostumeList, 200302)
|
||||
player.CostumeList = append(player.CostumeList, 202101)
|
||||
player.CostumeList = append(player.CostumeList, 204101)
|
||||
player.CostumeList = append(player.CostumeList, 204501)
|
||||
player.CostumeList = append(player.CostumeList, 201601)
|
||||
player.CostumeList = append(player.CostumeList, 203101)
|
||||
|
||||
player.Pos = &model.Vector{X: 2747, Y: 194, Z: -1719}
|
||||
player.Rot = &model.Vector{X: 0, Y: 307, Z: 0}
|
||||
|
||||
player.ItemMap = make(map[uint32]*model.Item)
|
||||
player.WeaponMap = make(map[uint64]*model.Weapon)
|
||||
player.ReliquaryMap = make(map[uint64]*model.Reliquary)
|
||||
player.AvatarMap = make(map[uint32]*model.Avatar)
|
||||
player.GameObjectGuidMap = make(map[uint64]model.GameObject)
|
||||
player.DropInfo = model.NewDropInfo()
|
||||
player.ChatMsgMap = make(map[uint32][]*model.ChatMsg)
|
||||
|
||||
// 选哥哥的福报
|
||||
if mainCharAvatarId == 10000005 {
|
||||
// 添加所有角色
|
||||
allAvatarDataConfig := g.GetAllAvatarDataConfig()
|
||||
for avatarId, avatarDataConfig := range allAvatarDataConfig {
|
||||
player.AddAvatar(uint32(avatarId))
|
||||
// 添加初始武器
|
||||
weaponId := uint64(g.snowflake.GenId())
|
||||
player.AddWeapon(uint32(avatarDataConfig.InitialWeapon), weaponId)
|
||||
// 角色装上初始武器
|
||||
player.WearWeapon(uint32(avatarId), weaponId)
|
||||
}
|
||||
// 添加所有武器
|
||||
allWeaponDataConfig := g.GetAllWeaponDataConfig()
|
||||
for itemId := range allWeaponDataConfig {
|
||||
weaponId := uint64(g.snowflake.GenId())
|
||||
player.AddWeapon(uint32(itemId), weaponId)
|
||||
}
|
||||
// 添加所有道具
|
||||
allItemDataConfig := g.GetAllItemDataConfig()
|
||||
for itemId := range allItemDataConfig {
|
||||
player.AddItem(uint32(itemId), 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 添加选定的主角
|
||||
player.AddAvatar(mainCharAvatarId)
|
||||
// 添加初始武器
|
||||
avatarDataConfig := gdc.CONF.AvatarDataMap[int32(mainCharAvatarId)]
|
||||
weaponId := uint64(g.snowflake.GenId())
|
||||
player.AddWeapon(uint32(avatarDataConfig.InitialWeapon), weaponId)
|
||||
// 角色装上初始武器
|
||||
player.WearWeapon(mainCharAvatarId, weaponId)
|
||||
|
||||
player.TeamConfig = model.NewTeamInfo()
|
||||
player.TeamConfig.AddAvatarToTeam(mainCharAvatarId, 0)
|
||||
|
||||
return player
|
||||
}
|
||||
300
service/game-hk4e/game/user_manager.go
Normal file
300
service/game-hk4e/game/user_manager.go
Normal file
@@ -0,0 +1,300 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/dao"
|
||||
"game-hk4e/model"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserManager struct {
|
||||
dao *dao.Dao
|
||||
playerMap map[uint32]*model.Player
|
||||
playerMapLock sync.RWMutex
|
||||
localEventChan chan *LocalEvent
|
||||
}
|
||||
|
||||
func NewUserManager(dao *dao.Dao, localEventChan chan *LocalEvent) (r *UserManager) {
|
||||
r = new(UserManager)
|
||||
r.dao = dao
|
||||
r.playerMap = make(map[uint32]*model.Player)
|
||||
r.localEventChan = localEventChan
|
||||
return r
|
||||
}
|
||||
|
||||
func (u *UserManager) GetUserOnlineState(userId uint32) bool {
|
||||
u.playerMapLock.RLock()
|
||||
player, exist := u.playerMap[userId]
|
||||
u.playerMapLock.RUnlock()
|
||||
if !exist {
|
||||
return false
|
||||
} else {
|
||||
return player.Online
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) GetOnlineUser(userId uint32) *model.Player {
|
||||
u.playerMapLock.RLock()
|
||||
player, exist := u.playerMap[userId]
|
||||
u.playerMapLock.RUnlock()
|
||||
if !exist {
|
||||
return nil
|
||||
} else {
|
||||
if player.Online {
|
||||
return player
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) GetAllOnlineUserList() map[uint32]*model.Player {
|
||||
onlinePlayerMap := make(map[uint32]*model.Player)
|
||||
u.playerMapLock.RLock()
|
||||
for userId, player := range u.playerMap {
|
||||
if player.Online == false {
|
||||
continue
|
||||
}
|
||||
onlinePlayerMap[userId] = player
|
||||
}
|
||||
u.playerMapLock.RUnlock()
|
||||
return onlinePlayerMap
|
||||
}
|
||||
|
||||
type PlayerRegInfo struct {
|
||||
Exist bool
|
||||
Req *proto.SetPlayerBornDataReq
|
||||
UserId uint32
|
||||
ClientSeq uint32
|
||||
}
|
||||
|
||||
func (u *UserManager) CheckUserExistOnReg(userId uint32, req *proto.SetPlayerBornDataReq, clientSeq uint32) (exist bool, asyncWait bool) {
|
||||
u.playerMapLock.RLock()
|
||||
_, exist = u.playerMap[userId]
|
||||
u.playerMapLock.RUnlock()
|
||||
if exist {
|
||||
return true, false
|
||||
} else {
|
||||
go func() {
|
||||
player := u.loadUserFromDb(userId)
|
||||
exist = false
|
||||
if player != nil {
|
||||
exist = true
|
||||
}
|
||||
u.localEventChan <- &LocalEvent{
|
||||
EventId: CheckUserExistOnRegFromDbFinish,
|
||||
Msg: &PlayerRegInfo{
|
||||
Exist: exist,
|
||||
Req: req,
|
||||
UserId: userId,
|
||||
ClientSeq: clientSeq,
|
||||
},
|
||||
}
|
||||
}()
|
||||
return false, true
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) LoadTempOfflineUserSync(userId uint32) *model.Player {
|
||||
u.playerMapLock.RLock()
|
||||
player, exist := u.playerMap[userId]
|
||||
u.playerMapLock.RUnlock()
|
||||
if exist {
|
||||
return player
|
||||
} else {
|
||||
player = u.loadUserFromDb(userId)
|
||||
if player == nil {
|
||||
return nil
|
||||
}
|
||||
player.DbState = model.DbOffline
|
||||
u.playerMapLock.Lock()
|
||||
u.playerMap[player.PlayerID] = player
|
||||
u.playerMapLock.Unlock()
|
||||
return player
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) loadUserFromDb(userId uint32) *model.Player {
|
||||
player, err := u.dao.QueryPlayerByID(userId)
|
||||
if err != nil {
|
||||
logger.LOG.Error("query player error: %v", err)
|
||||
return nil
|
||||
}
|
||||
return player
|
||||
}
|
||||
|
||||
func (u *UserManager) AddUser(player *model.Player) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
u.ChangeUserDbState(player, model.DbInsert)
|
||||
u.playerMapLock.Lock()
|
||||
u.playerMap[player.PlayerID] = player
|
||||
u.playerMapLock.Unlock()
|
||||
}
|
||||
|
||||
func (u *UserManager) DeleteUser(player *model.Player) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
u.ChangeUserDbState(player, model.DbDelete)
|
||||
u.playerMapLock.Lock()
|
||||
u.playerMap[player.PlayerID] = player
|
||||
u.playerMapLock.Unlock()
|
||||
}
|
||||
|
||||
func (u *UserManager) UpdateUser(player *model.Player) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
u.ChangeUserDbState(player, model.DbUpdate)
|
||||
u.playerMapLock.Lock()
|
||||
u.playerMap[player.PlayerID] = player
|
||||
u.playerMapLock.Unlock()
|
||||
}
|
||||
|
||||
type PlayerLoginInfo struct {
|
||||
UserId uint32
|
||||
Player *model.Player
|
||||
ClientSeq uint32
|
||||
}
|
||||
|
||||
func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32) (*model.Player, bool) {
|
||||
u.playerMapLock.RLock()
|
||||
player, exist := u.playerMap[userId]
|
||||
u.playerMapLock.RUnlock()
|
||||
if exist {
|
||||
u.ChangeUserDbState(player, model.DbNormal)
|
||||
return player, false
|
||||
} else {
|
||||
go func() {
|
||||
player = u.loadUserFromDb(userId)
|
||||
if player != nil {
|
||||
player.DbState = model.DbNormal
|
||||
u.playerMapLock.Lock()
|
||||
u.playerMap[player.PlayerID] = player
|
||||
u.playerMapLock.Unlock()
|
||||
}
|
||||
u.localEventChan <- &LocalEvent{
|
||||
EventId: LoadLoginUserFromDbFinish,
|
||||
Msg: &PlayerLoginInfo{
|
||||
UserId: userId,
|
||||
Player: player,
|
||||
ClientSeq: clientSeq,
|
||||
},
|
||||
}
|
||||
}()
|
||||
return nil, true
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) OfflineUser(player *model.Player) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
u.ChangeUserDbState(player, model.DbOffline)
|
||||
u.playerMapLock.Lock()
|
||||
u.playerMap[player.PlayerID] = player
|
||||
u.playerMapLock.Unlock()
|
||||
}
|
||||
|
||||
func (u *UserManager) ChangeUserDbState(player *model.Player, state int) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
switch player.DbState {
|
||||
case model.DbInsert:
|
||||
if state == model.DbDelete {
|
||||
player.DbState = model.DbDelete
|
||||
}
|
||||
case model.DbDelete:
|
||||
case model.DbUpdate:
|
||||
if state == model.DbDelete {
|
||||
player.DbState = model.DbDelete
|
||||
} else if state == model.DbOffline {
|
||||
player.DbState = model.DbOffline
|
||||
}
|
||||
case model.DbNormal:
|
||||
if state == model.DbDelete {
|
||||
player.DbState = model.DbDelete
|
||||
} else if state == model.DbUpdate {
|
||||
player.DbState = model.DbUpdate
|
||||
} else if state == model.DbOffline {
|
||||
player.DbState = model.DbOffline
|
||||
}
|
||||
case model.DbOffline:
|
||||
if state == model.DbDelete {
|
||||
player.DbState = model.DbDelete
|
||||
} else if state == model.DbUpdate {
|
||||
player.DbState = model.DbUpdate
|
||||
} else if state == model.DbNormal {
|
||||
player.DbState = model.DbNormal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) StartAutoSaveUser() {
|
||||
// 用户数据库定时同步协程
|
||||
go func() {
|
||||
ticker := time.NewTicker(time.Minute * 5)
|
||||
for {
|
||||
logger.LOG.Info("auto save user start")
|
||||
playerMapTemp := make(map[uint32]*model.Player)
|
||||
u.playerMapLock.RLock()
|
||||
for k, v := range u.playerMap {
|
||||
playerMapTemp[k] = v
|
||||
}
|
||||
u.playerMapLock.RUnlock()
|
||||
logger.LOG.Info("copy user map finish")
|
||||
insertList := make([]*model.Player, 0)
|
||||
deleteList := make([]uint32, 0)
|
||||
updateList := make([]*model.Player, 0)
|
||||
for k, v := range playerMapTemp {
|
||||
switch v.DbState {
|
||||
case model.DbInsert:
|
||||
insertList = append(insertList, v)
|
||||
playerMapTemp[k].DbState = model.DbNormal
|
||||
case model.DbDelete:
|
||||
deleteList = append(deleteList, v.PlayerID)
|
||||
delete(playerMapTemp, k)
|
||||
case model.DbUpdate:
|
||||
updateList = append(updateList, v)
|
||||
playerMapTemp[k].DbState = model.DbNormal
|
||||
case model.DbNormal:
|
||||
continue
|
||||
case model.DbOffline:
|
||||
updateList = append(updateList, v)
|
||||
delete(playerMapTemp, k)
|
||||
}
|
||||
}
|
||||
insertListJson, err := json.Marshal(insertList)
|
||||
logger.LOG.Debug("insertList: %v", string(insertListJson))
|
||||
deleteListJson, err := json.Marshal(deleteList)
|
||||
logger.LOG.Debug("deleteList: %v", string(deleteListJson))
|
||||
updateListJson, err := json.Marshal(updateList)
|
||||
logger.LOG.Debug("updateList: %v", string(updateListJson))
|
||||
logger.LOG.Info("db state init finish")
|
||||
err = u.dao.InsertPlayerList(insertList)
|
||||
if err != nil {
|
||||
logger.LOG.Error("insert player list error: %v", err)
|
||||
}
|
||||
err = u.dao.DeletePlayerList(deleteList)
|
||||
if err != nil {
|
||||
logger.LOG.Error("delete player error: %v", err)
|
||||
}
|
||||
err = u.dao.UpdatePlayerList(updateList)
|
||||
if err != nil {
|
||||
logger.LOG.Error("update player error: %v", err)
|
||||
}
|
||||
logger.LOG.Info("db write finish")
|
||||
u.playerMapLock.Lock()
|
||||
u.playerMap = playerMapTemp
|
||||
u.playerMapLock.Unlock()
|
||||
logger.LOG.Info("auto save user finish")
|
||||
<-ticker.C
|
||||
}
|
||||
}()
|
||||
}
|
||||
191
service/game-hk4e/game/user_map.go
Normal file
191
service/game-hk4e/game/user_map.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (g *GameManager) SceneTransToPointReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get scene trans to point, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.SceneTransToPointReq)
|
||||
|
||||
transPointId := strconv.Itoa(int(req.SceneId)) + "_" + strconv.Itoa(int(req.PointId))
|
||||
transPointConfig, exist := gdc.CONF.ScenePointEntries[transPointId]
|
||||
if !exist {
|
||||
// PacketSceneTransToPointRsp
|
||||
sceneTransToPointRsp := new(proto.SceneTransToPointRsp)
|
||||
sceneTransToPointRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SVR_ERROR)
|
||||
g.SendMsg(proto.ApiSceneTransToPointRsp, userId, player.ClientSeq, sceneTransToPointRsp)
|
||||
return
|
||||
}
|
||||
|
||||
// 传送玩家
|
||||
newSceneId := req.SceneId
|
||||
oldSceneId := player.SceneId
|
||||
oldPos := &model.Vector{
|
||||
X: player.Pos.X,
|
||||
Y: player.Pos.Y,
|
||||
Z: player.Pos.Z,
|
||||
}
|
||||
jumpScene := false
|
||||
if newSceneId != oldSceneId {
|
||||
jumpScene = true
|
||||
}
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
oldScene := world.GetSceneById(oldSceneId)
|
||||
activeAvatarId := player.TeamConfig.GetActiveAvatarId()
|
||||
playerTeamEntity := oldScene.GetPlayerTeamEntity(player.PlayerID)
|
||||
g.RemoveSceneEntityNotifyBroadcast(oldScene, []uint32{playerTeamEntity.avatarEntityMap[activeAvatarId]})
|
||||
if jumpScene {
|
||||
// PacketDelTeamEntityNotify
|
||||
delTeamEntityNotify := g.PacketDelTeamEntityNotify(oldScene, player)
|
||||
g.SendMsg(proto.ApiDelTeamEntityNotify, player.PlayerID, player.ClientSeq, delTeamEntityNotify)
|
||||
|
||||
oldScene.RemovePlayer(player)
|
||||
newScene := world.GetSceneById(newSceneId)
|
||||
newScene.AddPlayer(player)
|
||||
} else {
|
||||
oldScene.UpdatePlayerTeamEntity(player)
|
||||
}
|
||||
player.Pos.X = transPointConfig.PointData.TranPos.X
|
||||
player.Pos.Y = transPointConfig.PointData.TranPos.Y
|
||||
player.Pos.Z = transPointConfig.PointData.TranPos.Z
|
||||
player.SceneId = newSceneId
|
||||
player.SceneLoadState = model.SceneNone
|
||||
|
||||
// PacketPlayerEnterSceneNotify
|
||||
var enterType proto.EnterType
|
||||
if jumpScene {
|
||||
logger.LOG.Debug("player jump scene, scene: %v, pos: %v", player.SceneId, player.Pos)
|
||||
enterType = proto.EnterType_ENTER_TYPE_JUMP
|
||||
} else {
|
||||
logger.LOG.Debug("player goto scene, scene: %v, pos: %v", player.SceneId, player.Pos)
|
||||
enterType = proto.EnterType_ENTER_TYPE_GOTO
|
||||
}
|
||||
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyTp(player, enterType, uint32(constant.EnterReasonConst.TransPoint), oldSceneId, oldPos)
|
||||
g.SendMsg(proto.ApiPlayerEnterSceneNotify, userId, player.ClientSeq, playerEnterSceneNotify)
|
||||
|
||||
// PacketSceneTransToPointRsp
|
||||
sceneTransToPointRsp := new(proto.SceneTransToPointRsp)
|
||||
sceneTransToPointRsp.Retcode = 0
|
||||
sceneTransToPointRsp.PointId = req.PointId
|
||||
sceneTransToPointRsp.SceneId = req.SceneId
|
||||
g.SendMsg(proto.ApiSceneTransToPointRsp, userId, player.ClientSeq, sceneTransToPointRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) MarkMapReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user mark map, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.MarkMapReq)
|
||||
operation := req.Op
|
||||
if operation == proto.MarkMapReq_OPERATION_ADD {
|
||||
logger.LOG.Debug("user mark type: %v", req.Mark.PointType)
|
||||
if req.Mark.PointType == proto.MapMarkPointType_MAP_MARK_POINT_TYPE_NPC {
|
||||
posYInt, err := strconv.ParseInt(req.Mark.Name, 10, 64)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse pos y error: %v", err)
|
||||
posYInt = 0
|
||||
}
|
||||
|
||||
// 传送玩家
|
||||
newSceneId := req.Mark.SceneId
|
||||
oldSceneId := player.SceneId
|
||||
oldPos := &model.Vector{
|
||||
X: player.Pos.X,
|
||||
Y: player.Pos.Y,
|
||||
Z: player.Pos.Z,
|
||||
}
|
||||
jumpScene := false
|
||||
if newSceneId != oldSceneId {
|
||||
jumpScene = true
|
||||
}
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
oldScene := world.GetSceneById(oldSceneId)
|
||||
activeAvatarId := player.TeamConfig.GetActiveAvatarId()
|
||||
playerTeamEntity := oldScene.GetPlayerTeamEntity(player.PlayerID)
|
||||
g.RemoveSceneEntityNotifyBroadcast(oldScene, []uint32{playerTeamEntity.avatarEntityMap[activeAvatarId]})
|
||||
if jumpScene {
|
||||
// PacketDelTeamEntityNotify
|
||||
delTeamEntityNotify := g.PacketDelTeamEntityNotify(oldScene, player)
|
||||
g.SendMsg(proto.ApiDelTeamEntityNotify, player.PlayerID, player.ClientSeq, delTeamEntityNotify)
|
||||
|
||||
oldScene.RemovePlayer(player)
|
||||
newScene := world.GetSceneById(newSceneId)
|
||||
newScene.AddPlayer(player)
|
||||
} else {
|
||||
oldScene.UpdatePlayerTeamEntity(player)
|
||||
}
|
||||
player.Pos.X = float64(req.Mark.Pos.X)
|
||||
player.Pos.Y = float64(posYInt)
|
||||
player.Pos.Z = float64(req.Mark.Pos.Z)
|
||||
player.SceneId = newSceneId
|
||||
player.SceneLoadState = model.SceneNone
|
||||
|
||||
// PacketPlayerEnterSceneNotify
|
||||
var enterType proto.EnterType
|
||||
if jumpScene {
|
||||
logger.LOG.Debug("player jump scene, scene: %v, pos: %v", player.SceneId, player.Pos)
|
||||
enterType = proto.EnterType_ENTER_TYPE_JUMP
|
||||
} else {
|
||||
logger.LOG.Debug("player goto scene, scene: %v, pos: %v", player.SceneId, player.Pos)
|
||||
enterType = proto.EnterType_ENTER_TYPE_GOTO
|
||||
}
|
||||
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyTp(player, enterType, uint32(constant.EnterReasonConst.TransPoint), oldSceneId, oldPos)
|
||||
g.SendMsg(proto.ApiPlayerEnterSceneNotify, userId, player.ClientSeq, playerEnterSceneNotify)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) PathfindingEnterSceneReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user pathfinding enter scene, user id: %v", userId)
|
||||
g.SendMsg(proto.ApiPathfindingEnterSceneRsp, userId, player.ClientSeq, new(proto.PathfindingEnterSceneRsp))
|
||||
}
|
||||
|
||||
func (g *GameManager) QueryPathReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
//logger.LOG.Debug("user query path, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.QueryPathReq)
|
||||
|
||||
// PacketQueryPathRsp
|
||||
queryPathRsp := new(proto.QueryPathRsp)
|
||||
queryPathRsp.Corners = []*proto.Vector{req.DestinationPos[0]}
|
||||
queryPathRsp.QueryId = req.QueryId
|
||||
queryPathRsp.QueryStatus = proto.QueryPathRsp_PATH_STATUS_TYPE_SUCC
|
||||
g.SendMsg(proto.ApiQueryPathRsp, userId, player.ClientSeq, queryPathRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) GetScenePointReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get scene point, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.GetScenePointReq)
|
||||
|
||||
// PacketGetScenePointRsp
|
||||
getScenePointRsp := new(proto.GetScenePointRsp)
|
||||
getScenePointRsp.SceneId = req.SceneId
|
||||
getScenePointRsp.UnlockedPointList = make([]uint32, 0)
|
||||
for i := uint32(1); i < 1000; i++ {
|
||||
getScenePointRsp.UnlockedPointList = append(getScenePointRsp.UnlockedPointList, i)
|
||||
}
|
||||
getScenePointRsp.UnlockAreaList = make([]uint32, 0)
|
||||
for i := uint32(1); i < 9; i++ {
|
||||
getScenePointRsp.UnlockAreaList = append(getScenePointRsp.UnlockAreaList, i)
|
||||
}
|
||||
g.SendMsg(proto.ApiGetScenePointRsp, userId, player.ClientSeq, getScenePointRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) GetSceneAreaReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get scene area, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.GetSceneAreaReq)
|
||||
|
||||
// PacketGetSceneAreaRsp
|
||||
getSceneAreaRsp := new(proto.GetSceneAreaRsp)
|
||||
getSceneAreaRsp.SceneId = req.SceneId
|
||||
getSceneAreaRsp.AreaIdList = []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23, 24, 25, 100, 101, 102, 103, 200, 210, 300, 400, 401, 402, 403}
|
||||
getSceneAreaRsp.CityInfoList = make([]*proto.CityInfo, 0)
|
||||
getSceneAreaRsp.CityInfoList = append(getSceneAreaRsp.CityInfoList, &proto.CityInfo{CityId: 1, Level: 1})
|
||||
getSceneAreaRsp.CityInfoList = append(getSceneAreaRsp.CityInfoList, &proto.CityInfo{CityId: 2, Level: 1})
|
||||
getSceneAreaRsp.CityInfoList = append(getSceneAreaRsp.CityInfoList, &proto.CityInfo{CityId: 3, Level: 1})
|
||||
g.SendMsg(proto.ApiGetSceneAreaRsp, userId, player.ClientSeq, getSceneAreaRsp)
|
||||
}
|
||||
416
service/game-hk4e/game/user_multiplayer.go
Normal file
416
service/game-hk4e/game/user_multiplayer.go
Normal file
@@ -0,0 +1,416 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (g *GameManager) PlayerApplyEnterMpReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user apply enter world, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.PlayerApplyEnterMpReq)
|
||||
targetUid := req.TargetUid
|
||||
|
||||
// PacketPlayerApplyEnterMpRsp
|
||||
playerApplyEnterMpRsp := new(proto.PlayerApplyEnterMpRsp)
|
||||
playerApplyEnterMpRsp.TargetUid = targetUid
|
||||
g.SendMsg(proto.ApiPlayerApplyEnterMpRsp, player.PlayerID, player.ClientSeq, playerApplyEnterMpRsp)
|
||||
|
||||
ok := g.UserApplyEnterWorld(player, targetUid)
|
||||
if !ok {
|
||||
// PacketPlayerApplyEnterMpResultNotify
|
||||
playerApplyEnterMpResultNotify := new(proto.PlayerApplyEnterMpResultNotify)
|
||||
playerApplyEnterMpResultNotify.TargetUid = targetUid
|
||||
playerApplyEnterMpResultNotify.TargetNickname = ""
|
||||
playerApplyEnterMpResultNotify.IsAgreed = false
|
||||
playerApplyEnterMpResultNotify.Reason = proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_CANNOT_ENTER_MP
|
||||
g.SendMsg(proto.ApiPlayerApplyEnterMpResultNotify, player.PlayerID, player.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) PlayerApplyEnterMpResultReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user deal world enter apply, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.PlayerApplyEnterMpResultReq)
|
||||
applyUid := req.ApplyUid
|
||||
isAgreed := req.IsAgreed
|
||||
|
||||
g.UserDealEnterWorld(player, applyUid, isAgreed)
|
||||
|
||||
// PacketPlayerApplyEnterMpResultRsp
|
||||
playerApplyEnterMpResultRsp := new(proto.PlayerApplyEnterMpResultRsp)
|
||||
playerApplyEnterMpResultRsp.ApplyUid = applyUid
|
||||
playerApplyEnterMpResultRsp.IsAgreed = isAgreed
|
||||
g.SendMsg(proto.ApiPlayerApplyEnterMpResultRsp, player.PlayerID, player.ClientSeq, playerApplyEnterMpResultRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) PlayerGetForceQuitBanInfoReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get world exit ban info, user id: %v", userId)
|
||||
|
||||
result := true
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
if worldPlayer.SceneLoadState != model.SceneEnterDone {
|
||||
result = false
|
||||
}
|
||||
}
|
||||
|
||||
// PacketPlayerGetForceQuitBanInfoRsp
|
||||
playerGetForceQuitBanInfoRsp := new(proto.PlayerGetForceQuitBanInfoRsp)
|
||||
if result {
|
||||
playerGetForceQuitBanInfoRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SUCC)
|
||||
} else {
|
||||
playerGetForceQuitBanInfoRsp.Retcode = int32(proto.Retcode_RETCODE_RET_MP_TARGET_PLAYER_IN_TRANSFER)
|
||||
}
|
||||
g.SendMsg(proto.ApiPlayerGetForceQuitBanInfoRsp, player.PlayerID, player.ClientSeq, playerGetForceQuitBanInfoRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) BackMyWorldReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user back world, user id: %v", userId)
|
||||
|
||||
// 其他玩家
|
||||
ok := g.UserLeaveWorld(player)
|
||||
|
||||
// PacketBackMyWorldRsp
|
||||
backMyWorldRsp := new(proto.BackMyWorldRsp)
|
||||
if ok {
|
||||
backMyWorldRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SUCC)
|
||||
} else {
|
||||
backMyWorldRsp.Retcode = int32(proto.Retcode_RETCODE_RET_MP_TARGET_PLAYER_IN_TRANSFER)
|
||||
}
|
||||
g.SendMsg(proto.ApiBackMyWorldRsp, player.PlayerID, player.ClientSeq, backMyWorldRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) ChangeWorldToSingleModeReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change world to single, user id: %v", userId)
|
||||
|
||||
// 房主
|
||||
ok := g.UserLeaveWorld(player)
|
||||
|
||||
// PacketChangeWorldToSingleModeRsp
|
||||
changeWorldToSingleModeRsp := new(proto.ChangeWorldToSingleModeRsp)
|
||||
if ok {
|
||||
changeWorldToSingleModeRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SUCC)
|
||||
} else {
|
||||
changeWorldToSingleModeRsp.Retcode = int32(proto.Retcode_RETCODE_RET_MP_TARGET_PLAYER_IN_TRANSFER)
|
||||
}
|
||||
g.SendMsg(proto.ApiChangeWorldToSingleModeRsp, player.PlayerID, player.ClientSeq, changeWorldToSingleModeRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) SceneKickPlayerReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user kick player, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.SceneKickPlayerReq)
|
||||
targetUid := req.TargetUid
|
||||
|
||||
targetPlayer := g.userManager.GetOnlineUser(targetUid)
|
||||
ok := g.UserLeaveWorld(targetPlayer)
|
||||
if ok {
|
||||
// PacketSceneKickPlayerNotify
|
||||
sceneKickPlayerNotify := new(proto.SceneKickPlayerNotify)
|
||||
sceneKickPlayerNotify.TargetUid = targetUid
|
||||
sceneKickPlayerNotify.KickerUid = player.PlayerID
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
g.SendMsg(proto.ApiSceneKickPlayerNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, sceneKickPlayerNotify)
|
||||
}
|
||||
}
|
||||
|
||||
// PacketSceneKickPlayerRsp
|
||||
sceneKickPlayerRsp := new(proto.SceneKickPlayerRsp)
|
||||
if ok {
|
||||
sceneKickPlayerRsp.TargetUid = targetUid
|
||||
} else {
|
||||
sceneKickPlayerRsp.Retcode = int32(proto.Retcode_RETCODE_RET_MP_TARGET_PLAYER_IN_TRANSFER)
|
||||
}
|
||||
g.SendMsg(proto.ApiSceneKickPlayerRsp, player.PlayerID, player.ClientSeq, sceneKickPlayerRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) UserApplyEnterWorld(player *model.Player, targetUid uint32) bool {
|
||||
targetPlayer := g.userManager.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
return false
|
||||
}
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
if world.multiplayer {
|
||||
return false
|
||||
}
|
||||
applyTime, exist := targetPlayer.CoopApplyMap[player.PlayerID]
|
||||
if exist && time.Now().UnixNano() < applyTime+int64(10*time.Second) {
|
||||
return false
|
||||
}
|
||||
targetPlayer.CoopApplyMap[player.PlayerID] = time.Now().UnixNano()
|
||||
targetWorld := g.worldManager.GetWorldByID(targetPlayer.WorldId)
|
||||
if targetWorld.multiplayer && targetWorld.owner.PlayerID != targetPlayer.PlayerID {
|
||||
return false
|
||||
}
|
||||
|
||||
// PacketPlayerApplyEnterMpNotify
|
||||
playerApplyEnterMpNotify := new(proto.PlayerApplyEnterMpNotify)
|
||||
playerApplyEnterMpNotify.SrcPlayerInfo = g.PacketOnlinePlayerInfo(player)
|
||||
g.SendMsg(proto.ApiPlayerApplyEnterMpNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, playerApplyEnterMpNotify)
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *GameManager) UserDealEnterWorld(hostPlayer *model.Player, otherUid uint32, agree bool) {
|
||||
otherPlayer := g.userManager.GetOnlineUser(otherUid)
|
||||
if otherPlayer == nil {
|
||||
return
|
||||
}
|
||||
applyTime, exist := hostPlayer.CoopApplyMap[otherUid]
|
||||
if !exist || time.Now().UnixNano() > applyTime+int64(10*time.Second) {
|
||||
return
|
||||
}
|
||||
delete(hostPlayer.CoopApplyMap, otherUid)
|
||||
otherPlayerWorld := g.worldManager.GetWorldByID(otherPlayer.WorldId)
|
||||
if otherPlayerWorld.multiplayer {
|
||||
// PacketPlayerApplyEnterMpResultNotify
|
||||
playerApplyEnterMpResultNotify := new(proto.PlayerApplyEnterMpResultNotify)
|
||||
playerApplyEnterMpResultNotify.TargetUid = hostPlayer.PlayerID
|
||||
playerApplyEnterMpResultNotify.TargetNickname = hostPlayer.NickName
|
||||
playerApplyEnterMpResultNotify.IsAgreed = false
|
||||
playerApplyEnterMpResultNotify.Reason = proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_CANNOT_ENTER_MP
|
||||
g.SendMsg(proto.ApiPlayerApplyEnterMpResultNotify, otherPlayer.PlayerID, otherPlayer.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
return
|
||||
}
|
||||
|
||||
// PacketPlayerApplyEnterMpResultNotify
|
||||
playerApplyEnterMpResultNotify := new(proto.PlayerApplyEnterMpResultNotify)
|
||||
playerApplyEnterMpResultNotify.TargetUid = hostPlayer.PlayerID
|
||||
playerApplyEnterMpResultNotify.TargetNickname = hostPlayer.NickName
|
||||
playerApplyEnterMpResultNotify.IsAgreed = agree
|
||||
playerApplyEnterMpResultNotify.Reason = proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_JUDGE
|
||||
g.SendMsg(proto.ApiPlayerApplyEnterMpResultNotify, otherPlayer.PlayerID, otherPlayer.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
|
||||
if !agree {
|
||||
return
|
||||
}
|
||||
|
||||
hostWorld := g.worldManager.GetWorldByID(hostPlayer.WorldId)
|
||||
if hostWorld.multiplayer == false {
|
||||
g.UserWorldRemovePlayer(hostWorld, hostPlayer)
|
||||
|
||||
hostPlayer.TeamConfig.CurrTeamIndex = 3
|
||||
hostPlayer.TeamConfig.CurrAvatarIndex = 0
|
||||
|
||||
// PacketPlayerEnterSceneNotify
|
||||
hostPlayerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyMp(
|
||||
hostPlayer,
|
||||
hostPlayer,
|
||||
proto.EnterType_ENTER_TYPE_SELF,
|
||||
uint32(constant.EnterReasonConst.HostFromSingleToMp),
|
||||
hostPlayer.SceneId,
|
||||
hostPlayer.Pos,
|
||||
)
|
||||
g.SendMsg(proto.ApiPlayerEnterSceneNotify, hostPlayer.PlayerID, hostPlayer.ClientSeq, hostPlayerEnterSceneNotify)
|
||||
|
||||
hostWorld = g.worldManager.CreateWorld(hostPlayer, true)
|
||||
g.UserWorldAddPlayer(hostWorld, hostPlayer)
|
||||
hostPlayer.SceneLoadState = model.SceneNone
|
||||
}
|
||||
|
||||
otherWorld := g.worldManager.GetWorldByID(otherPlayer.WorldId)
|
||||
g.UserWorldRemovePlayer(otherWorld, otherPlayer)
|
||||
|
||||
otherPlayerOldSceneId := otherPlayer.SceneId
|
||||
otherPlayerOldPos := &model.Vector{
|
||||
X: otherPlayer.Pos.X,
|
||||
Y: otherPlayer.Pos.Y,
|
||||
Z: otherPlayer.Pos.Z,
|
||||
}
|
||||
|
||||
otherPlayer.Pos = &model.Vector{
|
||||
X: hostPlayer.Pos.X,
|
||||
Y: hostPlayer.Pos.Y + 1,
|
||||
Z: hostPlayer.Pos.Z,
|
||||
}
|
||||
otherPlayer.Rot = &model.Vector{
|
||||
X: hostPlayer.Rot.X,
|
||||
Y: hostPlayer.Rot.Y,
|
||||
Z: hostPlayer.Rot.Z,
|
||||
}
|
||||
otherPlayer.SceneId = hostPlayer.SceneId
|
||||
otherPlayer.TeamConfig.CurrTeamIndex = 3
|
||||
otherPlayer.TeamConfig.CurrAvatarIndex = 0
|
||||
|
||||
// PacketPlayerEnterSceneNotify
|
||||
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyMp(
|
||||
otherPlayer,
|
||||
hostPlayer,
|
||||
proto.EnterType_ENTER_TYPE_OTHER,
|
||||
uint32(constant.EnterReasonConst.TeamJoin),
|
||||
otherPlayerOldSceneId,
|
||||
otherPlayerOldPos,
|
||||
)
|
||||
g.SendMsg(proto.ApiPlayerEnterSceneNotify, otherPlayer.PlayerID, otherPlayer.ClientSeq, playerEnterSceneNotify)
|
||||
|
||||
g.UserWorldAddPlayer(hostWorld, otherPlayer)
|
||||
otherPlayer.SceneLoadState = model.SceneNone
|
||||
}
|
||||
|
||||
func (g *GameManager) UserLeaveWorld(player *model.Player) bool {
|
||||
oldWorld := g.worldManager.GetWorldByID(player.WorldId)
|
||||
if !oldWorld.multiplayer {
|
||||
return false
|
||||
}
|
||||
for _, worldPlayer := range oldWorld.playerMap {
|
||||
if worldPlayer.SceneLoadState != model.SceneEnterDone {
|
||||
return false
|
||||
}
|
||||
}
|
||||
g.UserWorldRemovePlayer(oldWorld, player)
|
||||
//{
|
||||
// newWorld := g.worldManager.CreateWorld(player, false)
|
||||
// g.UserWorldAddPlayer(newWorld, player)
|
||||
// player.SceneLoadState = model.SceneNone
|
||||
//
|
||||
// // PacketPlayerEnterSceneNotify
|
||||
// enterReasonConst := constant.GetEnterReasonConst()
|
||||
// playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyMp(
|
||||
// player,
|
||||
// player,
|
||||
// proto.EnterType_ENTER_TYPE_SELF,
|
||||
// uint32(enterReasonConst.TeamBack),
|
||||
// player.SceneId,
|
||||
// player.Pos,
|
||||
// )
|
||||
// g.SendMsg(proto.ApiPlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, playerEnterSceneNotify)
|
||||
//}
|
||||
{
|
||||
// PacketClientReconnectNotify
|
||||
g.SendMsg(proto.ApiClientReconnectNotify, player.PlayerID, 0, new(proto.ClientReconnectNotify))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *GameManager) UserWorldAddPlayer(world *World, player *model.Player) {
|
||||
_, exist := world.playerMap[player.PlayerID]
|
||||
if exist {
|
||||
return
|
||||
}
|
||||
world.AddPlayer(player, player.SceneId)
|
||||
player.WorldId = world.id
|
||||
if len(world.playerMap) > 1 {
|
||||
g.UpdateWorldPlayerInfo(world, player)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) UserWorldRemovePlayer(world *World, player *model.Player) {
|
||||
if world.multiplayer && player.PlayerID == world.owner.PlayerID {
|
||||
// 多人世界房主离开剔除所有其他玩家
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
if worldPlayer.PlayerID == world.owner.PlayerID {
|
||||
continue
|
||||
}
|
||||
if ok := g.UserLeaveWorld(worldPlayer); !ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PacketDelTeamEntityNotify
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
delTeamEntityNotify := g.PacketDelTeamEntityNotify(scene, player)
|
||||
g.SendMsg(proto.ApiDelTeamEntityNotify, player.PlayerID, player.ClientSeq, delTeamEntityNotify)
|
||||
|
||||
if world.multiplayer {
|
||||
// PlayerQuitFromMpNotify
|
||||
playerQuitFromMpNotify := new(proto.PlayerQuitFromMpNotify)
|
||||
playerQuitFromMpNotify.Reason = proto.PlayerQuitFromMpNotify_QUIT_REASON_BACK_TO_MY_WORLD
|
||||
g.SendMsg(proto.ApiPlayerQuitFromMpNotify, player.PlayerID, player.ClientSeq, playerQuitFromMpNotify)
|
||||
|
||||
activeAvatarId := player.TeamConfig.GetActiveAvatarId()
|
||||
playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID)
|
||||
g.RemoveSceneEntityNotifyBroadcast(scene, []uint32{playerTeamEntity.avatarEntityMap[activeAvatarId]})
|
||||
}
|
||||
|
||||
world.RemovePlayer(player)
|
||||
player.WorldId = 0
|
||||
|
||||
if world.multiplayer && len(world.playerMap) > 0 {
|
||||
g.UpdateWorldPlayerInfo(world, player)
|
||||
}
|
||||
|
||||
if world.owner.PlayerID == player.PlayerID {
|
||||
// 房主离开销毁世界
|
||||
g.worldManager.DestroyWorld(world.id)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) UpdateWorldPlayerInfo(hostWorld *World, excludePlayer *model.Player) {
|
||||
for _, worldPlayer := range hostWorld.playerMap {
|
||||
if worldPlayer.PlayerID == excludePlayer.PlayerID || worldPlayer.SceneLoadState == model.SceneNone {
|
||||
continue
|
||||
}
|
||||
|
||||
// PacketSceneTeamUpdateNotify
|
||||
sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(hostWorld)
|
||||
g.SendMsg(proto.ApiSceneTeamUpdateNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, sceneTeamUpdateNotify)
|
||||
|
||||
// PacketWorldPlayerInfoNotify
|
||||
worldPlayerInfoNotify := new(proto.WorldPlayerInfoNotify)
|
||||
for _, subWorldPlayer := range hostWorld.playerMap {
|
||||
onlinePlayerInfo := new(proto.OnlinePlayerInfo)
|
||||
onlinePlayerInfo.Uid = subWorldPlayer.PlayerID
|
||||
onlinePlayerInfo.Nickname = subWorldPlayer.NickName
|
||||
onlinePlayerInfo.PlayerLevel = subWorldPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]
|
||||
onlinePlayerInfo.MpSettingType = proto.MpSettingType(subWorldPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE])
|
||||
onlinePlayerInfo.NameCardId = subWorldPlayer.NameCard
|
||||
onlinePlayerInfo.Signature = subWorldPlayer.Signature
|
||||
onlinePlayerInfo.ProfilePicture = &proto.ProfilePicture{AvatarId: subWorldPlayer.HeadImage}
|
||||
onlinePlayerInfo.CurPlayerNumInWorld = uint32(len(hostWorld.playerMap))
|
||||
worldPlayerInfoNotify.PlayerInfoList = append(worldPlayerInfoNotify.PlayerInfoList, onlinePlayerInfo)
|
||||
worldPlayerInfoNotify.PlayerUidList = append(worldPlayerInfoNotify.PlayerUidList, subWorldPlayer.PlayerID)
|
||||
}
|
||||
g.SendMsg(proto.ApiWorldPlayerInfoNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, worldPlayerInfoNotify)
|
||||
|
||||
// PacketScenePlayerInfoNotify
|
||||
scenePlayerInfoNotify := new(proto.ScenePlayerInfoNotify)
|
||||
for _, subWorldPlayer := range hostWorld.playerMap {
|
||||
onlinePlayerInfo := new(proto.OnlinePlayerInfo)
|
||||
onlinePlayerInfo.Uid = subWorldPlayer.PlayerID
|
||||
onlinePlayerInfo.Nickname = subWorldPlayer.NickName
|
||||
onlinePlayerInfo.PlayerLevel = subWorldPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]
|
||||
onlinePlayerInfo.MpSettingType = proto.MpSettingType(subWorldPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE])
|
||||
onlinePlayerInfo.NameCardId = subWorldPlayer.NameCard
|
||||
onlinePlayerInfo.Signature = subWorldPlayer.Signature
|
||||
onlinePlayerInfo.ProfilePicture = &proto.ProfilePicture{AvatarId: subWorldPlayer.HeadImage}
|
||||
onlinePlayerInfo.CurPlayerNumInWorld = uint32(len(hostWorld.playerMap))
|
||||
scenePlayerInfoNotify.PlayerInfoList = append(scenePlayerInfoNotify.PlayerInfoList, &proto.ScenePlayerInfo{
|
||||
Uid: subWorldPlayer.PlayerID,
|
||||
PeerId: subWorldPlayer.PeerId,
|
||||
Name: subWorldPlayer.NickName,
|
||||
SceneId: subWorldPlayer.SceneId,
|
||||
OnlinePlayerInfo: onlinePlayerInfo,
|
||||
})
|
||||
}
|
||||
g.SendMsg(proto.ApiScenePlayerInfoNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, scenePlayerInfoNotify)
|
||||
|
||||
// PacketSyncTeamEntityNotify
|
||||
syncTeamEntityNotify := new(proto.SyncTeamEntityNotify)
|
||||
syncTeamEntityNotify.SceneId = worldPlayer.SceneId
|
||||
syncTeamEntityNotify.TeamEntityInfoList = make([]*proto.TeamEntityInfo, 0)
|
||||
if hostWorld.multiplayer {
|
||||
for _, subWorldPlayer := range hostWorld.playerMap {
|
||||
if subWorldPlayer.PlayerID == worldPlayer.PlayerID {
|
||||
continue
|
||||
}
|
||||
subWorldPlayerScene := hostWorld.GetSceneById(subWorldPlayer.SceneId)
|
||||
subWorldPlayerTeamEntity := subWorldPlayerScene.GetPlayerTeamEntity(subWorldPlayer.PlayerID)
|
||||
teamEntityInfo := &proto.TeamEntityInfo{
|
||||
TeamEntityId: subWorldPlayerTeamEntity.teamEntityId,
|
||||
AuthorityPeerId: subWorldPlayer.PeerId,
|
||||
TeamAbilityInfo: new(proto.AbilitySyncStateInfo),
|
||||
}
|
||||
syncTeamEntityNotify.TeamEntityInfoList = append(syncTeamEntityNotify.TeamEntityInfoList, teamEntityInfo)
|
||||
}
|
||||
}
|
||||
g.SendMsg(proto.ApiSyncTeamEntityNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, syncTeamEntityNotify)
|
||||
|
||||
// PacketSyncScenePlayTeamEntityNotify
|
||||
syncScenePlayTeamEntityNotify := new(proto.SyncScenePlayTeamEntityNotify)
|
||||
syncScenePlayTeamEntityNotify.SceneId = worldPlayer.SceneId
|
||||
g.SendMsg(proto.ApiSyncScenePlayTeamEntityNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, syncScenePlayTeamEntityNotify)
|
||||
}
|
||||
}
|
||||
710
service/game-hk4e/game/user_scene.go
Normal file
710
service/game-hk4e/game/user_scene.go
Normal file
@@ -0,0 +1,710 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/common/utils/object"
|
||||
"flswld.com/common/utils/random"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (g *GameManager) EnterSceneReadyReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user enter scene ready, user id: %v", userId)
|
||||
|
||||
// PacketEnterScenePeerNotify
|
||||
enterScenePeerNotify := new(proto.EnterScenePeerNotify)
|
||||
enterScenePeerNotify.DestSceneId = player.SceneId
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
enterScenePeerNotify.PeerId = player.PeerId
|
||||
enterScenePeerNotify.HostPeerId = world.owner.PeerId
|
||||
enterScenePeerNotify.EnterSceneToken = player.EnterSceneToken
|
||||
g.SendMsg(proto.ApiEnterScenePeerNotify, userId, player.ClientSeq, enterScenePeerNotify)
|
||||
|
||||
// PacketEnterSceneReadyRsp
|
||||
enterSceneReadyRsp := new(proto.EnterSceneReadyRsp)
|
||||
enterSceneReadyRsp.EnterSceneToken = player.EnterSceneToken
|
||||
g.SendMsg(proto.ApiEnterSceneReadyRsp, userId, player.ClientSeq, enterSceneReadyRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) SceneInitFinishReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user scene init finish, user id: %v", userId)
|
||||
|
||||
// PacketServerTimeNotify
|
||||
serverTimeNotify := new(proto.ServerTimeNotify)
|
||||
serverTimeNotify.ServerTime = uint64(time.Now().UnixMilli())
|
||||
g.SendMsg(proto.ApiServerTimeNotify, userId, player.ClientSeq, serverTimeNotify)
|
||||
|
||||
// PacketWorldPlayerInfoNotify
|
||||
worldPlayerInfoNotify := new(proto.WorldPlayerInfoNotify)
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
onlinePlayerInfo := new(proto.OnlinePlayerInfo)
|
||||
onlinePlayerInfo.Uid = worldPlayer.PlayerID
|
||||
onlinePlayerInfo.Nickname = worldPlayer.NickName
|
||||
onlinePlayerInfo.PlayerLevel = worldPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]
|
||||
onlinePlayerInfo.MpSettingType = proto.MpSettingType(worldPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE])
|
||||
onlinePlayerInfo.NameCardId = worldPlayer.NameCard
|
||||
onlinePlayerInfo.Signature = worldPlayer.Signature
|
||||
onlinePlayerInfo.ProfilePicture = &proto.ProfilePicture{AvatarId: worldPlayer.HeadImage}
|
||||
onlinePlayerInfo.CurPlayerNumInWorld = uint32(len(world.playerMap))
|
||||
worldPlayerInfoNotify.PlayerInfoList = append(worldPlayerInfoNotify.PlayerInfoList, onlinePlayerInfo)
|
||||
worldPlayerInfoNotify.PlayerUidList = append(worldPlayerInfoNotify.PlayerUidList, worldPlayer.PlayerID)
|
||||
}
|
||||
g.SendMsg(proto.ApiWorldPlayerInfoNotify, userId, player.ClientSeq, worldPlayerInfoNotify)
|
||||
|
||||
// PacketWorldDataNotify
|
||||
worldDataNotify := new(proto.WorldDataNotify)
|
||||
worldDataNotify.WorldPropMap = make(map[uint32]*proto.PropValue)
|
||||
// 世界等级
|
||||
worldDataNotify.WorldPropMap[1] = &proto.PropValue{
|
||||
Type: 1,
|
||||
Val: int64(world.worldLevel),
|
||||
Value: &proto.PropValue_Ival{Ival: int64(world.worldLevel)},
|
||||
}
|
||||
// 是否多人游戏
|
||||
worldDataNotify.WorldPropMap[2] = &proto.PropValue{
|
||||
Type: 2,
|
||||
Val: object.ConvBoolToInt64(world.multiplayer),
|
||||
Value: &proto.PropValue_Ival{Ival: object.ConvBoolToInt64(world.multiplayer)},
|
||||
}
|
||||
g.SendMsg(proto.ApiWorldDataNotify, userId, player.ClientSeq, worldDataNotify)
|
||||
|
||||
// PacketPlayerWorldSceneInfoListNotify
|
||||
playerWorldSceneInfoListNotify := new(proto.PlayerWorldSceneInfoListNotify)
|
||||
playerWorldSceneInfoListNotify.InfoList = []*proto.PlayerWorldSceneInfo{
|
||||
{SceneId: 1, IsLocked: false, SceneTagIdList: []uint32{}},
|
||||
{SceneId: 3, IsLocked: false, SceneTagIdList: []uint32{102, 113, 117}},
|
||||
{SceneId: 4, IsLocked: false, SceneTagIdList: []uint32{106, 109, 117}},
|
||||
{SceneId: 5, IsLocked: false, SceneTagIdList: []uint32{}},
|
||||
{SceneId: 6, IsLocked: false, SceneTagIdList: []uint32{}},
|
||||
{SceneId: 7, IsLocked: false, SceneTagIdList: []uint32{}},
|
||||
}
|
||||
xumi := &proto.PlayerWorldSceneInfo{
|
||||
SceneId: 9,
|
||||
IsLocked: false,
|
||||
SceneTagIdList: []uint32{},
|
||||
}
|
||||
for i := 0; i < 3000; i++ {
|
||||
xumi.SceneTagIdList = append(xumi.SceneTagIdList, uint32(i))
|
||||
}
|
||||
playerWorldSceneInfoListNotify.InfoList = append(playerWorldSceneInfoListNotify.InfoList, xumi)
|
||||
g.SendMsg(proto.ApiPlayerWorldSceneInfoListNotify, userId, player.ClientSeq, playerWorldSceneInfoListNotify)
|
||||
|
||||
// SceneForceUnlockNotify
|
||||
g.SendMsg(proto.ApiSceneForceUnlockNotify, userId, player.ClientSeq, new(proto.SceneForceUnlockNotify))
|
||||
|
||||
// PacketHostPlayerNotify
|
||||
hostPlayerNotify := new(proto.HostPlayerNotify)
|
||||
hostPlayerNotify.HostUid = world.owner.PlayerID
|
||||
hostPlayerNotify.HostPeerId = world.owner.PeerId
|
||||
g.SendMsg(proto.ApiHostPlayerNotify, userId, player.ClientSeq, hostPlayerNotify)
|
||||
|
||||
// PacketSceneTimeNotify
|
||||
sceneTimeNotify := new(proto.SceneTimeNotify)
|
||||
sceneTimeNotify.SceneId = player.SceneId
|
||||
sceneTimeNotify.SceneTime = uint64(scene.GetSceneTime())
|
||||
g.SendMsg(proto.ApiSceneTimeNotify, userId, player.ClientSeq, sceneTimeNotify)
|
||||
|
||||
// PacketPlayerGameTimeNotify
|
||||
playerGameTimeNotify := new(proto.PlayerGameTimeNotify)
|
||||
playerGameTimeNotify.GameTime = scene.gameTime
|
||||
playerGameTimeNotify.Uid = player.PlayerID
|
||||
g.SendMsg(proto.ApiPlayerGameTimeNotify, userId, player.ClientSeq, playerGameTimeNotify)
|
||||
|
||||
// PacketPlayerEnterSceneInfoNotify
|
||||
empty := new(proto.AbilitySyncStateInfo)
|
||||
playerEnterSceneInfoNotify := new(proto.PlayerEnterSceneInfoNotify)
|
||||
activeAvatarId := player.TeamConfig.GetActiveAvatarId()
|
||||
playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID)
|
||||
playerEnterSceneInfoNotify.CurAvatarEntityId = playerTeamEntity.avatarEntityMap[activeAvatarId]
|
||||
playerEnterSceneInfoNotify.EnterSceneToken = player.EnterSceneToken
|
||||
playerEnterSceneInfoNotify.TeamEnterInfo = &proto.TeamEnterSceneInfo{
|
||||
TeamEntityId: playerTeamEntity.teamEntityId,
|
||||
TeamAbilityInfo: empty,
|
||||
AbilityControlBlock: new(proto.AbilityControlBlock),
|
||||
}
|
||||
playerEnterSceneInfoNotify.MpLevelEntityInfo = &proto.MPLevelEntityInfo{
|
||||
EntityId: g.worldManager.GetWorldByID(player.WorldId).mpLevelEntityId,
|
||||
AuthorityPeerId: g.worldManager.GetWorldByID(player.WorldId).owner.PeerId,
|
||||
AbilityInfo: empty,
|
||||
}
|
||||
activeTeam := player.TeamConfig.GetActiveTeam()
|
||||
for _, avatarId := range activeTeam.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
avatar := player.AvatarMap[avatarId]
|
||||
avatarEnterSceneInfo := new(proto.AvatarEnterSceneInfo)
|
||||
avatarEnterSceneInfo.AvatarGuid = avatar.Guid
|
||||
avatarEnterSceneInfo.AvatarEntityId = playerTeamEntity.avatarEntityMap[avatarId]
|
||||
avatarEnterSceneInfo.WeaponGuid = avatar.EquipWeapon.Guid
|
||||
avatarEnterSceneInfo.WeaponEntityId = playerTeamEntity.weaponEntityMap[avatar.EquipWeapon.WeaponId]
|
||||
avatarEnterSceneInfo.AvatarAbilityInfo = empty
|
||||
avatarEnterSceneInfo.WeaponAbilityInfo = empty
|
||||
playerEnterSceneInfoNotify.AvatarEnterInfo = append(playerEnterSceneInfoNotify.AvatarEnterInfo, avatarEnterSceneInfo)
|
||||
}
|
||||
g.SendMsg(proto.ApiPlayerEnterSceneInfoNotify, userId, player.ClientSeq, playerEnterSceneInfoNotify)
|
||||
|
||||
// PacketSceneAreaWeatherNotify
|
||||
sceneAreaWeatherNotify := new(proto.SceneAreaWeatherNotify)
|
||||
sceneAreaWeatherNotify.WeatherAreaId = 0
|
||||
sceneAreaWeatherNotify.ClimateType = uint32(constant.ClimateTypeConst.CLIMATE_SUNNY)
|
||||
g.SendMsg(proto.ApiSceneAreaWeatherNotify, userId, player.ClientSeq, sceneAreaWeatherNotify)
|
||||
|
||||
// PacketScenePlayerInfoNotify
|
||||
scenePlayerInfoNotify := new(proto.ScenePlayerInfoNotify)
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
onlinePlayerInfo := new(proto.OnlinePlayerInfo)
|
||||
onlinePlayerInfo.Uid = worldPlayer.PlayerID
|
||||
onlinePlayerInfo.Nickname = worldPlayer.NickName
|
||||
onlinePlayerInfo.PlayerLevel = worldPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]
|
||||
onlinePlayerInfo.MpSettingType = proto.MpSettingType(worldPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE])
|
||||
onlinePlayerInfo.NameCardId = worldPlayer.NameCard
|
||||
onlinePlayerInfo.Signature = worldPlayer.Signature
|
||||
onlinePlayerInfo.ProfilePicture = &proto.ProfilePicture{AvatarId: worldPlayer.HeadImage}
|
||||
onlinePlayerInfo.CurPlayerNumInWorld = uint32(len(world.playerMap))
|
||||
scenePlayerInfoNotify.PlayerInfoList = append(scenePlayerInfoNotify.PlayerInfoList, &proto.ScenePlayerInfo{
|
||||
Uid: worldPlayer.PlayerID,
|
||||
PeerId: worldPlayer.PeerId,
|
||||
Name: worldPlayer.NickName,
|
||||
SceneId: worldPlayer.SceneId,
|
||||
OnlinePlayerInfo: onlinePlayerInfo,
|
||||
})
|
||||
}
|
||||
g.SendMsg(proto.ApiScenePlayerInfoNotify, userId, player.ClientSeq, scenePlayerInfoNotify)
|
||||
|
||||
// PacketSceneTeamUpdateNotify
|
||||
sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(world)
|
||||
g.SendMsg(proto.ApiSceneTeamUpdateNotify, userId, player.ClientSeq, sceneTeamUpdateNotify)
|
||||
|
||||
// PacketSyncTeamEntityNotify
|
||||
syncTeamEntityNotify := new(proto.SyncTeamEntityNotify)
|
||||
syncTeamEntityNotify.SceneId = player.SceneId
|
||||
syncTeamEntityNotify.TeamEntityInfoList = make([]*proto.TeamEntityInfo, 0)
|
||||
if world.multiplayer {
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
if worldPlayer.PlayerID == player.PlayerID {
|
||||
continue
|
||||
}
|
||||
worldPlayerScene := world.GetSceneById(worldPlayer.SceneId)
|
||||
worldPlayerTeamEntity := worldPlayerScene.GetPlayerTeamEntity(worldPlayer.PlayerID)
|
||||
teamEntityInfo := &proto.TeamEntityInfo{
|
||||
TeamEntityId: worldPlayerTeamEntity.teamEntityId,
|
||||
AuthorityPeerId: worldPlayer.PeerId,
|
||||
TeamAbilityInfo: new(proto.AbilitySyncStateInfo),
|
||||
}
|
||||
syncTeamEntityNotify.TeamEntityInfoList = append(syncTeamEntityNotify.TeamEntityInfoList, teamEntityInfo)
|
||||
}
|
||||
}
|
||||
g.SendMsg(proto.ApiSyncTeamEntityNotify, userId, player.ClientSeq, syncTeamEntityNotify)
|
||||
|
||||
// PacketSyncScenePlayTeamEntityNotify
|
||||
syncScenePlayTeamEntityNotify := new(proto.SyncScenePlayTeamEntityNotify)
|
||||
syncScenePlayTeamEntityNotify.SceneId = player.SceneId
|
||||
g.SendMsg(proto.ApiSyncScenePlayTeamEntityNotify, userId, player.ClientSeq, syncScenePlayTeamEntityNotify)
|
||||
|
||||
// PacketSceneInitFinishRsp
|
||||
SceneInitFinishRsp := new(proto.SceneInitFinishRsp)
|
||||
SceneInitFinishRsp.EnterSceneToken = player.EnterSceneToken
|
||||
g.SendMsg(proto.ApiSceneInitFinishRsp, userId, player.ClientSeq, SceneInitFinishRsp)
|
||||
|
||||
player.SceneLoadState = model.SceneInitFinish
|
||||
}
|
||||
|
||||
func (g *GameManager) EnterSceneDoneReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user enter scene done, user id: %v", userId)
|
||||
|
||||
// PacketEnterSceneDoneRsp
|
||||
enterSceneDoneRsp := new(proto.EnterSceneDoneRsp)
|
||||
enterSceneDoneRsp.EnterSceneToken = player.EnterSceneToken
|
||||
g.SendMsg(proto.ApiEnterSceneDoneRsp, userId, player.ClientSeq, enterSceneDoneRsp)
|
||||
|
||||
// PacketPlayerTimeNotify
|
||||
playerTimeNotify := new(proto.PlayerTimeNotify)
|
||||
playerTimeNotify.IsPaused = player.Pause
|
||||
playerTimeNotify.PlayerTime = uint64(player.TotalOnlineTime)
|
||||
playerTimeNotify.ServerTime = uint64(time.Now().UnixMilli())
|
||||
g.SendMsg(proto.ApiPlayerTimeNotify, userId, player.ClientSeq, playerTimeNotify)
|
||||
|
||||
player.SceneLoadState = model.SceneEnterDone
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
|
||||
playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID)
|
||||
activeAvatarId := player.TeamConfig.GetActiveAvatarId()
|
||||
g.AddSceneEntityNotify(player, proto.VisionType_VISION_TYPE_BORN, []uint32{playerTeamEntity.avatarEntityMap[activeAvatarId]}, true)
|
||||
|
||||
// 通过aoi获取场景中在自己周围格子里的全部实体id
|
||||
entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z))
|
||||
g.AddSceneEntityNotify(player, proto.VisionType_VISION_TYPE_MEET, entityIdList, false)
|
||||
}
|
||||
|
||||
func (g *GameManager) PostEnterSceneReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user post enter scene, user id: %v", userId)
|
||||
|
||||
// PacketPostEnterSceneRsp
|
||||
postEnterSceneRsp := new(proto.PostEnterSceneRsp)
|
||||
postEnterSceneRsp.EnterSceneToken = player.EnterSceneToken
|
||||
g.SendMsg(proto.ApiPostEnterSceneRsp, userId, player.ClientSeq, postEnterSceneRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) EnterWorldAreaReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user enter world area, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.EnterWorldAreaReq)
|
||||
|
||||
// PacketEnterWorldAreaRsp
|
||||
enterWorldAreaRsp := new(proto.EnterWorldAreaRsp)
|
||||
enterWorldAreaRsp.AreaType = req.AreaType
|
||||
enterWorldAreaRsp.AreaId = req.AreaId
|
||||
g.SendMsg(proto.ApiEnterWorldAreaRsp, userId, player.ClientSeq, enterWorldAreaRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) ChangeGameTimeReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change game time, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.ChangeGameTimeReq)
|
||||
gameTime := req.GameTime
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
scene.ChangeGameTime(gameTime)
|
||||
|
||||
for _, scenePlayer := range scene.playerMap {
|
||||
// PacketPlayerGameTimeNotify
|
||||
playerGameTimeNotify := new(proto.PlayerGameTimeNotify)
|
||||
playerGameTimeNotify.GameTime = scene.gameTime
|
||||
playerGameTimeNotify.Uid = scenePlayer.PlayerID
|
||||
g.SendMsg(proto.ApiPlayerGameTimeNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, playerGameTimeNotify)
|
||||
}
|
||||
|
||||
// PacketChangeGameTimeRsp
|
||||
changeGameTimeRsp := new(proto.ChangeGameTimeRsp)
|
||||
changeGameTimeRsp.CurGameTime = scene.gameTime
|
||||
g.SendMsg(proto.ApiChangeGameTimeRsp, userId, player.ClientSeq, changeGameTimeRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketPlayerEnterSceneNotify(player *model.Player) *proto.PlayerEnterSceneNotify {
|
||||
player.EnterSceneToken = uint32(random.GetRandomInt32(1000, 99999))
|
||||
playerEnterSceneNotify := new(proto.PlayerEnterSceneNotify)
|
||||
playerEnterSceneNotify.SceneId = player.SceneId
|
||||
playerEnterSceneNotify.Pos = &proto.Vector{X: float32(player.Pos.X), Y: float32(player.Pos.Y), Z: float32(player.Pos.Z)}
|
||||
playerEnterSceneNotify.SceneBeginTime = uint64(time.Now().UnixMilli())
|
||||
playerEnterSceneNotify.Type = proto.EnterType_ENTER_TYPE_SELF
|
||||
playerEnterSceneNotify.TargetUid = player.PlayerID
|
||||
playerEnterSceneNotify.EnterSceneToken = player.EnterSceneToken
|
||||
playerEnterSceneNotify.WorldLevel = player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL]
|
||||
playerEnterSceneNotify.EnterReason = uint32(constant.EnterReasonConst.Login)
|
||||
// 刚登录进入场景的时候才为true
|
||||
playerEnterSceneNotify.IsFirstLoginEnterScene = true
|
||||
playerEnterSceneNotify.WorldType = 1
|
||||
playerEnterSceneNotify.SceneTransaction = strconv.Itoa(int(player.SceneId)) + "-" +
|
||||
strconv.Itoa(int(player.PlayerID)) + "-" +
|
||||
strconv.Itoa(int(time.Now().Unix())) + "-" +
|
||||
"18402"
|
||||
return playerEnterSceneNotify
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketPlayerEnterSceneNotifyTp(
|
||||
player *model.Player,
|
||||
enterType proto.EnterType,
|
||||
enterReason uint32,
|
||||
prevSceneId uint32,
|
||||
prevPos *model.Vector,
|
||||
) *proto.PlayerEnterSceneNotify {
|
||||
return g.PacketPlayerEnterSceneNotifyMp(player, player, enterType, enterReason, prevSceneId, prevPos)
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketPlayerEnterSceneNotifyMp(
|
||||
player *model.Player,
|
||||
targetPlayer *model.Player,
|
||||
enterType proto.EnterType,
|
||||
enterReason uint32,
|
||||
prevSceneId uint32,
|
||||
prevPos *model.Vector,
|
||||
) *proto.PlayerEnterSceneNotify {
|
||||
player.EnterSceneToken = uint32(random.GetRandomInt32(1000, 99999))
|
||||
playerEnterSceneNotify := new(proto.PlayerEnterSceneNotify)
|
||||
playerEnterSceneNotify.PrevSceneId = prevSceneId
|
||||
playerEnterSceneNotify.PrevPos = &proto.Vector{X: float32(prevPos.X), Y: float32(prevPos.Y), Z: float32(prevPos.Z)}
|
||||
playerEnterSceneNotify.SceneId = player.SceneId
|
||||
playerEnterSceneNotify.Pos = &proto.Vector{X: float32(player.Pos.X), Y: float32(player.Pos.Y), Z: float32(player.Pos.Z)}
|
||||
playerEnterSceneNotify.SceneBeginTime = uint64(time.Now().UnixMilli())
|
||||
playerEnterSceneNotify.Type = enterType
|
||||
playerEnterSceneNotify.TargetUid = targetPlayer.PlayerID
|
||||
playerEnterSceneNotify.EnterSceneToken = player.EnterSceneToken
|
||||
playerEnterSceneNotify.WorldLevel = targetPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL]
|
||||
playerEnterSceneNotify.EnterReason = enterReason
|
||||
playerEnterSceneNotify.WorldType = 1
|
||||
playerEnterSceneNotify.SceneTransaction = strconv.Itoa(int(player.SceneId)) + "-" +
|
||||
strconv.Itoa(int(targetPlayer.PlayerID)) + "-" +
|
||||
strconv.Itoa(int(time.Now().Unix())) + "-" +
|
||||
"18402"
|
||||
|
||||
//playerEnterSceneNotify.SceneTagIdList = []uint32{102, 107, 109, 113, 117}
|
||||
playerEnterSceneNotify.SceneTagIdList = make([]uint32, 0)
|
||||
for sceneTagId := uint32(0); sceneTagId < 3000; sceneTagId++ {
|
||||
playerEnterSceneNotify.SceneTagIdList = append(playerEnterSceneNotify.SceneTagIdList, sceneTagId)
|
||||
}
|
||||
|
||||
return playerEnterSceneNotify
|
||||
}
|
||||
|
||||
func (g *GameManager) AddSceneEntityNotifyToPlayer(player *model.Player, visionType proto.VisionType, entityList []*proto.SceneEntityInfo) {
|
||||
// PacketSceneEntityAppearNotify
|
||||
sceneEntityAppearNotify := new(proto.SceneEntityAppearNotify)
|
||||
sceneEntityAppearNotify.AppearType = visionType
|
||||
sceneEntityAppearNotify.EntityList = entityList
|
||||
g.SendMsg(proto.ApiSceneEntityAppearNotify, player.PlayerID, player.ClientSeq, sceneEntityAppearNotify)
|
||||
logger.LOG.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v",
|
||||
player.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList))
|
||||
}
|
||||
|
||||
func (g *GameManager) AddSceneEntityNotifyBroadcast(scene *Scene, visionType proto.VisionType, entityList []*proto.SceneEntityInfo) {
|
||||
// PacketSceneEntityAppearNotify
|
||||
sceneEntityAppearNotify := new(proto.SceneEntityAppearNotify)
|
||||
sceneEntityAppearNotify.AppearType = visionType
|
||||
sceneEntityAppearNotify.EntityList = entityList
|
||||
for _, scenePlayer := range scene.playerMap {
|
||||
g.SendMsg(proto.ApiSceneEntityAppearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityAppearNotify)
|
||||
logger.LOG.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v",
|
||||
scenePlayer.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList))
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) RemoveSceneEntityNotifyToPlayer(player *model.Player, entityIdList []uint32) {
|
||||
// PacketSceneEntityDisappearNotify
|
||||
sceneEntityDisappearNotify := new(proto.SceneEntityDisappearNotify)
|
||||
sceneEntityDisappearNotify.EntityList = entityIdList
|
||||
sceneEntityDisappearNotify.DisappearType = proto.VisionType_VISION_TYPE_REMOVE
|
||||
g.SendMsg(proto.ApiSceneEntityDisappearNotify, player.PlayerID, player.ClientSeq, sceneEntityDisappearNotify)
|
||||
logger.LOG.Debug("SceneEntityDisappearNotify, uid: %v, type: %v, len: %v",
|
||||
player.PlayerID, sceneEntityDisappearNotify.DisappearType, len(sceneEntityDisappearNotify.EntityList))
|
||||
}
|
||||
|
||||
func (g *GameManager) RemoveSceneEntityNotifyBroadcast(scene *Scene, entityIdList []uint32) {
|
||||
// PacketSceneEntityDisappearNotify
|
||||
sceneEntityDisappearNotify := new(proto.SceneEntityDisappearNotify)
|
||||
sceneEntityDisappearNotify.EntityList = entityIdList
|
||||
sceneEntityDisappearNotify.DisappearType = proto.VisionType_VISION_TYPE_REMOVE
|
||||
for _, scenePlayer := range scene.playerMap {
|
||||
g.SendMsg(proto.ApiSceneEntityDisappearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityDisappearNotify)
|
||||
logger.LOG.Debug("SceneEntityDisappearNotify, uid: %v, type: %v, len: %v",
|
||||
scenePlayer.PlayerID, sceneEntityDisappearNotify.DisappearType, len(sceneEntityDisappearNotify.EntityList))
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) AddSceneEntityNotify(player *model.Player, visionType proto.VisionType, entityIdList []uint32, broadcast bool) {
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
entityList := make([]*proto.SceneEntityInfo, 0)
|
||||
for _, entityId := range entityIdList {
|
||||
entity := scene.entityMap[entityId]
|
||||
if entity == nil {
|
||||
logger.LOG.Error("get entity is nil, entityId: %v", entityId)
|
||||
continue
|
||||
}
|
||||
switch entity.entityType {
|
||||
case uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_AVATAR):
|
||||
if visionType == proto.VisionType_VISION_TYPE_MEET && entity.avatarEntity.uid == player.PlayerID {
|
||||
continue
|
||||
}
|
||||
scenePlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid)
|
||||
if scenePlayer == nil {
|
||||
logger.LOG.Error("get scene player is nil, world id: %v, scene id: %v", world.id, scene.id)
|
||||
continue
|
||||
}
|
||||
if scenePlayer.SceneLoadState != model.SceneEnterDone {
|
||||
continue
|
||||
}
|
||||
if entity.avatarEntity.avatarId != scenePlayer.TeamConfig.GetActiveAvatarId() {
|
||||
continue
|
||||
}
|
||||
sceneEntityInfoAvatar := g.PacketSceneEntityInfoAvatar(scene, scenePlayer, scenePlayer.TeamConfig.GetActiveAvatarId())
|
||||
entityList = append(entityList, sceneEntityInfoAvatar)
|
||||
case uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_WEAPON):
|
||||
case uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_MONSTER):
|
||||
sceneEntityInfoMonster := g.PacketSceneEntityInfoMonster(scene, entity.id)
|
||||
entityList = append(entityList, sceneEntityInfoMonster)
|
||||
case uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET):
|
||||
sceneEntityInfoGadget := g.PacketSceneEntityInfoGadget(scene, entity.id)
|
||||
entityList = append(entityList, sceneEntityInfoGadget)
|
||||
}
|
||||
}
|
||||
if broadcast {
|
||||
g.AddSceneEntityNotifyBroadcast(scene, visionType, entityList)
|
||||
} else {
|
||||
g.AddSceneEntityNotifyToPlayer(player, visionType, entityList)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketFightPropMapToPbFightPropList(fightPropMap map[uint32]float32) []*proto.FightPropPair {
|
||||
fightPropList := []*proto.FightPropPair{
|
||||
{
|
||||
PropType: uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_HP),
|
||||
PropValue: fightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_HP)],
|
||||
},
|
||||
{
|
||||
PropType: uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_ATTACK),
|
||||
PropValue: fightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_ATTACK)],
|
||||
},
|
||||
{
|
||||
PropType: uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_DEFENSE),
|
||||
PropValue: fightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_DEFENSE)],
|
||||
},
|
||||
{
|
||||
PropType: uint32(constant.FightPropertyConst.FIGHT_PROP_CRITICAL),
|
||||
PropValue: fightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CRITICAL)],
|
||||
},
|
||||
{
|
||||
PropType: uint32(constant.FightPropertyConst.FIGHT_PROP_CRITICAL_HURT),
|
||||
PropValue: fightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CRITICAL_HURT)],
|
||||
},
|
||||
{
|
||||
PropType: uint32(constant.FightPropertyConst.FIGHT_PROP_CHARGE_EFFICIENCY),
|
||||
PropValue: fightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CHARGE_EFFICIENCY)],
|
||||
},
|
||||
{
|
||||
PropType: uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP),
|
||||
PropValue: fightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)],
|
||||
},
|
||||
{
|
||||
PropType: uint32(constant.FightPropertyConst.FIGHT_PROP_MAX_HP),
|
||||
PropValue: fightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_MAX_HP)],
|
||||
},
|
||||
{
|
||||
PropType: uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_ATTACK),
|
||||
PropValue: fightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_ATTACK)],
|
||||
},
|
||||
{
|
||||
PropType: uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_DEFENSE),
|
||||
PropValue: fightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_DEFENSE)],
|
||||
},
|
||||
}
|
||||
return fightPropList
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketSceneEntityInfoAvatar(scene *Scene, player *model.Player, avatarId uint32) *proto.SceneEntityInfo {
|
||||
playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID)
|
||||
entity := scene.GetEntity(playerTeamEntity.avatarEntityMap[avatarId])
|
||||
if entity == nil {
|
||||
return new(proto.SceneEntityInfo)
|
||||
}
|
||||
sceneEntityInfo := &proto.SceneEntityInfo{
|
||||
EntityType: proto.ProtEntityType_PROT_ENTITY_TYPE_AVATAR,
|
||||
EntityId: entity.id,
|
||||
MotionInfo: &proto.MotionInfo{
|
||||
Pos: &proto.Vector{
|
||||
X: float32(entity.pos.X),
|
||||
Y: float32(entity.pos.Y),
|
||||
Z: float32(entity.pos.Z),
|
||||
},
|
||||
Rot: &proto.Vector{
|
||||
X: float32(entity.rot.X),
|
||||
Y: float32(entity.rot.Y),
|
||||
Z: float32(entity.rot.Z),
|
||||
},
|
||||
Speed: &proto.Vector{},
|
||||
State: proto.MotionState(entity.moveState),
|
||||
},
|
||||
PropList: []*proto.PropPair{{Type: uint32(constant.PlayerPropertyConst.PROP_LEVEL), PropValue: &proto.PropValue{
|
||||
Type: uint32(constant.PlayerPropertyConst.PROP_LEVEL),
|
||||
Value: &proto.PropValue_Ival{Ival: int64(entity.level)},
|
||||
Val: int64(entity.level),
|
||||
}}},
|
||||
FightPropList: g.PacketFightPropMapToPbFightPropList(entity.fightProp),
|
||||
LifeState: 1,
|
||||
AnimatorParaList: make([]*proto.AnimatorParameterValueInfoPair, 0),
|
||||
Entity: &proto.SceneEntityInfo_Avatar{
|
||||
Avatar: g.PacketSceneAvatarInfo(scene, player, avatarId),
|
||||
},
|
||||
EntityClientData: new(proto.EntityClientData),
|
||||
EntityAuthorityInfo: &proto.EntityAuthorityInfo{
|
||||
AbilityInfo: new(proto.AbilitySyncStateInfo),
|
||||
RendererChangedInfo: new(proto.EntityRendererChangedInfo),
|
||||
AiInfo: &proto.SceneEntityAiInfo{
|
||||
IsAiOpen: true,
|
||||
BornPos: new(proto.Vector),
|
||||
},
|
||||
BornPos: new(proto.Vector),
|
||||
},
|
||||
LastMoveSceneTimeMs: entity.lastMoveSceneTimeMs,
|
||||
LastMoveReliableSeq: entity.lastMoveReliableSeq,
|
||||
}
|
||||
return sceneEntityInfo
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketSceneEntityInfoMonster(scene *Scene, entityId uint32) *proto.SceneEntityInfo {
|
||||
entity := scene.GetEntity(entityId)
|
||||
if entity == nil {
|
||||
return new(proto.SceneEntityInfo)
|
||||
}
|
||||
pos := &proto.Vector{
|
||||
X: float32(entity.pos.X),
|
||||
Y: float32(entity.pos.Y),
|
||||
Z: float32(entity.pos.Z),
|
||||
}
|
||||
sceneEntityInfo := &proto.SceneEntityInfo{
|
||||
EntityType: proto.ProtEntityType_PROT_ENTITY_TYPE_MONSTER,
|
||||
EntityId: entity.id,
|
||||
MotionInfo: &proto.MotionInfo{
|
||||
Pos: pos,
|
||||
Rot: &proto.Vector{
|
||||
X: float32(entity.rot.X),
|
||||
Y: float32(entity.rot.Y),
|
||||
Z: float32(entity.rot.Z),
|
||||
},
|
||||
Speed: &proto.Vector{},
|
||||
State: proto.MotionState(entity.moveState),
|
||||
},
|
||||
PropList: []*proto.PropPair{{Type: uint32(constant.PlayerPropertyConst.PROP_LEVEL), PropValue: &proto.PropValue{
|
||||
Type: uint32(constant.PlayerPropertyConst.PROP_LEVEL),
|
||||
Value: &proto.PropValue_Ival{Ival: int64(entity.level)},
|
||||
Val: int64(entity.level),
|
||||
}}},
|
||||
FightPropList: g.PacketFightPropMapToPbFightPropList(entity.fightProp),
|
||||
LifeState: 1,
|
||||
AnimatorParaList: make([]*proto.AnimatorParameterValueInfoPair, 0),
|
||||
Entity: &proto.SceneEntityInfo_Monster{
|
||||
Monster: g.PacketSceneMonsterInfo(),
|
||||
},
|
||||
EntityClientData: new(proto.EntityClientData),
|
||||
EntityAuthorityInfo: &proto.EntityAuthorityInfo{
|
||||
AbilityInfo: new(proto.AbilitySyncStateInfo),
|
||||
RendererChangedInfo: new(proto.EntityRendererChangedInfo),
|
||||
AiInfo: &proto.SceneEntityAiInfo{
|
||||
IsAiOpen: true,
|
||||
BornPos: pos,
|
||||
},
|
||||
BornPos: pos,
|
||||
},
|
||||
}
|
||||
return sceneEntityInfo
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketSceneEntityInfoGadget(scene *Scene, entityId uint32) *proto.SceneEntityInfo {
|
||||
entity := scene.GetEntity(entityId)
|
||||
if entity == nil {
|
||||
return new(proto.SceneEntityInfo)
|
||||
}
|
||||
sceneEntityInfo := &proto.SceneEntityInfo{
|
||||
EntityType: proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET,
|
||||
EntityId: entity.id,
|
||||
MotionInfo: &proto.MotionInfo{
|
||||
Pos: &proto.Vector{
|
||||
X: float32(entity.pos.X),
|
||||
Y: float32(entity.pos.Y),
|
||||
Z: float32(entity.pos.Z),
|
||||
},
|
||||
Rot: &proto.Vector{
|
||||
X: float32(entity.rot.X),
|
||||
Y: float32(entity.rot.Y),
|
||||
Z: float32(entity.rot.Z),
|
||||
},
|
||||
Speed: &proto.Vector{},
|
||||
State: proto.MotionState(entity.moveState),
|
||||
},
|
||||
PropList: []*proto.PropPair{{Type: uint32(constant.PlayerPropertyConst.PROP_LEVEL), PropValue: &proto.PropValue{
|
||||
Type: uint32(constant.PlayerPropertyConst.PROP_LEVEL),
|
||||
Value: &proto.PropValue_Ival{Ival: int64(1)},
|
||||
Val: int64(1),
|
||||
}}},
|
||||
FightPropList: g.PacketFightPropMapToPbFightPropList(entity.fightProp),
|
||||
LifeState: 1,
|
||||
AnimatorParaList: make([]*proto.AnimatorParameterValueInfoPair, 0),
|
||||
Entity: &proto.SceneEntityInfo_Gadget{
|
||||
Gadget: g.PacketSceneGadgetInfo(entity.gadgetEntity.gatherId),
|
||||
},
|
||||
EntityClientData: new(proto.EntityClientData),
|
||||
EntityAuthorityInfo: &proto.EntityAuthorityInfo{
|
||||
AbilityInfo: new(proto.AbilitySyncStateInfo),
|
||||
RendererChangedInfo: new(proto.EntityRendererChangedInfo),
|
||||
AiInfo: &proto.SceneEntityAiInfo{
|
||||
IsAiOpen: true,
|
||||
BornPos: new(proto.Vector),
|
||||
},
|
||||
BornPos: new(proto.Vector),
|
||||
},
|
||||
}
|
||||
return sceneEntityInfo
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketSceneAvatarInfo(scene *Scene, player *model.Player, avatarId uint32) *proto.SceneAvatarInfo {
|
||||
activeAvatarId := player.TeamConfig.GetActiveAvatarId()
|
||||
activeAvatar := player.AvatarMap[activeAvatarId]
|
||||
playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID)
|
||||
equipIdList := make([]uint32, 0)
|
||||
weapon := player.AvatarMap[avatarId].EquipWeapon
|
||||
equipIdList = append(equipIdList, weapon.ItemId)
|
||||
for _, reliquary := range player.AvatarMap[avatarId].EquipReliquaryList {
|
||||
equipIdList = append(equipIdList, reliquary.ItemId)
|
||||
}
|
||||
sceneAvatarInfo := &proto.SceneAvatarInfo{
|
||||
Uid: player.PlayerID,
|
||||
AvatarId: avatarId,
|
||||
Guid: player.AvatarMap[avatarId].Guid,
|
||||
PeerId: player.PeerId,
|
||||
EquipIdList: equipIdList,
|
||||
SkillDepotId: player.AvatarMap[avatarId].SkillDepotId,
|
||||
Weapon: &proto.SceneWeaponInfo{
|
||||
EntityId: playerTeamEntity.weaponEntityMap[activeAvatar.EquipWeapon.WeaponId],
|
||||
GadgetId: uint32(gdc.CONF.ItemDataMap[int32(weapon.ItemId)].GadgetId),
|
||||
ItemId: weapon.ItemId,
|
||||
Guid: weapon.Guid,
|
||||
Level: uint32(weapon.Level),
|
||||
AbilityInfo: new(proto.AbilitySyncStateInfo),
|
||||
},
|
||||
ReliquaryList: nil,
|
||||
SkillLevelMap: player.AvatarMap[avatarId].SkillLevelMap,
|
||||
WearingFlycloakId: player.AvatarMap[avatarId].FlyCloak,
|
||||
CostumeId: player.AvatarMap[avatarId].Costume,
|
||||
BornTime: uint32(player.AvatarMap[avatarId].BornTime),
|
||||
TeamResonanceList: make([]uint32, 0),
|
||||
}
|
||||
for id := range player.TeamConfig.TeamResonances {
|
||||
sceneAvatarInfo.TeamResonanceList = append(sceneAvatarInfo.TeamResonanceList, uint32(id))
|
||||
}
|
||||
return sceneAvatarInfo
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketSceneMonsterInfo() *proto.SceneMonsterInfo {
|
||||
sceneMonsterInfo := &proto.SceneMonsterInfo{
|
||||
MonsterId: 20011301,
|
||||
AuthorityPeerId: 1,
|
||||
BornType: proto.MonsterBornType_MONSTER_BORN_TYPE_DEFAULT,
|
||||
BlockId: 3001,
|
||||
TitleId: 3001,
|
||||
SpecialNameId: 40,
|
||||
}
|
||||
return sceneMonsterInfo
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketSceneGadgetInfo(gatherId uint32) *proto.SceneGadgetInfo {
|
||||
gather := gdc.CONF.GatherDataMap[int32(gatherId)]
|
||||
sceneGadgetInfo := &proto.SceneGadgetInfo{
|
||||
GadgetId: uint32(gather.GadgetId),
|
||||
//GroupId: 133003011,
|
||||
//ConfigId: 11001,
|
||||
GadgetState: 0,
|
||||
IsEnableInteract: false,
|
||||
AuthorityPeerId: 1,
|
||||
Content: &proto.SceneGadgetInfo_GatherGadget{
|
||||
GatherGadget: &proto.GatherGadgetInfo{
|
||||
ItemId: uint32(gather.ItemId),
|
||||
IsForbidGuest: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
return sceneGadgetInfo
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketDelTeamEntityNotify(scene *Scene, player *model.Player) *proto.DelTeamEntityNotify {
|
||||
delTeamEntityNotify := new(proto.DelTeamEntityNotify)
|
||||
delTeamEntityNotify.SceneId = player.SceneId
|
||||
playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID)
|
||||
delTeamEntityNotify.DelEntityIdList = []uint32{playerTeamEntity.teamEntityId}
|
||||
return delTeamEntityNotify
|
||||
}
|
||||
128
service/game-hk4e/game/user_shop.go
Normal file
128
service/game-hk4e/game/user_shop.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (g *GameManager) GetShopmallDataReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get shop mall, userId: %v", userId)
|
||||
|
||||
// PacketGetShopmallDataRsp
|
||||
getShopmallDataRsp := new(proto.GetShopmallDataRsp)
|
||||
getShopmallDataRsp.ShopTypeList = []uint32{900, 1052, 902, 1001, 903}
|
||||
g.SendMsg(proto.ApiGetShopmallDataRsp, userId, player.ClientSeq, getShopmallDataRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) GetShopReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get shop, userId: %v", userId)
|
||||
req := payloadMsg.(*proto.GetShopReq)
|
||||
shopType := req.ShopType
|
||||
|
||||
if shopType != 1001 {
|
||||
return
|
||||
}
|
||||
|
||||
nextRefreshTime := uint32(time.Now().Add(time.Hour * 24 * 30).Unix())
|
||||
|
||||
// PacketGetShopRsp
|
||||
getShopRsp := new(proto.GetShopRsp)
|
||||
getShopRsp.Shop = &proto.Shop{
|
||||
GoodsList: []*proto.ShopGoods{
|
||||
{
|
||||
MinLevel: 1,
|
||||
EndTime: 2051193600,
|
||||
Hcoin: 160,
|
||||
GoodsId: 102001,
|
||||
NextRefreshTime: nextRefreshTime,
|
||||
MaxLevel: 99,
|
||||
BeginTime: 1575129600,
|
||||
GoodsItem: &proto.ItemParam{
|
||||
ItemId: 223,
|
||||
Count: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
MinLevel: 1,
|
||||
EndTime: 2051193600,
|
||||
Hcoin: 160,
|
||||
GoodsId: 102002,
|
||||
NextRefreshTime: nextRefreshTime,
|
||||
MaxLevel: 99,
|
||||
BeginTime: 1575129600,
|
||||
GoodsItem: &proto.ItemParam{
|
||||
ItemId: 224,
|
||||
Count: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
NextRefreshTime: nextRefreshTime,
|
||||
ShopType: 1001,
|
||||
}
|
||||
g.SendMsg(proto.ApiGetShopRsp, userId, player.ClientSeq, getShopRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) BuyGoodsReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user buy goods, userId: %v", userId)
|
||||
req := payloadMsg.(*proto.BuyGoodsReq)
|
||||
buyItemId := req.Goods.GoodsItem.ItemId
|
||||
buyItemCount := req.BuyCount
|
||||
costHcoinCount := req.Goods.Hcoin * buyItemCount
|
||||
|
||||
if buyItemId != 223 && buyItemId != 224 {
|
||||
return
|
||||
}
|
||||
|
||||
if player.GetItemCount(201) < costHcoinCount {
|
||||
return
|
||||
}
|
||||
g.CostUserItem(userId, []*UserItem{{
|
||||
ItemId: 201,
|
||||
ChangeCount: costHcoinCount,
|
||||
}})
|
||||
|
||||
g.AddUserItem(userId, []*UserItem{{
|
||||
ItemId: buyItemId,
|
||||
ChangeCount: buyItemCount,
|
||||
}}, true, constant.ActionReasonConst.Shop)
|
||||
req.Goods.BoughtNum = player.GetItemCount(buyItemId)
|
||||
|
||||
// PacketBuyGoodsRsp
|
||||
buyGoodsRsp := new(proto.BuyGoodsRsp)
|
||||
buyGoodsRsp.ShopType = req.ShopType
|
||||
buyGoodsRsp.BuyCount = req.BuyCount
|
||||
buyGoodsRsp.GoodsList = []*proto.ShopGoods{req.Goods}
|
||||
g.SendMsg(proto.ApiBuyGoodsRsp, userId, player.ClientSeq, buyGoodsRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) McoinExchangeHcoinReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user mcoin exchange hcoin, userId: %v", userId)
|
||||
req := payloadMsg.(*proto.McoinExchangeHcoinReq)
|
||||
if req.Hcoin != req.McoinCost {
|
||||
return
|
||||
}
|
||||
count := req.Hcoin
|
||||
|
||||
if player.GetItemCount(203) < count {
|
||||
return
|
||||
}
|
||||
g.CostUserItem(userId, []*UserItem{{
|
||||
ItemId: 203,
|
||||
ChangeCount: count,
|
||||
}})
|
||||
|
||||
g.AddUserItem(userId, []*UserItem{{
|
||||
ItemId: 201,
|
||||
ChangeCount: count,
|
||||
}}, false, 0)
|
||||
|
||||
// PacketMcoinExchangeHcoinRsp
|
||||
mcoinExchangeHcoinRsp := new(proto.McoinExchangeHcoinRsp)
|
||||
mcoinExchangeHcoinRsp.Hcoin = req.Hcoin
|
||||
mcoinExchangeHcoinRsp.McoinCost = req.McoinCost
|
||||
g.SendMsg(proto.ApiMcoinExchangeHcoinRsp, userId, player.ClientSeq, mcoinExchangeHcoinRsp)
|
||||
}
|
||||
334
service/game-hk4e/game/user_social.go
Normal file
334
service/game-hk4e/game/user_social.go
Normal file
@@ -0,0 +1,334 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/common/utils/object"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"regexp"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func (g *GameManager) GetPlayerSocialDetailReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get player social detail, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.GetPlayerSocialDetailReq)
|
||||
targetUid := req.Uid
|
||||
|
||||
// PacketGetPlayerSocialDetailRsp
|
||||
getPlayerSocialDetailRsp := new(proto.GetPlayerSocialDetailRsp)
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := g.userManager.LoadTempOfflineUserSync(targetUid)
|
||||
if targetPlayer != nil {
|
||||
socialDetail := new(proto.SocialDetail)
|
||||
socialDetail.Uid = targetPlayer.PlayerID
|
||||
socialDetail.ProfilePicture = &proto.ProfilePicture{AvatarId: targetPlayer.HeadImage}
|
||||
socialDetail.Nickname = targetPlayer.NickName
|
||||
socialDetail.Signature = targetPlayer.Signature
|
||||
socialDetail.Level = targetPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL]
|
||||
socialDetail.Birthday = &proto.Birthday{Month: 2, Day: 13}
|
||||
socialDetail.WorldLevel = targetPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL]
|
||||
socialDetail.NameCardId = targetPlayer.NameCard
|
||||
socialDetail.IsShowAvatar = false
|
||||
socialDetail.FinishAchievementNum = 0
|
||||
_, exist := player.FriendList[targetPlayer.PlayerID]
|
||||
socialDetail.IsFriend = exist
|
||||
getPlayerSocialDetailRsp.DetailData = socialDetail
|
||||
} else {
|
||||
getPlayerSocialDetailRsp.Retcode = int32(proto.Retcode_RETCODE_RET_PLAYER_NOT_EXIST)
|
||||
}
|
||||
g.SendMsg(proto.ApiGetPlayerSocialDetailRsp, userId, player.ClientSeq, getPlayerSocialDetailRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) SetPlayerBirthdayReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user set birthday, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.SetPlayerBirthdayReq)
|
||||
_ = req
|
||||
}
|
||||
|
||||
func (g *GameManager) SetNameCardReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change name card, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.SetNameCardReq)
|
||||
nameCardId := req.NameCardId
|
||||
exist := false
|
||||
for _, nameCard := range player.NameCardList {
|
||||
if nameCard == nameCardId {
|
||||
exist = true
|
||||
}
|
||||
}
|
||||
if !exist {
|
||||
logger.LOG.Error("name card not exist, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
player.NameCard = nameCardId
|
||||
|
||||
// PacketSetNameCardRsp
|
||||
setNameCardRsp := new(proto.SetNameCardRsp)
|
||||
setNameCardRsp.NameCardId = nameCardId
|
||||
g.SendMsg(proto.ApiSetNameCardRsp, userId, player.ClientSeq, setNameCardRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) SetPlayerSignatureReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change signature, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.SetPlayerSignatureReq)
|
||||
signature := req.Signature
|
||||
|
||||
// PacketSetPlayerSignatureRsp
|
||||
setPlayerSignatureRsp := new(proto.SetPlayerSignatureRsp)
|
||||
if !object.IsUtf8String(signature) {
|
||||
setPlayerSignatureRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SIGNATURE_ILLEGAL)
|
||||
} else if utf8.RuneCountInString(signature) > 50 {
|
||||
setPlayerSignatureRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SIGNATURE_ILLEGAL)
|
||||
} else {
|
||||
player.Signature = signature
|
||||
setPlayerSignatureRsp.Signature = player.Signature
|
||||
}
|
||||
g.SendMsg(proto.ApiSetPlayerSignatureRsp, userId, player.ClientSeq, setPlayerSignatureRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) SetPlayerNameReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change nickname, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.SetPlayerNameReq)
|
||||
nickName := req.NickName
|
||||
|
||||
// PacketSetPlayerNameRsp
|
||||
setPlayerNameRsp := new(proto.SetPlayerNameRsp)
|
||||
if len(nickName) == 0 {
|
||||
setPlayerNameRsp.Retcode = int32(proto.Retcode_RETCODE_RET_NICKNAME_IS_EMPTY)
|
||||
} else if !object.IsUtf8String(nickName) {
|
||||
setPlayerNameRsp.Retcode = int32(proto.Retcode_RETCODE_RET_NICKNAME_UTF8_ERROR)
|
||||
} else if utf8.RuneCountInString(nickName) > 14 {
|
||||
setPlayerNameRsp.Retcode = int32(proto.Retcode_RETCODE_RET_NICKNAME_TOO_LONG)
|
||||
} else if len(regexp.MustCompile(`\d`).FindAllString(nickName, -1)) > 6 {
|
||||
setPlayerNameRsp.Retcode = int32(proto.Retcode_RETCODE_RET_NICKNAME_TOO_MANY_DIGITS)
|
||||
} else {
|
||||
player.NickName = nickName
|
||||
setPlayerNameRsp.NickName = player.NickName
|
||||
}
|
||||
g.SendMsg(proto.ApiSetPlayerNameRsp, userId, player.ClientSeq, setPlayerNameRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) SetPlayerHeadImageReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change head image, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.SetPlayerHeadImageReq)
|
||||
avatarId := req.AvatarId
|
||||
_, exist := player.AvatarMap[avatarId]
|
||||
if !exist {
|
||||
logger.LOG.Error("the head img of the avatar not exist, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
player.HeadImage = avatarId
|
||||
|
||||
// PacketSetPlayerHeadImageRsp
|
||||
setPlayerHeadImageRsp := new(proto.SetPlayerHeadImageRsp)
|
||||
setPlayerHeadImageRsp.ProfilePicture = &proto.ProfilePicture{AvatarId: player.HeadImage}
|
||||
g.SendMsg(proto.ApiSetPlayerHeadImageRsp, userId, player.ClientSeq, setPlayerHeadImageRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) GetAllUnlockNameCardReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get all unlock name card, user id: %v", userId)
|
||||
|
||||
// PacketGetAllUnlockNameCardRsp
|
||||
getAllUnlockNameCardRsp := new(proto.GetAllUnlockNameCardRsp)
|
||||
getAllUnlockNameCardRsp.NameCardList = player.NameCardList
|
||||
g.SendMsg(proto.ApiGetAllUnlockNameCardRsp, userId, player.ClientSeq, getAllUnlockNameCardRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) GetPlayerFriendListReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get friend list, user id: %v", userId)
|
||||
|
||||
// PacketGetPlayerFriendListRsp
|
||||
getPlayerFriendListRsp := new(proto.GetPlayerFriendListRsp)
|
||||
getPlayerFriendListRsp.FriendList = make([]*proto.FriendBrief, 0)
|
||||
for uid := range player.FriendList {
|
||||
// TODO 同步阻塞待优化
|
||||
var onlineState proto.FriendOnlineState
|
||||
online := g.userManager.GetUserOnlineState(uid)
|
||||
if online {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE
|
||||
} else {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_FREIEND_DISCONNECT
|
||||
}
|
||||
friendPlayer := g.userManager.LoadTempOfflineUserSync(uid)
|
||||
if friendPlayer == nil {
|
||||
logger.LOG.Error("target player is nil, userId: %v", userId)
|
||||
continue
|
||||
}
|
||||
friendBrief := &proto.FriendBrief{
|
||||
Uid: friendPlayer.PlayerID,
|
||||
Nickname: friendPlayer.NickName,
|
||||
Level: friendPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: friendPlayer.HeadImage},
|
||||
WorldLevel: friendPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
Signature: friendPlayer.Signature,
|
||||
OnlineState: onlineState,
|
||||
IsMpModeAvailable: true,
|
||||
LastActiveTime: player.OfflineTime,
|
||||
NameCardId: friendPlayer.NameCard,
|
||||
Param: (uint32(time.Now().Unix()) - player.OfflineTime) / 3600 / 24,
|
||||
IsGameSource: true,
|
||||
PlatformType: proto.PlatformType_PLATFORM_TYPE_PC,
|
||||
}
|
||||
getPlayerFriendListRsp.FriendList = append(getPlayerFriendListRsp.FriendList, friendBrief)
|
||||
}
|
||||
g.SendMsg(proto.ApiGetPlayerFriendListRsp, userId, player.ClientSeq, getPlayerFriendListRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) GetPlayerAskFriendListReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get friend apply list, user id: %v", userId)
|
||||
|
||||
// PacketGetPlayerAskFriendListRsp
|
||||
getPlayerAskFriendListRsp := new(proto.GetPlayerAskFriendListRsp)
|
||||
getPlayerAskFriendListRsp.AskFriendList = make([]*proto.FriendBrief, 0)
|
||||
for uid := range player.FriendApplyList {
|
||||
// TODO 同步阻塞待优化
|
||||
var onlineState proto.FriendOnlineState
|
||||
online := g.userManager.GetUserOnlineState(uid)
|
||||
if online {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE
|
||||
} else {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_FREIEND_DISCONNECT
|
||||
}
|
||||
friendPlayer := g.userManager.LoadTempOfflineUserSync(uid)
|
||||
if friendPlayer == nil {
|
||||
logger.LOG.Error("target player is nil, userId: %v", userId)
|
||||
continue
|
||||
}
|
||||
friendBrief := &proto.FriendBrief{
|
||||
Uid: friendPlayer.PlayerID,
|
||||
Nickname: friendPlayer.NickName,
|
||||
Level: friendPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: friendPlayer.HeadImage},
|
||||
WorldLevel: friendPlayer.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
Signature: friendPlayer.Signature,
|
||||
OnlineState: onlineState,
|
||||
IsMpModeAvailable: true,
|
||||
LastActiveTime: player.OfflineTime,
|
||||
NameCardId: friendPlayer.NameCard,
|
||||
Param: (uint32(time.Now().Unix()) - player.OfflineTime) / 3600 / 24,
|
||||
IsGameSource: true,
|
||||
PlatformType: proto.PlatformType_PLATFORM_TYPE_PC,
|
||||
}
|
||||
getPlayerAskFriendListRsp.AskFriendList = append(getPlayerAskFriendListRsp.AskFriendList, friendBrief)
|
||||
}
|
||||
g.SendMsg(proto.ApiGetPlayerAskFriendListRsp, userId, player.ClientSeq, getPlayerAskFriendListRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) AskAddFriendReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user apply add friend, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.AskAddFriendReq)
|
||||
targetUid := req.TargetUid
|
||||
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayerOnline := g.userManager.GetUserOnlineState(targetUid)
|
||||
targetPlayer := g.userManager.LoadTempOfflineUserSync(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.LOG.Error("apply add friend target player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
_, applyExist := targetPlayer.FriendApplyList[player.PlayerID]
|
||||
_, friendExist := targetPlayer.FriendList[player.PlayerID]
|
||||
if applyExist || friendExist {
|
||||
logger.LOG.Error("friend or apply already exist, user id: %v", userId)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendApplyList[player.PlayerID] = true
|
||||
|
||||
if targetPlayerOnline {
|
||||
// PacketAskAddFriendNotify
|
||||
askAddFriendNotify := new(proto.AskAddFriendNotify)
|
||||
askAddFriendNotify.TargetUid = player.PlayerID
|
||||
askAddFriendNotify.TargetFriendBrief = &proto.FriendBrief{
|
||||
Uid: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
Level: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: player.HeadImage},
|
||||
WorldLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
Signature: player.Signature,
|
||||
OnlineState: proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE,
|
||||
IsMpModeAvailable: true,
|
||||
LastActiveTime: player.OfflineTime,
|
||||
NameCardId: player.NameCard,
|
||||
Param: (uint32(time.Now().Unix()) - player.OfflineTime) / 3600 / 24,
|
||||
IsGameSource: true,
|
||||
PlatformType: proto.PlatformType_PLATFORM_TYPE_PC,
|
||||
}
|
||||
g.SendMsg(proto.ApiAskAddFriendNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, askAddFriendNotify)
|
||||
}
|
||||
|
||||
// PacketAskAddFriendRsp
|
||||
askAddFriendRsp := new(proto.AskAddFriendRsp)
|
||||
askAddFriendRsp.TargetUid = targetUid
|
||||
g.SendMsg(proto.ApiAskAddFriendRsp, userId, player.ClientSeq, askAddFriendRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) DealAddFriendReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user deal friend apply, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.DealAddFriendReq)
|
||||
targetUid := req.TargetUid
|
||||
result := req.DealAddFriendResult
|
||||
|
||||
if result == proto.DealAddFriendResultType_DEAL_ADD_FRIEND_RESULT_TYPE_ACCEPT {
|
||||
player.FriendList[targetUid] = true
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := g.userManager.LoadTempOfflineUserSync(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.LOG.Error("agree friend apply target player is nil, userId: %v", userId)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendList[player.PlayerID] = true
|
||||
}
|
||||
delete(player.FriendApplyList, targetUid)
|
||||
|
||||
// PacketDealAddFriendRsp
|
||||
dealAddFriendRsp := new(proto.DealAddFriendRsp)
|
||||
dealAddFriendRsp.TargetUid = targetUid
|
||||
dealAddFriendRsp.DealAddFriendResult = result
|
||||
g.SendMsg(proto.ApiDealAddFriendRsp, userId, player.ClientSeq, dealAddFriendRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) GetOnlinePlayerListReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user get online player list, user id: %v", userId)
|
||||
|
||||
count := 0
|
||||
onlinePlayerList := make([]*model.Player, 0)
|
||||
for _, onlinePlayer := range g.userManager.GetAllOnlineUserList() {
|
||||
if onlinePlayer.PlayerID == player.PlayerID {
|
||||
continue
|
||||
}
|
||||
onlinePlayerList = append(onlinePlayerList, onlinePlayer)
|
||||
count++
|
||||
if count >= 50 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// PacketGetOnlinePlayerListRsp
|
||||
getOnlinePlayerListRsp := new(proto.GetOnlinePlayerListRsp)
|
||||
getOnlinePlayerListRsp.PlayerInfoList = make([]*proto.OnlinePlayerInfo, 0)
|
||||
for _, onlinePlayer := range onlinePlayerList {
|
||||
onlinePlayerInfo := g.PacketOnlinePlayerInfo(onlinePlayer)
|
||||
getOnlinePlayerListRsp.PlayerInfoList = append(getOnlinePlayerListRsp.PlayerInfoList, onlinePlayerInfo)
|
||||
}
|
||||
g.SendMsg(proto.ApiGetOnlinePlayerListRsp, userId, player.ClientSeq, getOnlinePlayerListRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketOnlinePlayerInfo(player *model.Player) *proto.OnlinePlayerInfo {
|
||||
onlinePlayerInfo := &proto.OnlinePlayerInfo{
|
||||
Uid: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
PlayerLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
MpSettingType: proto.MpSettingType(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE]),
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: player.HeadImage},
|
||||
CurPlayerNumInWorld: 1,
|
||||
}
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
if world != nil && world.playerMap != nil {
|
||||
onlinePlayerInfo.CurPlayerNumInWorld = uint32(len(world.playerMap))
|
||||
}
|
||||
return onlinePlayerInfo
|
||||
}
|
||||
347
service/game-hk4e/game/user_team.go
Normal file
347
service/game-hk4e/game/user_team.go
Normal file
@@ -0,0 +1,347 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/common/utils/endec"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func (g *GameManager) ChangeAvatarReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change avatar, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.ChangeAvatarReq)
|
||||
targetAvatarGuid := req.Guid
|
||||
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID)
|
||||
|
||||
oldAvatarId := player.TeamConfig.GetActiveAvatarId()
|
||||
oldAvatar := player.AvatarMap[oldAvatarId]
|
||||
if oldAvatar.Guid == targetAvatarGuid {
|
||||
logger.LOG.Error("can not change to the same avatar, user id: %v, oldAvatarId: %v, oldAvatarGuid: %v", userId, oldAvatarId, oldAvatar.Guid)
|
||||
return
|
||||
}
|
||||
activeTeam := player.TeamConfig.GetActiveTeam()
|
||||
index := -1
|
||||
for avatarIndex, avatarId := range activeTeam.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
if targetAvatarGuid == player.AvatarMap[avatarId].Guid {
|
||||
index = avatarIndex
|
||||
}
|
||||
}
|
||||
if index == -1 {
|
||||
logger.LOG.Error("can not find the target avatar in team, user id: %v, target avatar guid: %v", userId, targetAvatarGuid)
|
||||
return
|
||||
}
|
||||
player.TeamConfig.CurrAvatarIndex = uint8(index)
|
||||
|
||||
entity := scene.GetEntity(playerTeamEntity.avatarEntityMap[oldAvatarId])
|
||||
if entity == nil {
|
||||
return
|
||||
}
|
||||
entity.moveState = uint16(proto.MotionState_MOTION_STATE_STANDBY)
|
||||
|
||||
// PacketSceneEntityDisappearNotify
|
||||
sceneEntityDisappearNotify := new(proto.SceneEntityDisappearNotify)
|
||||
sceneEntityDisappearNotify.DisappearType = proto.VisionType_VISION_TYPE_REPLACE
|
||||
sceneEntityDisappearNotify.EntityList = []uint32{playerTeamEntity.avatarEntityMap[oldAvatarId]}
|
||||
for _, scenePlayer := range scene.playerMap {
|
||||
g.SendMsg(proto.ApiSceneEntityDisappearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityDisappearNotify)
|
||||
}
|
||||
|
||||
// PacketSceneEntityAppearNotify
|
||||
sceneEntityAppearNotify := new(proto.SceneEntityAppearNotify)
|
||||
sceneEntityAppearNotify.AppearType = proto.VisionType_VISION_TYPE_REPLACE
|
||||
sceneEntityAppearNotify.Param = playerTeamEntity.avatarEntityMap[oldAvatarId]
|
||||
sceneEntityAppearNotify.EntityList = []*proto.SceneEntityInfo{g.PacketSceneEntityInfoAvatar(scene, player, player.TeamConfig.GetActiveAvatarId())}
|
||||
for _, scenePlayer := range scene.playerMap {
|
||||
g.SendMsg(proto.ApiSceneEntityAppearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityAppearNotify)
|
||||
}
|
||||
|
||||
// PacketChangeAvatarRsp
|
||||
changeAvatarRsp := new(proto.ChangeAvatarRsp)
|
||||
changeAvatarRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SUCC)
|
||||
changeAvatarRsp.CurGuid = targetAvatarGuid
|
||||
g.SendMsg(proto.ApiChangeAvatarRsp, userId, player.ClientSeq, changeAvatarRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) SetUpAvatarTeamReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change team, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.SetUpAvatarTeamReq)
|
||||
|
||||
teamId := req.TeamId
|
||||
if teamId <= 0 || teamId >= 5 {
|
||||
// PacketSetUpAvatarTeamRsp
|
||||
setUpAvatarTeamRsp := new(proto.SetUpAvatarTeamRsp)
|
||||
setUpAvatarTeamRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SVR_ERROR)
|
||||
g.SendMsg(proto.ApiSetUpAvatarTeamRsp, userId, player.ClientSeq, setUpAvatarTeamRsp)
|
||||
return
|
||||
}
|
||||
avatarGuidList := req.AvatarTeamGuidList
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
multiTeam := teamId == 4
|
||||
selfTeam := teamId == uint32(player.TeamConfig.GetActiveTeamId())
|
||||
if (multiTeam && len(avatarGuidList) == 0) || (selfTeam && len(avatarGuidList) == 0) || len(avatarGuidList) > 4 || world.multiplayer {
|
||||
// PacketSetUpAvatarTeamRsp
|
||||
setUpAvatarTeamRsp := new(proto.SetUpAvatarTeamRsp)
|
||||
setUpAvatarTeamRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SVR_ERROR)
|
||||
g.SendMsg(proto.ApiSetUpAvatarTeamRsp, userId, player.ClientSeq, setUpAvatarTeamRsp)
|
||||
return
|
||||
}
|
||||
avatarIdList := make([]uint32, 0)
|
||||
for _, avatarGuid := range avatarGuidList {
|
||||
for avatarId, avatar := range player.AvatarMap {
|
||||
if avatarGuid == avatar.Guid {
|
||||
avatarIdList = append(avatarIdList, avatarId)
|
||||
}
|
||||
}
|
||||
}
|
||||
player.TeamConfig.ClearTeamAvatar(uint8(teamId - 1))
|
||||
for _, avatarId := range avatarIdList {
|
||||
player.TeamConfig.AddAvatarToTeam(avatarId, uint8(teamId-1))
|
||||
}
|
||||
|
||||
if world.multiplayer {
|
||||
// PacketSetUpAvatarTeamRsp
|
||||
setUpAvatarTeamRsp := new(proto.SetUpAvatarTeamRsp)
|
||||
setUpAvatarTeamRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SVR_ERROR)
|
||||
g.SendMsg(proto.ApiSetUpAvatarTeamRsp, userId, player.ClientSeq, setUpAvatarTeamRsp)
|
||||
return
|
||||
}
|
||||
|
||||
// PacketAvatarTeamUpdateNotify
|
||||
avatarTeamUpdateNotify := new(proto.AvatarTeamUpdateNotify)
|
||||
avatarTeamUpdateNotify.AvatarTeamMap = make(map[uint32]*proto.AvatarTeam)
|
||||
for teamIndex, team := range player.TeamConfig.TeamList {
|
||||
avatarTeam := new(proto.AvatarTeam)
|
||||
avatarTeam.TeamName = team.Name
|
||||
for _, avatarId := range team.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
avatarTeam.AvatarGuidList = append(avatarTeam.AvatarGuidList, player.AvatarMap[avatarId].Guid)
|
||||
}
|
||||
avatarTeamUpdateNotify.AvatarTeamMap[uint32(teamIndex)+1] = avatarTeam
|
||||
}
|
||||
g.SendMsg(proto.ApiAvatarTeamUpdateNotify, userId, player.ClientSeq, avatarTeamUpdateNotify)
|
||||
|
||||
if selfTeam {
|
||||
player.TeamConfig.CurrAvatarIndex = 0
|
||||
player.TeamConfig.UpdateTeam()
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
scene.UpdatePlayerTeamEntity(player)
|
||||
|
||||
// PacketSceneTeamUpdateNotify
|
||||
sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(world)
|
||||
g.SendMsg(proto.ApiSceneTeamUpdateNotify, userId, player.ClientSeq, sceneTeamUpdateNotify)
|
||||
|
||||
// PacketSetUpAvatarTeamRsp
|
||||
setUpAvatarTeamRsp := new(proto.SetUpAvatarTeamRsp)
|
||||
setUpAvatarTeamRsp.TeamId = teamId
|
||||
setUpAvatarTeamRsp.CurAvatarGuid = player.AvatarMap[player.TeamConfig.GetActiveAvatarId()].Guid
|
||||
team := player.TeamConfig.GetTeamByIndex(uint8(teamId - 1))
|
||||
for _, avatarId := range team.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
setUpAvatarTeamRsp.AvatarTeamGuidList = append(setUpAvatarTeamRsp.AvatarTeamGuidList, player.AvatarMap[avatarId].Guid)
|
||||
}
|
||||
g.SendMsg(proto.ApiSetUpAvatarTeamRsp, userId, player.ClientSeq, setUpAvatarTeamRsp)
|
||||
} else {
|
||||
// PacketSetUpAvatarTeamRsp
|
||||
setUpAvatarTeamRsp := new(proto.SetUpAvatarTeamRsp)
|
||||
setUpAvatarTeamRsp.TeamId = teamId
|
||||
setUpAvatarTeamRsp.CurAvatarGuid = player.AvatarMap[player.TeamConfig.GetActiveAvatarId()].Guid
|
||||
team := player.TeamConfig.GetTeamByIndex(uint8(teamId - 1))
|
||||
for _, avatarId := range team.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
setUpAvatarTeamRsp.AvatarTeamGuidList = append(setUpAvatarTeamRsp.AvatarTeamGuidList, player.AvatarMap[avatarId].Guid)
|
||||
}
|
||||
g.SendMsg(proto.ApiSetUpAvatarTeamRsp, userId, player.ClientSeq, setUpAvatarTeamRsp)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) ChooseCurAvatarTeamReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user switch team, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.ChooseCurAvatarTeamReq)
|
||||
teamId := req.TeamId
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
if world.multiplayer {
|
||||
return
|
||||
}
|
||||
team := player.TeamConfig.GetTeamByIndex(uint8(teamId) - 1)
|
||||
if team == nil || len(team.AvatarIdList) == 0 {
|
||||
return
|
||||
}
|
||||
player.TeamConfig.CurrTeamIndex = uint8(teamId) - 1
|
||||
player.TeamConfig.CurrAvatarIndex = 0
|
||||
player.TeamConfig.UpdateTeam()
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
scene.UpdatePlayerTeamEntity(player)
|
||||
|
||||
// PacketSceneTeamUpdateNotify
|
||||
sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(world)
|
||||
g.SendMsg(proto.ApiSceneTeamUpdateNotify, userId, player.ClientSeq, sceneTeamUpdateNotify)
|
||||
|
||||
// PacketChooseCurAvatarTeamRsp
|
||||
chooseCurAvatarTeamRsp := new(proto.ChooseCurAvatarTeamRsp)
|
||||
chooseCurAvatarTeamRsp.CurTeamId = teamId
|
||||
g.SendMsg(proto.ApiChooseCurAvatarTeamRsp, userId, player.ClientSeq, chooseCurAvatarTeamRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) ChangeMpTeamAvatarReq(userId uint32, player *model.Player, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.LOG.Debug("user change mp team, user id: %v", userId)
|
||||
req := payloadMsg.(*proto.ChangeMpTeamAvatarReq)
|
||||
avatarGuidList := req.AvatarGuidList
|
||||
|
||||
world := g.worldManager.GetWorldByID(player.WorldId)
|
||||
if len(avatarGuidList) == 0 || len(avatarGuidList) > 4 || !world.multiplayer {
|
||||
// PacketChangeMpTeamAvatarRsp
|
||||
changeMpTeamAvatarRsp := new(proto.ChangeMpTeamAvatarRsp)
|
||||
changeMpTeamAvatarRsp.Retcode = int32(proto.Retcode_RETCODE_RET_SVR_ERROR)
|
||||
g.SendMsg(proto.ApiChangeMpTeamAvatarRsp, userId, player.ClientSeq, changeMpTeamAvatarRsp)
|
||||
return
|
||||
}
|
||||
avatarIdList := make([]uint32, 0)
|
||||
for _, avatarGuid := range avatarGuidList {
|
||||
for avatarId, avatar := range player.AvatarMap {
|
||||
if avatarGuid == avatar.Guid {
|
||||
avatarIdList = append(avatarIdList, avatarId)
|
||||
}
|
||||
}
|
||||
}
|
||||
player.TeamConfig.ClearTeamAvatar(3)
|
||||
for _, avatarId := range avatarIdList {
|
||||
player.TeamConfig.AddAvatarToTeam(avatarId, 3)
|
||||
}
|
||||
player.TeamConfig.CurrAvatarIndex = 0
|
||||
player.TeamConfig.UpdateTeam()
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
scene.UpdatePlayerTeamEntity(player)
|
||||
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
// PacketSceneTeamUpdateNotify
|
||||
sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(world)
|
||||
g.SendMsg(proto.ApiSceneTeamUpdateNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, sceneTeamUpdateNotify)
|
||||
}
|
||||
|
||||
// PacketChangeMpTeamAvatarRsp
|
||||
changeMpTeamAvatarRsp := new(proto.ChangeMpTeamAvatarRsp)
|
||||
changeMpTeamAvatarRsp.CurAvatarGuid = player.AvatarMap[player.TeamConfig.GetActiveAvatarId()].Guid
|
||||
team := player.TeamConfig.GetTeamByIndex(3)
|
||||
for _, avatarId := range team.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
changeMpTeamAvatarRsp.AvatarGuidList = append(changeMpTeamAvatarRsp.AvatarGuidList, player.AvatarMap[avatarId].Guid)
|
||||
}
|
||||
g.SendMsg(proto.ApiChangeMpTeamAvatarRsp, userId, player.ClientSeq, changeMpTeamAvatarRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketSceneTeamUpdateNotify(world *World) *proto.SceneTeamUpdateNotify {
|
||||
sceneTeamUpdateNotify := new(proto.SceneTeamUpdateNotify)
|
||||
sceneTeamUpdateNotify.IsInMp = world.multiplayer
|
||||
empty := new(proto.AbilitySyncStateInfo)
|
||||
for _, worldPlayer := range world.playerMap {
|
||||
worldPlayerScene := world.GetSceneById(worldPlayer.SceneId)
|
||||
worldPlayerTeamEntity := worldPlayerScene.GetPlayerTeamEntity(worldPlayer.PlayerID)
|
||||
team := worldPlayer.TeamConfig.GetActiveTeam()
|
||||
for _, avatarId := range team.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
worldPlayerAvatar := worldPlayer.AvatarMap[avatarId]
|
||||
equipIdList := make([]uint32, 0)
|
||||
weapon := worldPlayerAvatar.EquipWeapon
|
||||
equipIdList = append(equipIdList, weapon.ItemId)
|
||||
for _, reliquary := range worldPlayerAvatar.EquipReliquaryList {
|
||||
equipIdList = append(equipIdList, reliquary.ItemId)
|
||||
}
|
||||
sceneTeamAvatar := &proto.SceneTeamAvatar{
|
||||
PlayerUid: worldPlayer.PlayerID,
|
||||
AvatarGuid: worldPlayerAvatar.Guid,
|
||||
SceneId: worldPlayer.SceneId,
|
||||
EntityId: worldPlayerTeamEntity.avatarEntityMap[avatarId],
|
||||
SceneEntityInfo: g.PacketSceneEntityInfoAvatar(worldPlayerScene, worldPlayer, avatarId),
|
||||
WeaponGuid: worldPlayerAvatar.EquipWeapon.Guid,
|
||||
WeaponEntityId: worldPlayerTeamEntity.weaponEntityMap[worldPlayerAvatar.EquipWeapon.WeaponId],
|
||||
IsPlayerCurAvatar: worldPlayer.TeamConfig.GetActiveAvatarId() == avatarId,
|
||||
IsOnScene: worldPlayer.TeamConfig.GetActiveAvatarId() == avatarId,
|
||||
AvatarAbilityInfo: empty,
|
||||
WeaponAbilityInfo: empty,
|
||||
AbilityControlBlock: new(proto.AbilityControlBlock),
|
||||
}
|
||||
if world.multiplayer {
|
||||
sceneTeamAvatar.AvatarInfo = g.PacketAvatarInfo(worldPlayerAvatar)
|
||||
sceneTeamAvatar.SceneAvatarInfo = g.PacketSceneAvatarInfo(worldPlayerScene, worldPlayer, avatarId)
|
||||
}
|
||||
// add AbilityControlBlock
|
||||
avatarDataConfig := gdc.CONF.AvatarDataMap[int32(avatarId)]
|
||||
acb := sceneTeamAvatar.AbilityControlBlock
|
||||
embryoId := 0
|
||||
// add avatar abilities
|
||||
for _, abilityId := range avatarDataConfig.Abilities {
|
||||
embryoId++
|
||||
emb := &proto.AbilityEmbryo{
|
||||
AbilityId: uint32(embryoId),
|
||||
AbilityNameHash: uint32(abilityId),
|
||||
AbilityOverrideNameHash: uint32(constant.GameConstantConst.DEFAULT_ABILITY_NAME),
|
||||
}
|
||||
acb.AbilityEmbryoList = append(acb.AbilityEmbryoList, emb)
|
||||
}
|
||||
// add default abilities
|
||||
for _, abilityId := range constant.GameConstantConst.DEFAULT_ABILITY_HASHES {
|
||||
embryoId++
|
||||
emb := &proto.AbilityEmbryo{
|
||||
AbilityId: uint32(embryoId),
|
||||
AbilityNameHash: uint32(abilityId),
|
||||
AbilityOverrideNameHash: uint32(constant.GameConstantConst.DEFAULT_ABILITY_NAME),
|
||||
}
|
||||
acb.AbilityEmbryoList = append(acb.AbilityEmbryoList, emb)
|
||||
}
|
||||
// add team resonances
|
||||
for id := range worldPlayer.TeamConfig.TeamResonancesConfig {
|
||||
embryoId++
|
||||
emb := &proto.AbilityEmbryo{
|
||||
AbilityId: uint32(embryoId),
|
||||
AbilityNameHash: uint32(id),
|
||||
AbilityOverrideNameHash: uint32(constant.GameConstantConst.DEFAULT_ABILITY_NAME),
|
||||
}
|
||||
acb.AbilityEmbryoList = append(acb.AbilityEmbryoList, emb)
|
||||
}
|
||||
// add skill depot abilities
|
||||
skillDepot := gdc.CONF.AvatarSkillDepotDataMap[int32(worldPlayerAvatar.SkillDepotId)]
|
||||
if skillDepot != nil && len(skillDepot.Abilities) != 0 {
|
||||
for _, id := range skillDepot.Abilities {
|
||||
embryoId++
|
||||
emb := &proto.AbilityEmbryo{
|
||||
AbilityId: uint32(embryoId),
|
||||
AbilityNameHash: uint32(id),
|
||||
AbilityOverrideNameHash: uint32(constant.GameConstantConst.DEFAULT_ABILITY_NAME),
|
||||
}
|
||||
acb.AbilityEmbryoList = append(acb.AbilityEmbryoList, emb)
|
||||
}
|
||||
}
|
||||
// add equip abilities
|
||||
for skill := range worldPlayerAvatar.ExtraAbilityEmbryos {
|
||||
embryoId++
|
||||
emb := &proto.AbilityEmbryo{
|
||||
AbilityId: uint32(embryoId),
|
||||
AbilityNameHash: uint32(endec.Hk4eAbilityHashCode(skill)),
|
||||
AbilityOverrideNameHash: uint32(constant.GameConstantConst.DEFAULT_ABILITY_NAME),
|
||||
}
|
||||
acb.AbilityEmbryoList = append(acb.AbilityEmbryoList, emb)
|
||||
}
|
||||
sceneTeamUpdateNotify.SceneTeamAvatarList = append(sceneTeamUpdateNotify.SceneTeamAvatarList, sceneTeamAvatar)
|
||||
}
|
||||
}
|
||||
return sceneTeamUpdateNotify
|
||||
}
|
||||
77
service/game-hk4e/game/user_weapon.go
Normal file
77
service/game-hk4e/game/user_weapon.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
)
|
||||
|
||||
func (g *GameManager) GetAllWeaponDataConfig() map[int32]*gdc.ItemData {
|
||||
allWeaponDataConfig := make(map[int32]*gdc.ItemData)
|
||||
for itemId, itemData := range gdc.CONF.ItemDataMap {
|
||||
if itemData.EquipEnumType != constant.EquipTypeConst.EQUIP_WEAPON {
|
||||
continue
|
||||
}
|
||||
if (itemId >= 10000 && itemId <= 10008) ||
|
||||
itemId == 11411 ||
|
||||
(itemId >= 11506 && itemId <= 11508) ||
|
||||
itemId == 12505 ||
|
||||
itemId == 12506 ||
|
||||
itemId == 12508 ||
|
||||
itemId == 12509 ||
|
||||
itemId == 13503 ||
|
||||
itemId == 13506 ||
|
||||
itemId == 14411 ||
|
||||
itemId == 14503 ||
|
||||
itemId == 14505 ||
|
||||
itemId == 14508 ||
|
||||
(itemId >= 15504 && itemId <= 15506) ||
|
||||
itemId == 20001 || itemId == 15306 || itemId == 14306 || itemId == 13304 || itemId == 12304 {
|
||||
// 跳过无效武器
|
||||
continue
|
||||
}
|
||||
allWeaponDataConfig[itemId] = itemData
|
||||
}
|
||||
return allWeaponDataConfig
|
||||
}
|
||||
|
||||
func (g *GameManager) AddUserWeapon(userId uint32, itemId uint32) uint64 {
|
||||
player := g.userManager.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.LOG.Error("player is nil, userId: %v", userId)
|
||||
return 0
|
||||
}
|
||||
weaponId := uint64(g.snowflake.GenId())
|
||||
player.AddWeapon(itemId, weaponId)
|
||||
weapon := player.GetWeapon(weaponId)
|
||||
|
||||
// PacketStoreItemChangeNotify
|
||||
storeItemChangeNotify := new(proto.StoreItemChangeNotify)
|
||||
storeItemChangeNotify.StoreType = proto.StoreType_STORE_TYPE_PACK
|
||||
affixMap := make(map[uint32]uint32)
|
||||
for _, affixId := range weapon.AffixIdList {
|
||||
affixMap[affixId] = uint32(weapon.Refinement)
|
||||
}
|
||||
pbItem := &proto.Item{
|
||||
ItemId: itemId,
|
||||
Guid: player.GetWeaponGuid(weaponId),
|
||||
Detail: &proto.Item_Equip{
|
||||
Equip: &proto.Equip{
|
||||
Detail: &proto.Equip_Weapon{
|
||||
Weapon: &proto.Weapon{
|
||||
Level: uint32(weapon.Level),
|
||||
Exp: weapon.Exp,
|
||||
PromoteLevel: uint32(weapon.Promote),
|
||||
// key:武器效果id value:精炼等阶
|
||||
AffixMap: affixMap,
|
||||
},
|
||||
},
|
||||
IsLocked: weapon.Lock,
|
||||
},
|
||||
},
|
||||
}
|
||||
storeItemChangeNotify.ItemList = append(storeItemChangeNotify.ItemList, pbItem)
|
||||
g.SendMsg(proto.ApiStoreItemChangeNotify, userId, player.ClientSeq, storeItemChangeNotify)
|
||||
return weaponId
|
||||
}
|
||||
620
service/game-hk4e/game/world_manager.go
Normal file
620
service/game-hk4e/game/world_manager.go
Normal file
@@ -0,0 +1,620 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"flswld.com/common/utils/alg"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
"game-hk4e/game/aoi"
|
||||
"game-hk4e/model"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
"math"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// 世界管理器
|
||||
|
||||
type MeshMapPos struct {
|
||||
X int16
|
||||
Y int16
|
||||
Z int16
|
||||
}
|
||||
|
||||
type WorldStatic struct {
|
||||
// x y z -> if terrain exist
|
||||
terrain map[MeshMapPos]bool
|
||||
// x y z -> gather id
|
||||
gather map[MeshMapPos]uint32
|
||||
pathfindingStartPos MeshMapPos
|
||||
pathfindingEndPos MeshMapPos
|
||||
pathVectorList []MeshMapPos
|
||||
aiMoveMeshSpeedParam int
|
||||
aiMoveVectorList []*model.Vector
|
||||
aiMoveCurrIndex int
|
||||
}
|
||||
|
||||
func NewWorldStatic() (r *WorldStatic) {
|
||||
r = new(WorldStatic)
|
||||
r.terrain = make(map[MeshMapPos]bool)
|
||||
r.gather = make(map[MeshMapPos]uint32)
|
||||
r.InitGather()
|
||||
r.pathfindingStartPos = MeshMapPos{
|
||||
X: 2747,
|
||||
Y: 194,
|
||||
Z: -1719,
|
||||
}
|
||||
r.pathfindingEndPos = MeshMapPos{
|
||||
X: 2588,
|
||||
Y: 211,
|
||||
Z: -1349,
|
||||
}
|
||||
r.pathVectorList = make([]MeshMapPos, 0)
|
||||
r.aiMoveMeshSpeedParam = 3
|
||||
r.aiMoveVectorList = make([]*model.Vector, 0)
|
||||
r.aiMoveCurrIndex = 0
|
||||
return r
|
||||
}
|
||||
|
||||
func (w *WorldStatic) ConvWSTMapToPFMap() map[alg.MeshMapPos]bool {
|
||||
return *(*map[alg.MeshMapPos]bool)(unsafe.Pointer(&w.terrain))
|
||||
}
|
||||
|
||||
func (w *WorldStatic) ConvWSPosToPFPos(v MeshMapPos) alg.MeshMapPos {
|
||||
return alg.MeshMapPos(v)
|
||||
}
|
||||
|
||||
func (w *WorldStatic) ConvPFPVLToWSPVL(v []alg.MeshMapPos) []MeshMapPos {
|
||||
return *(*[]MeshMapPos)(unsafe.Pointer(&v))
|
||||
}
|
||||
|
||||
func (w *WorldStatic) Pathfinding() {
|
||||
bfs := alg.NewBFS()
|
||||
bfs.InitMap(
|
||||
w.ConvWSTMapToPFMap(),
|
||||
w.ConvWSPosToPFPos(w.pathfindingStartPos),
|
||||
w.ConvWSPosToPFPos(w.pathfindingEndPos),
|
||||
100,
|
||||
)
|
||||
pathVectorList := bfs.Pathfinding()
|
||||
if pathVectorList == nil {
|
||||
logger.LOG.Error("could not find path")
|
||||
return
|
||||
}
|
||||
logger.LOG.Debug("find path success, path: %v", pathVectorList)
|
||||
w.pathVectorList = w.ConvPFPVLToWSPVL(pathVectorList)
|
||||
}
|
||||
|
||||
func (w *WorldStatic) ConvPathVectorListToAiMoveVectorList() {
|
||||
for index, currPathVector := range w.pathVectorList {
|
||||
if index > 0 {
|
||||
lastPathVector := w.pathVectorList[index-1]
|
||||
for i := 0; i < w.aiMoveMeshSpeedParam; i++ {
|
||||
w.aiMoveVectorList = append(w.aiMoveVectorList, &model.Vector{
|
||||
X: float64(lastPathVector.X) + float64(currPathVector.X-lastPathVector.X)/float64(w.aiMoveMeshSpeedParam)*float64(i),
|
||||
Y: float64(lastPathVector.Y) + float64(currPathVector.Y-lastPathVector.Y)/float64(w.aiMoveMeshSpeedParam)*float64(i),
|
||||
Z: float64(lastPathVector.Z) + float64(currPathVector.Z-lastPathVector.Z)/float64(w.aiMoveMeshSpeedParam)*float64(i),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WorldStatic) InitTerrain() bool {
|
||||
data := gdc.CONF.ReadWorldTerrain()
|
||||
decoder := gob.NewDecoder(bytes.NewReader(data))
|
||||
err := decoder.Decode(&w.terrain)
|
||||
if err != nil {
|
||||
logger.LOG.Error("unmarshal world terrain data error: %v", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *WorldStatic) SaveTerrain() bool {
|
||||
var buffer bytes.Buffer
|
||||
encoder := gob.NewEncoder(&buffer)
|
||||
err := encoder.Encode(w.terrain)
|
||||
if err != nil {
|
||||
logger.LOG.Error("marshal world terrain data error: %v", err)
|
||||
return false
|
||||
}
|
||||
gdc.CONF.WriteWorldTerrain(buffer.Bytes())
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *WorldStatic) GetTerrain(x int16, y int16, z int16) (exist bool) {
|
||||
pos := MeshMapPos{
|
||||
X: x,
|
||||
Y: y,
|
||||
Z: z,
|
||||
}
|
||||
exist = w.terrain[pos]
|
||||
return exist
|
||||
}
|
||||
|
||||
func (w *WorldStatic) SetTerrain(x int16, y int16, z int16) {
|
||||
pos := MeshMapPos{
|
||||
X: x,
|
||||
Y: y,
|
||||
Z: z,
|
||||
}
|
||||
w.terrain[pos] = true
|
||||
}
|
||||
|
||||
func (w *WorldStatic) InitGather() {
|
||||
}
|
||||
|
||||
func (w *WorldStatic) GetGather(x int16, y int16, z int16) (gatherId uint32, exist bool) {
|
||||
pos := MeshMapPos{
|
||||
X: x,
|
||||
Y: y,
|
||||
Z: z,
|
||||
}
|
||||
gatherId, exist = w.gather[pos]
|
||||
return gatherId, exist
|
||||
}
|
||||
|
||||
func (w *WorldStatic) SetGather(x int16, y int16, z int16, gatherId uint32) {
|
||||
pos := MeshMapPos{
|
||||
X: x,
|
||||
Y: y,
|
||||
Z: z,
|
||||
}
|
||||
w.gather[pos] = gatherId
|
||||
}
|
||||
|
||||
type WorldManager struct {
|
||||
worldMap map[uint32]*World
|
||||
snowflake *alg.SnowflakeWorker
|
||||
worldStatic *WorldStatic
|
||||
bigWorld *World
|
||||
}
|
||||
|
||||
func NewWorldManager(snowflake *alg.SnowflakeWorker) (r *WorldManager) {
|
||||
r = new(WorldManager)
|
||||
r.worldMap = make(map[uint32]*World)
|
||||
r.snowflake = snowflake
|
||||
r.worldStatic = NewWorldStatic()
|
||||
return r
|
||||
}
|
||||
|
||||
func (w *WorldManager) GetWorldByID(worldId uint32) *World {
|
||||
return w.worldMap[worldId]
|
||||
}
|
||||
|
||||
func (w *WorldManager) GetWorldMap() map[uint32]*World {
|
||||
return w.worldMap
|
||||
}
|
||||
|
||||
func (w *WorldManager) CreateWorld(owner *model.Player, multiplayer bool) *World {
|
||||
worldId := uint32(w.snowflake.GenId())
|
||||
world := &World{
|
||||
id: worldId,
|
||||
owner: owner,
|
||||
playerMap: make(map[uint32]*model.Player),
|
||||
sceneMap: make(map[uint32]*Scene),
|
||||
entityIdCounter: 0,
|
||||
worldLevel: 0,
|
||||
multiplayer: multiplayer,
|
||||
mpLevelEntityId: 0,
|
||||
chatMsgList: make([]*proto.ChatInfo, 0),
|
||||
// aoi划分
|
||||
aoiManager: aoi.NewAoiManager(
|
||||
-8000, 4000, 120,
|
||||
-2000, 2000, 80,
|
||||
-5500, 6500, 120,
|
||||
),
|
||||
}
|
||||
if world.IsBigWorld() {
|
||||
world.aoiManager = aoi.NewAoiManager(
|
||||
-8000, 4000, 800,
|
||||
-2000, 2000, 80,
|
||||
-5500, 6500, 800,
|
||||
)
|
||||
}
|
||||
world.mpLevelEntityId = world.GetNextWorldEntityId(constant.EntityIdTypeConst.MPLEVEL)
|
||||
w.worldMap[worldId] = world
|
||||
return world
|
||||
}
|
||||
|
||||
func (w *WorldManager) DestroyWorld(worldId uint32) {
|
||||
world := w.GetWorldByID(worldId)
|
||||
for _, player := range world.playerMap {
|
||||
world.RemovePlayer(player)
|
||||
player.WorldId = 0
|
||||
}
|
||||
delete(w.worldMap, worldId)
|
||||
}
|
||||
|
||||
func (w *WorldManager) GetBigWorld() *World {
|
||||
return w.bigWorld
|
||||
}
|
||||
|
||||
func (w *WorldManager) InitBigWorld(owner *model.Player) {
|
||||
w.bigWorld = w.GetWorldByID(owner.WorldId)
|
||||
w.bigWorld.multiplayer = true
|
||||
}
|
||||
|
||||
type World struct {
|
||||
id uint32
|
||||
owner *model.Player
|
||||
playerMap map[uint32]*model.Player
|
||||
sceneMap map[uint32]*Scene
|
||||
entityIdCounter uint32
|
||||
worldLevel uint8
|
||||
multiplayer bool
|
||||
mpLevelEntityId uint32
|
||||
chatMsgList []*proto.ChatInfo
|
||||
aoiManager *aoi.AoiManager // 当前世界地图的aoi管理器
|
||||
}
|
||||
|
||||
func (w *World) GetNextWorldEntityId(entityType uint16) uint32 {
|
||||
w.entityIdCounter++
|
||||
ret := (uint32(entityType) << 24) + w.entityIdCounter
|
||||
return ret
|
||||
}
|
||||
|
||||
func (w *World) AddPlayer(player *model.Player, sceneId uint32) {
|
||||
player.PeerId = uint32(len(w.playerMap) + 1)
|
||||
w.playerMap[player.PlayerID] = player
|
||||
scene := w.GetSceneById(sceneId)
|
||||
scene.AddPlayer(player)
|
||||
}
|
||||
|
||||
func (w *World) RemovePlayer(player *model.Player) {
|
||||
scene := w.sceneMap[player.SceneId]
|
||||
scene.RemovePlayer(player)
|
||||
delete(w.playerMap, player.PlayerID)
|
||||
}
|
||||
|
||||
func (w *World) CreateScene(sceneId uint32) *Scene {
|
||||
scene := &Scene{
|
||||
id: sceneId,
|
||||
world: w,
|
||||
playerMap: make(map[uint32]*model.Player),
|
||||
entityMap: make(map[uint32]*Entity),
|
||||
playerTeamEntityMap: make(map[uint32]*PlayerTeamEntity),
|
||||
gameTime: 18 * 60,
|
||||
attackQueue: alg.NewRAQueue[*Attack](1000),
|
||||
createTime: time.Now().UnixMilli(),
|
||||
}
|
||||
w.sceneMap[sceneId] = scene
|
||||
return scene
|
||||
}
|
||||
|
||||
func (w *World) GetSceneById(sceneId uint32) *Scene {
|
||||
scene, exist := w.sceneMap[sceneId]
|
||||
if !exist {
|
||||
scene = w.CreateScene(sceneId)
|
||||
}
|
||||
return scene
|
||||
}
|
||||
|
||||
func (w *World) AddChat(chatInfo *proto.ChatInfo) {
|
||||
w.chatMsgList = append(w.chatMsgList, chatInfo)
|
||||
}
|
||||
|
||||
func (w *World) GetChatList() []*proto.ChatInfo {
|
||||
return w.chatMsgList
|
||||
}
|
||||
|
||||
func (w *World) IsBigWorld() bool {
|
||||
return w.owner.PlayerID == 1
|
||||
}
|
||||
|
||||
type Scene struct {
|
||||
id uint32
|
||||
world *World
|
||||
playerMap map[uint32]*model.Player
|
||||
entityMap map[uint32]*Entity
|
||||
playerTeamEntityMap map[uint32]*PlayerTeamEntity
|
||||
gameTime uint32
|
||||
attackQueue *alg.RAQueue[*Attack]
|
||||
createTime int64
|
||||
}
|
||||
|
||||
type AvatarEntity struct {
|
||||
uid uint32
|
||||
avatarId uint32
|
||||
}
|
||||
|
||||
type MonsterEntity struct {
|
||||
}
|
||||
|
||||
type GadgetEntity struct {
|
||||
gatherId uint32
|
||||
}
|
||||
|
||||
type Entity struct {
|
||||
id uint32
|
||||
scene *Scene
|
||||
pos *model.Vector
|
||||
rot *model.Vector
|
||||
moveState uint16
|
||||
lastMoveSceneTimeMs uint32
|
||||
lastMoveReliableSeq uint32
|
||||
fightProp map[uint32]float32
|
||||
entityType uint32
|
||||
level uint8
|
||||
avatarEntity *AvatarEntity
|
||||
monsterEntity *MonsterEntity
|
||||
gadgetEntity *GadgetEntity
|
||||
}
|
||||
|
||||
type PlayerTeamEntity struct {
|
||||
teamEntityId uint32
|
||||
avatarEntityMap map[uint32]uint32
|
||||
weaponEntityMap map[uint64]uint32
|
||||
}
|
||||
|
||||
type Attack struct {
|
||||
combatInvokeEntry *proto.CombatInvokeEntry
|
||||
uid uint32
|
||||
}
|
||||
|
||||
func (s *Scene) ChangeGameTime(time uint32) {
|
||||
s.gameTime = time % 1440
|
||||
}
|
||||
|
||||
func (s *Scene) GetSceneTime() int64 {
|
||||
now := time.Now().UnixMilli()
|
||||
return now - s.createTime
|
||||
}
|
||||
|
||||
func (s *Scene) GetPlayerTeamEntity(userId uint32) *PlayerTeamEntity {
|
||||
return s.playerTeamEntityMap[userId]
|
||||
}
|
||||
|
||||
func (s *Scene) CreatePlayerTeamEntity(player *model.Player) {
|
||||
playerTeamEntity := &PlayerTeamEntity{
|
||||
teamEntityId: s.world.GetNextWorldEntityId(constant.EntityIdTypeConst.TEAM),
|
||||
avatarEntityMap: make(map[uint32]uint32),
|
||||
weaponEntityMap: make(map[uint64]uint32),
|
||||
}
|
||||
s.playerTeamEntityMap[player.PlayerID] = playerTeamEntity
|
||||
}
|
||||
|
||||
func (s *Scene) UpdatePlayerTeamEntity(player *model.Player) {
|
||||
team := player.TeamConfig.GetActiveTeam()
|
||||
playerTeamEntity := s.playerTeamEntityMap[player.PlayerID]
|
||||
for _, avatarId := range team.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
avatar := player.AvatarMap[avatarId]
|
||||
avatarEntityId, exist := playerTeamEntity.avatarEntityMap[avatarId]
|
||||
if exist {
|
||||
s.DestroyEntity(avatarEntityId)
|
||||
}
|
||||
playerTeamEntity.avatarEntityMap[avatarId] = s.CreateEntityAvatar(player, avatarId)
|
||||
weaponEntityId, exist := playerTeamEntity.weaponEntityMap[avatar.EquipWeapon.WeaponId]
|
||||
if exist {
|
||||
s.DestroyEntity(weaponEntityId)
|
||||
}
|
||||
playerTeamEntity.weaponEntityMap[avatar.EquipWeapon.WeaponId] = s.CreateEntityWeapon()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Scene) AddPlayer(player *model.Player) {
|
||||
s.playerMap[player.PlayerID] = player
|
||||
s.CreatePlayerTeamEntity(player)
|
||||
s.UpdatePlayerTeamEntity(player)
|
||||
}
|
||||
|
||||
func (s *Scene) RemovePlayer(player *model.Player) {
|
||||
playerTeamEntity := s.GetPlayerTeamEntity(player.PlayerID)
|
||||
for _, avatarEntityId := range playerTeamEntity.avatarEntityMap {
|
||||
s.DestroyEntity(avatarEntityId)
|
||||
}
|
||||
for _, weaponEntityId := range playerTeamEntity.weaponEntityMap {
|
||||
s.DestroyEntity(weaponEntityId)
|
||||
}
|
||||
delete(s.playerTeamEntityMap, player.PlayerID)
|
||||
delete(s.playerMap, player.PlayerID)
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32 {
|
||||
entityId := s.world.GetNextWorldEntityId(constant.EntityIdTypeConst.AVATAR)
|
||||
entity := &Entity{
|
||||
id: entityId,
|
||||
scene: s,
|
||||
pos: player.Pos,
|
||||
rot: player.Rot,
|
||||
moveState: uint16(proto.MotionState_MOTION_STATE_NONE),
|
||||
lastMoveSceneTimeMs: 0,
|
||||
lastMoveReliableSeq: 0,
|
||||
fightProp: player.AvatarMap[avatarId].FightPropMap,
|
||||
entityType: uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_AVATAR),
|
||||
level: player.AvatarMap[avatarId].Level,
|
||||
avatarEntity: &AvatarEntity{
|
||||
uid: player.PlayerID,
|
||||
avatarId: avatarId,
|
||||
},
|
||||
}
|
||||
s.entityMap[entity.id] = entity
|
||||
if avatarId == player.TeamConfig.GetActiveAvatarId() {
|
||||
s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
|
||||
}
|
||||
return entity.id
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntityWeapon() uint32 {
|
||||
entityId := s.world.GetNextWorldEntityId(constant.EntityIdTypeConst.WEAPON)
|
||||
entity := &Entity{
|
||||
id: entityId,
|
||||
scene: s,
|
||||
pos: new(model.Vector),
|
||||
rot: new(model.Vector),
|
||||
moveState: uint16(proto.MotionState_MOTION_STATE_NONE),
|
||||
lastMoveSceneTimeMs: 0,
|
||||
lastMoveReliableSeq: 0,
|
||||
fightProp: nil,
|
||||
entityType: uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_WEAPON),
|
||||
level: 0,
|
||||
}
|
||||
s.entityMap[entity.id] = entity
|
||||
return entity.id
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntityMonster(pos *model.Vector, level uint8, fightProp map[uint32]float32) uint32 {
|
||||
entityId := s.world.GetNextWorldEntityId(constant.EntityIdTypeConst.MONSTER)
|
||||
entity := &Entity{
|
||||
id: entityId,
|
||||
scene: s,
|
||||
pos: pos,
|
||||
rot: new(model.Vector),
|
||||
moveState: uint16(proto.MotionState_MOTION_STATE_NONE),
|
||||
lastMoveSceneTimeMs: 0,
|
||||
lastMoveReliableSeq: 0,
|
||||
fightProp: fightProp,
|
||||
entityType: uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_MONSTER),
|
||||
level: level,
|
||||
}
|
||||
s.entityMap[entity.id] = entity
|
||||
s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
|
||||
return entity.id
|
||||
}
|
||||
|
||||
func (s *Scene) CreateEntityGadget(pos *model.Vector, gatherId uint32) uint32 {
|
||||
entityId := s.world.GetNextWorldEntityId(constant.EntityIdTypeConst.GADGET)
|
||||
entity := &Entity{
|
||||
id: entityId,
|
||||
scene: s,
|
||||
pos: pos,
|
||||
rot: new(model.Vector),
|
||||
moveState: uint16(proto.MotionState_MOTION_STATE_NONE),
|
||||
lastMoveSceneTimeMs: 0,
|
||||
lastMoveReliableSeq: 0,
|
||||
fightProp: map[uint32]float32{
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP): math.MaxFloat32,
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_MAX_HP): math.MaxFloat32,
|
||||
uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_HP): float32(1),
|
||||
},
|
||||
entityType: uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET),
|
||||
level: 0,
|
||||
gadgetEntity: &GadgetEntity{
|
||||
gatherId: gatherId,
|
||||
},
|
||||
}
|
||||
s.entityMap[entity.id] = entity
|
||||
s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
|
||||
return entity.id
|
||||
}
|
||||
|
||||
func (s *Scene) DestroyEntity(entityId uint32) {
|
||||
entity := s.GetEntity(entityId)
|
||||
if entity == nil {
|
||||
return
|
||||
}
|
||||
s.world.aoiManager.RemoveEntityIdFromGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
|
||||
delete(s.entityMap, entityId)
|
||||
}
|
||||
|
||||
func (s *Scene) GetEntity(entityId uint32) *Entity {
|
||||
return s.entityMap[entityId]
|
||||
}
|
||||
|
||||
func (s *Scene) AddAttack(attack *Attack) {
|
||||
s.attackQueue.EnQueue(attack)
|
||||
}
|
||||
|
||||
func (s *Scene) AttackHandler(gameManager *GameManager) {
|
||||
combatInvokeEntryListAll := make([]*proto.CombatInvokeEntry, 0)
|
||||
combatInvokeEntryListOther := make(map[uint32][]*proto.CombatInvokeEntry)
|
||||
combatInvokeEntryListHost := make([]*proto.CombatInvokeEntry, 0)
|
||||
|
||||
for s.attackQueue.Len() != 0 {
|
||||
attack := s.attackQueue.DeQueue()
|
||||
if attack.combatInvokeEntry == nil {
|
||||
logger.LOG.Error("error attack data, attack value: %v", attack)
|
||||
continue
|
||||
}
|
||||
|
||||
hitInfo := new(proto.EvtBeingHitInfo)
|
||||
err := pb.Unmarshal(attack.combatInvokeEntry.CombatData, hitInfo)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse combat invocations entity hit info error: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
attackResult := hitInfo.AttackResult
|
||||
//logger.LOG.Debug("run attack handler, attackResult: %v", attackResult)
|
||||
target := s.entityMap[attackResult.DefenseId]
|
||||
if target == nil {
|
||||
logger.LOG.Error("could not found target, defense id: %v", attackResult.DefenseId)
|
||||
continue
|
||||
}
|
||||
attackResult.Damage *= 100
|
||||
damage := attackResult.Damage
|
||||
attackerId := attackResult.AttackerId
|
||||
_ = attackerId
|
||||
currHp := float32(0)
|
||||
if target.fightProp != nil {
|
||||
currHp = target.fightProp[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)]
|
||||
currHp -= damage
|
||||
if currHp < 0 {
|
||||
currHp = 0
|
||||
}
|
||||
target.fightProp[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)] = currHp
|
||||
}
|
||||
|
||||
// PacketEntityFightPropUpdateNotify
|
||||
entityFightPropUpdateNotify := new(proto.EntityFightPropUpdateNotify)
|
||||
entityFightPropUpdateNotify.EntityId = target.id
|
||||
entityFightPropUpdateNotify.FightPropMap = make(map[uint32]float32)
|
||||
entityFightPropUpdateNotify.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)] = currHp
|
||||
for _, player := range s.playerMap {
|
||||
gameManager.SendMsg(proto.ApiEntityFightPropUpdateNotify, player.PlayerID, player.ClientSeq, entityFightPropUpdateNotify)
|
||||
}
|
||||
|
||||
combatData, err := pb.Marshal(hitInfo)
|
||||
if err != nil {
|
||||
logger.LOG.Error("create combat invocations entity hit info error: %v", err)
|
||||
}
|
||||
attack.combatInvokeEntry.CombatData = combatData
|
||||
switch attack.combatInvokeEntry.ForwardType {
|
||||
case proto.ForwardType_FORWARD_TYPE_TO_ALL:
|
||||
combatInvokeEntryListAll = append(combatInvokeEntryListAll, attack.combatInvokeEntry)
|
||||
case proto.ForwardType_FORWARD_TYPE_TO_ALL_EXCEPT_CUR:
|
||||
fallthrough
|
||||
case proto.ForwardType_FORWARD_TYPE_TO_ALL_EXIST_EXCEPT_CUR:
|
||||
if combatInvokeEntryListOther[attack.uid] == nil {
|
||||
combatInvokeEntryListOther[attack.uid] = make([]*proto.CombatInvokeEntry, 0)
|
||||
}
|
||||
combatInvokeEntryListOther[attack.uid] = append(combatInvokeEntryListOther[attack.uid], attack.combatInvokeEntry)
|
||||
case proto.ForwardType_FORWARD_TYPE_TO_HOST:
|
||||
combatInvokeEntryListHost = append(combatInvokeEntryListHost, attack.combatInvokeEntry)
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
// PacketCombatInvocationsNotify
|
||||
if len(combatInvokeEntryListAll) > 0 {
|
||||
combatInvocationsNotifyAll := new(proto.CombatInvocationsNotify)
|
||||
combatInvocationsNotifyAll.InvokeList = combatInvokeEntryListAll
|
||||
for _, player := range s.playerMap {
|
||||
gameManager.SendMsg(proto.ApiCombatInvocationsNotify, player.PlayerID, player.ClientSeq, combatInvocationsNotifyAll)
|
||||
}
|
||||
}
|
||||
if len(combatInvokeEntryListOther) > 0 {
|
||||
for uid, list := range combatInvokeEntryListOther {
|
||||
combatInvocationsNotifyOther := new(proto.CombatInvocationsNotify)
|
||||
combatInvocationsNotifyOther.InvokeList = list
|
||||
for _, player := range s.playerMap {
|
||||
if player.PlayerID == uid {
|
||||
continue
|
||||
}
|
||||
gameManager.SendMsg(proto.ApiCombatInvocationsNotify, player.PlayerID, player.ClientSeq, combatInvocationsNotifyOther)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(combatInvokeEntryListHost) > 0 {
|
||||
combatInvocationsNotifyHost := new(proto.CombatInvocationsNotify)
|
||||
combatInvocationsNotifyHost.InvokeList = combatInvokeEntryListHost
|
||||
gameManager.SendMsg(proto.ApiCombatInvocationsNotify, s.world.owner.PlayerID, s.world.owner.ClientSeq, combatInvocationsNotifyHost)
|
||||
}
|
||||
}
|
||||
64
service/game-hk4e/go.mod
Normal file
64
service/game-hk4e/go.mod
Normal file
@@ -0,0 +1,64 @@
|
||||
module game-hk4e
|
||||
|
||||
go 1.19
|
||||
|
||||
require flswld.com/common v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/common => ../../common
|
||||
|
||||
require flswld.com/logger v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/logger => ../../logger
|
||||
|
||||
require flswld.com/air-api v0.0.0-incompatible // indirect
|
||||
|
||||
replace flswld.com/air-api => ../../air-api
|
||||
|
||||
require flswld.com/light v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/light => ../../light
|
||||
|
||||
require flswld.com/gate-hk4e-api v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/gate-hk4e-api => ../../gate-hk4e-api
|
||||
|
||||
// protobuf
|
||||
require google.golang.org/protobuf v1.28.0
|
||||
|
||||
// mongodb
|
||||
require go.mongodb.org/mongo-driver v1.8.3
|
||||
|
||||
// jwt
|
||||
require github.com/golang-jwt/jwt/v4 v4.4.0
|
||||
|
||||
// csv
|
||||
require github.com/jszwec/csvutil v1.7.1
|
||||
|
||||
// nats
|
||||
require github.com/nats-io/nats.go v1.16.0
|
||||
|
||||
// msgpack
|
||||
require github.com/vmihailenco/msgpack/v5 v5.3.5
|
||||
|
||||
// statsviz
|
||||
require github.com/arl/statsviz v0.5.1
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/golang/snappy v0.0.1 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/klauspost/compress v1.14.4 // indirect
|
||||
github.com/nats-io/nats-server/v2 v2.8.4 // indirect
|
||||
github.com/nats-io/nkeys v0.3.0 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.0.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.2 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
)
|
||||
96
service/game-hk4e/go.sum
Normal file
96
service/game-hk4e/go.sum
Normal file
@@ -0,0 +1,96 @@
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/arl/statsviz v0.5.1 h1:3HY0ZEB738JtguWsD1Tf1pFJZiCcWUmYRq/3OTYKaSI=
|
||||
github.com/arl/statsviz v0.5.1/go.mod h1:zDnjgRblGm1Dyd7J5YlbH7gM1/+HRC+SfkhZhQb5AnM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.0 h1:EmVIxB5jzbllGIjiCV5JG4VylbK3KE400tLGLI1cdfU=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/jszwec/csvutil v1.7.1 h1:btxPxFwms8lHMgl0OIgOQ4Tayfqo0xid0hGkq1kM510=
|
||||
github.com/jszwec/csvutil v1.7.1/go.mod h1:Rpu7Uu9giO9subDyMCIQfHVDuLrcaC36UA4YcJjGBkg=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4=
|
||||
github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a h1:lem6QCvxR0Y28gth9P+wV2K/zYUUAkJ+55U8cpS0p5I=
|
||||
github.com/nats-io/nats-server/v2 v2.8.4 h1:0jQzze1T9mECg8YZEl8+WYUXb9JKluJfCBriPUtluB4=
|
||||
github.com/nats-io/nats-server/v2 v2.8.4/go.mod h1:8zZa+Al3WsESfmgSs98Fi06dRWLH5Bnq90m5bKD/eT4=
|
||||
github.com/nats-io/nats.go v1.16.0 h1:zvLE7fGBQYW6MWaFaRdsgm9qT39PJDQoju+DS8KsO1g=
|
||||
github.com/nats-io/nats.go v1.16.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
|
||||
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
|
||||
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
|
||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
|
||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
go.mongodb.org/mongo-driver v1.8.3 h1:TDKlTkGDKm9kkJVUOAXDK5/fkqKHJVwYQSpoRfB43R4=
|
||||
go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
111
service/game-hk4e/model/Item.go
Normal file
111
service/game-hk4e/model/Item.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"game-hk4e/constant"
|
||||
)
|
||||
|
||||
type Item struct {
|
||||
ItemId uint32 `bson:"itemId"` // 道具id
|
||||
Count uint32 `bson:"count"` // 道具数量
|
||||
Guid uint64 `bson:"-"`
|
||||
}
|
||||
|
||||
func (p *Player) InitAllItem() {
|
||||
for itemId, item := range p.ItemMap {
|
||||
item.Guid = p.GetNextGameObjectGuid()
|
||||
p.ItemMap[itemId] = item
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Player) GetItemGuid(itemId uint32) uint64 {
|
||||
itemInfo := p.ItemMap[itemId]
|
||||
if itemInfo == nil {
|
||||
return 0
|
||||
}
|
||||
return itemInfo.Guid
|
||||
}
|
||||
|
||||
func (p *Player) GetItemCount(itemId uint32) uint32 {
|
||||
isVirtualItem, prop := p.GetVirtualItemProp(itemId)
|
||||
if isVirtualItem {
|
||||
value := p.PropertiesMap[prop]
|
||||
return value
|
||||
} else {
|
||||
itemInfo := p.ItemMap[itemId]
|
||||
if itemInfo == nil {
|
||||
return 0
|
||||
}
|
||||
return itemInfo.Count
|
||||
}
|
||||
}
|
||||
|
||||
// 虚拟道具如下 实际值存在玩家的属性上
|
||||
// 原石 201
|
||||
// 摩拉 202
|
||||
// 创世结晶 203
|
||||
// 树脂 106
|
||||
// 传说任务钥匙 107
|
||||
// 洞天宝钱 204
|
||||
|
||||
func (p *Player) GetVirtualItemProp(itemId uint32) (isVirtualItem bool, prop uint16) {
|
||||
switch itemId {
|
||||
case 106:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_RESIN
|
||||
case 107:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_LEGENDARY_KEY
|
||||
case 201:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_HCOIN
|
||||
case 202:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_SCOIN
|
||||
case 203:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_MCOIN
|
||||
case 204:
|
||||
return true, constant.PlayerPropertyConst.PROP_PLAYER_HOME_COIN
|
||||
default:
|
||||
return false, 0
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Player) AddItem(itemId uint32, count uint32) {
|
||||
isVirtualItem, prop := p.GetVirtualItemProp(itemId)
|
||||
if isVirtualItem {
|
||||
value := p.PropertiesMap[prop]
|
||||
value += count
|
||||
p.PropertiesMap[prop] = value
|
||||
} else {
|
||||
itemInfo := p.ItemMap[itemId]
|
||||
if itemInfo == nil {
|
||||
itemInfo = &Item{
|
||||
ItemId: itemId,
|
||||
Count: 0,
|
||||
Guid: p.GetNextGameObjectGuid(),
|
||||
}
|
||||
}
|
||||
itemInfo.Count += count
|
||||
p.ItemMap[itemId] = itemInfo
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Player) CostItem(itemId uint32, count uint32) {
|
||||
isVirtualItem, prop := p.GetVirtualItemProp(itemId)
|
||||
if isVirtualItem {
|
||||
value := p.PropertiesMap[prop]
|
||||
if value < count {
|
||||
value = 0
|
||||
} else {
|
||||
value -= count
|
||||
}
|
||||
p.PropertiesMap[prop] = value
|
||||
} else {
|
||||
itemInfo := p.ItemMap[itemId]
|
||||
if itemInfo == nil {
|
||||
return
|
||||
}
|
||||
if itemInfo.Count < count {
|
||||
itemInfo.Count = 0
|
||||
} else {
|
||||
itemInfo.Count -= count
|
||||
}
|
||||
p.ItemMap[itemId] = itemInfo
|
||||
}
|
||||
}
|
||||
173
service/game-hk4e/model/avatar.go
Normal file
173
service/game-hk4e/model/avatar.go
Normal file
@@ -0,0 +1,173 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Avatar struct {
|
||||
AvatarId uint32 `bson:"avatarId"` // 角色id
|
||||
Level uint8 `bson:"level"` // 等级
|
||||
Exp uint32 `bson:"exp"` // 经验值
|
||||
Promote uint8 `bson:"promote"` // 突破等阶
|
||||
Satiation uint32 `bson:"satiation"` // 饱食度
|
||||
SatiationPenalty uint32 `bson:"satiationPenalty"` // 饱食度溢出
|
||||
CurrHP float64 `bson:"currHP"` // 当前生命值
|
||||
CurrEnergy float64 `bson:"currEnergy"` // 当前元素能量值
|
||||
FetterList []uint32 `bson:"fetterList"` // 资料解锁条目
|
||||
SkillLevelMap map[uint32]uint32 `bson:"skillLevelMap"` // 技能等级
|
||||
SkillExtraChargeMap map[uint32]uint32 `bson:"skillExtraChargeMap"`
|
||||
ProudSkillBonusMap map[uint32]uint32 `bson:"proudSkillBonusMap"`
|
||||
SkillDepotId uint32 `bson:"skillDepotId"`
|
||||
CoreProudSkillLevel uint8 `bson:"coreProudSkillLevel"` // 已解锁命之座层数
|
||||
TalentIdList []uint32 `bson:"talentIdList"` // 已解锁命之座技能列表
|
||||
ProudSkillList []uint32 `bson:"proudSkillList"` // 被动技能列表
|
||||
FlyCloak uint32 `bson:"flyCloak"` // 当前风之翼
|
||||
Costume uint32 `bson:"costume"` // 当前衣装
|
||||
BornTime int64 `bson:"bornTime"` // 获得时间
|
||||
FetterLevel uint8 `bson:"fetterLevel"` // 好感度等级
|
||||
FetterExp uint32 `bson:"fetterExp"` // 好感度经验
|
||||
NameCardRewardId uint32 `bson:"nameCardRewardId"`
|
||||
NameCardId uint32 `bson:"nameCardId"`
|
||||
Guid uint64 `bson:"-"`
|
||||
EquipGuidList map[uint64]uint64 `bson:"-"`
|
||||
EquipWeapon *Weapon `bson:"-"`
|
||||
EquipReliquaryList []*Reliquary `bson:"-"`
|
||||
FightPropMap map[uint32]float32 `bson:"-"`
|
||||
ExtraAbilityEmbryos map[string]bool `bson:"-"`
|
||||
}
|
||||
|
||||
func (p *Player) InitAllAvatar() {
|
||||
for _, avatar := range p.AvatarMap {
|
||||
p.InitAvatar(avatar)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Player) InitAvatar(avatar *Avatar) {
|
||||
avatarDataConfig := gdc.CONF.AvatarDataMap[int32(avatar.AvatarId)]
|
||||
// 角色战斗属性
|
||||
avatar.FightPropMap = make(map[uint32]float32)
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_NONE)] = 0.0
|
||||
// 白字攻防血
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_ATTACK)] = float32(avatarDataConfig.GetBaseAttackByLevel(avatar.Level))
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_DEFENSE)] = float32(avatarDataConfig.GetBaseDefenseByLevel(avatar.Level))
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_HP)] = float32(avatarDataConfig.GetBaseHpByLevel(avatar.Level))
|
||||
// 白字+绿字攻防血
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_ATTACK)] = float32(avatarDataConfig.GetBaseAttackByLevel(avatar.Level))
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_DEFENSE)] = float32(avatarDataConfig.GetBaseDefenseByLevel(avatar.Level))
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_MAX_HP)] = float32(avatarDataConfig.GetBaseHpByLevel(avatar.Level))
|
||||
// 当前血量
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)] = float32(avatar.CurrHP)
|
||||
// 双暴
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CRITICAL)] = float32(avatarDataConfig.Critical)
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CRITICAL_HURT)] = float32(avatarDataConfig.CriticalHurt)
|
||||
// 元素充能
|
||||
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CHARGE_EFFICIENCY)] = 1.0
|
||||
p.SetCurrEnergy(avatar, avatar.CurrEnergy, true)
|
||||
// guid
|
||||
avatar.Guid = p.GetNextGameObjectGuid()
|
||||
p.GameObjectGuidMap[avatar.Guid] = GameObject(avatar)
|
||||
avatar.EquipGuidList = make(map[uint64]uint64)
|
||||
p.AvatarMap[avatar.AvatarId] = avatar
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Player) AddAvatar(avatarId uint32) {
|
||||
avatarDataConfig := gdc.CONF.AvatarDataMap[int32(avatarId)]
|
||||
skillDepotId := int32(0)
|
||||
// 主角要单独设置
|
||||
if avatarId == 10000005 {
|
||||
skillDepotId = 504
|
||||
} else if avatarId == 10000007 {
|
||||
skillDepotId = 704
|
||||
} else {
|
||||
skillDepotId = avatarDataConfig.SkillDepotId
|
||||
}
|
||||
avatarSkillDepotDataConfig := gdc.CONF.AvatarSkillDepotDataMap[skillDepotId]
|
||||
avatar := &Avatar{
|
||||
AvatarId: avatarId,
|
||||
Level: 1,
|
||||
Exp: 0,
|
||||
Promote: 0,
|
||||
Satiation: 0,
|
||||
SatiationPenalty: 0,
|
||||
CurrHP: 0,
|
||||
CurrEnergy: 0,
|
||||
FetterList: nil,
|
||||
SkillLevelMap: make(map[uint32]uint32),
|
||||
SkillExtraChargeMap: make(map[uint32]uint32),
|
||||
ProudSkillBonusMap: nil,
|
||||
SkillDepotId: uint32(avatarSkillDepotDataConfig.Id),
|
||||
CoreProudSkillLevel: 0,
|
||||
TalentIdList: make([]uint32, 0),
|
||||
ProudSkillList: make([]uint32, 0),
|
||||
FlyCloak: 140001,
|
||||
Costume: 0,
|
||||
BornTime: time.Now().Unix(),
|
||||
FetterLevel: 1,
|
||||
FetterExp: 0,
|
||||
NameCardRewardId: 0,
|
||||
NameCardId: 0,
|
||||
Guid: 0,
|
||||
EquipGuidList: nil,
|
||||
EquipWeapon: nil,
|
||||
EquipReliquaryList: nil,
|
||||
FightPropMap: nil,
|
||||
ExtraAbilityEmbryos: nil,
|
||||
}
|
||||
|
||||
if avatarSkillDepotDataConfig.EnergySkill > 0 {
|
||||
avatar.SkillLevelMap[uint32(avatarSkillDepotDataConfig.EnergySkill)] = 1
|
||||
}
|
||||
for _, skillId := range avatarSkillDepotDataConfig.Skills {
|
||||
if skillId > 0 {
|
||||
avatar.SkillLevelMap[uint32(skillId)] = 1
|
||||
}
|
||||
}
|
||||
for _, openData := range avatarSkillDepotDataConfig.InherentProudSkillOpens {
|
||||
if openData.ProudSkillGroupId == 0 {
|
||||
continue
|
||||
}
|
||||
if openData.NeedAvatarPromoteLevel <= int32(avatar.Promote) {
|
||||
proudSkillId := (openData.ProudSkillGroupId * 100) + 1
|
||||
// TODO if GameData.getProudSkillDataMap().containsKey(proudSkillId) java
|
||||
avatar.ProudSkillList = append(avatar.ProudSkillList, uint32(proudSkillId))
|
||||
}
|
||||
}
|
||||
avatar.CurrHP = avatarDataConfig.GetBaseHpByLevel(avatar.Level)
|
||||
|
||||
p.InitAvatar(avatar)
|
||||
p.AvatarMap[avatarId] = avatar
|
||||
}
|
||||
|
||||
func (p *Player) SetCurrEnergy(avatar *Avatar, value float64, max bool) {
|
||||
avatarDataConfig := gdc.CONF.AvatarDataMap[int32(avatar.AvatarId)]
|
||||
avatarSkillDepotDataConfig := gdc.CONF.AvatarSkillDepotDataMap[avatarDataConfig.SkillDepotId]
|
||||
if avatarSkillDepotDataConfig == nil || avatarSkillDepotDataConfig.EnergySkillData == nil {
|
||||
return
|
||||
}
|
||||
element := avatarSkillDepotDataConfig.ElementType
|
||||
avatar.FightPropMap[uint32(element.MaxEnergyProp)] = float32(avatarSkillDepotDataConfig.EnergySkillData.CostElemVal)
|
||||
if max {
|
||||
avatar.FightPropMap[uint32(element.CurrEnergyProp)] = float32(avatarSkillDepotDataConfig.EnergySkillData.CostElemVal)
|
||||
} else {
|
||||
avatar.FightPropMap[uint32(element.CurrEnergyProp)] = float32(value)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Player) WearWeapon(avatarId uint32, weaponId uint64) {
|
||||
avatar := p.AvatarMap[avatarId]
|
||||
weapon := p.WeaponMap[weaponId]
|
||||
avatar.EquipWeapon = weapon
|
||||
weapon.AvatarId = avatarId
|
||||
avatar.EquipGuidList[weapon.Guid] = weapon.Guid
|
||||
}
|
||||
|
||||
func (p *Player) TakeOffWeapon(avatarId uint32, weaponId uint64) {
|
||||
avatar := p.AvatarMap[avatarId]
|
||||
weapon := p.WeaponMap[weaponId]
|
||||
avatar.EquipWeapon = nil
|
||||
weapon.AvatarId = 0
|
||||
delete(avatar.EquipGuidList, weapon.Guid)
|
||||
}
|
||||
16
service/game-hk4e/model/chat.go
Normal file
16
service/game-hk4e/model/chat.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package model
|
||||
|
||||
const (
|
||||
ChatMsgTypeText = iota
|
||||
ChatMsgTypeIcon
|
||||
)
|
||||
|
||||
type ChatMsg struct {
|
||||
Time uint32 `bson:"time"`
|
||||
ToUid uint32 `bson:"toUid"`
|
||||
Uid uint32 `bson:"uid"`
|
||||
IsRead bool `bson:"isRead"`
|
||||
MsgType uint8 `bson:"msgType"`
|
||||
Text string `bson:"text"`
|
||||
Icon uint32 `bson:"icon"`
|
||||
}
|
||||
51
service/game-hk4e/model/drop.go
Normal file
51
service/game-hk4e/model/drop.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package model
|
||||
|
||||
type GachaPoolInfo struct {
|
||||
GachaType uint32 `bson:"gachaType"` // 卡池类型
|
||||
OrangeTimes uint32 `bson:"orangeTimes"` // 5星保底计数
|
||||
PurpleTimes uint32 `bson:"purpleTimes"` // 4星保底计数
|
||||
MustGetUpOrange bool `bson:"mustGetUpOrange"` // 是否5星大保底
|
||||
MustGetUpPurple bool `bson:"mustGetUpPurple"` // 是否4星大保底
|
||||
}
|
||||
|
||||
type DropInfo struct {
|
||||
GachaPoolInfo map[uint32]*GachaPoolInfo `bson:"gachaPoolInfo"`
|
||||
}
|
||||
|
||||
func NewDropInfo() (r *DropInfo) {
|
||||
r = new(DropInfo)
|
||||
r.GachaPoolInfo = make(map[uint32]*GachaPoolInfo)
|
||||
r.GachaPoolInfo[300] = &GachaPoolInfo{
|
||||
// 温迪
|
||||
GachaType: 300,
|
||||
OrangeTimes: 0,
|
||||
PurpleTimes: 0,
|
||||
MustGetUpOrange: false,
|
||||
MustGetUpPurple: false,
|
||||
}
|
||||
r.GachaPoolInfo[400] = &GachaPoolInfo{
|
||||
// 可莉
|
||||
GachaType: 400,
|
||||
OrangeTimes: 0,
|
||||
PurpleTimes: 0,
|
||||
MustGetUpOrange: false,
|
||||
MustGetUpPurple: false,
|
||||
}
|
||||
r.GachaPoolInfo[431] = &GachaPoolInfo{
|
||||
// 阿莫斯之弓&天空之傲
|
||||
GachaType: 431,
|
||||
OrangeTimes: 0,
|
||||
PurpleTimes: 0,
|
||||
MustGetUpOrange: false,
|
||||
MustGetUpPurple: false,
|
||||
}
|
||||
r.GachaPoolInfo[201] = &GachaPoolInfo{
|
||||
// 常驻
|
||||
GachaType: 201,
|
||||
OrangeTimes: 0,
|
||||
PurpleTimes: 0,
|
||||
MustGetUpOrange: false,
|
||||
MustGetUpPurple: false,
|
||||
}
|
||||
return r
|
||||
}
|
||||
93
service/game-hk4e/model/player.go
Normal file
93
service/game-hk4e/model/player.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
const (
|
||||
DbInsert = iota
|
||||
DbDelete
|
||||
DbUpdate
|
||||
DbNormal
|
||||
DbOffline
|
||||
)
|
||||
|
||||
const (
|
||||
SceneNone = iota
|
||||
SceneInitFinish
|
||||
SceneEnterDone
|
||||
)
|
||||
|
||||
type GameObject interface {
|
||||
}
|
||||
|
||||
type Player struct {
|
||||
// 离线数据
|
||||
ID primitive.ObjectID `bson:"_id,omitempty"`
|
||||
PlayerID uint32 `bson:"playerID"` // 玩家uid
|
||||
NickName string `bson:"nickname"` // 玩家昵称
|
||||
Signature string `bson:"signature"` // 玩家签名
|
||||
HeadImage uint32 `bson:"headImage"` // 玩家头像
|
||||
NameCard uint32 `bson:"nameCard"` // 当前名片
|
||||
NameCardList []uint32 `bson:"nameCardList"` // 已解锁名片列表
|
||||
FriendList map[uint32]bool `bson:"friendList"` // 好友uid列表
|
||||
FriendApplyList map[uint32]bool `bson:"friendApplyList"` // 好友申请uid列表
|
||||
OfflineTime uint32 `bson:"offlineTime"` // 离线时间点
|
||||
OnlineTime uint32 `bson:"onlineTime"` // 上线时间点
|
||||
TotalOnlineTime uint32 `bson:"totalOnlineTime"` // 玩家累计在线时长
|
||||
PropertiesMap map[uint16]uint32 `bson:"propertiesMap"` // 玩家自身相关的一些属性
|
||||
RegionId uint32 `bson:"regionId"` // regionId
|
||||
FlyCloakList []uint32 `bson:"flyCloakList"` // 风之翼列表
|
||||
CostumeList []uint32 `bson:"costumeList"` // 角色衣装列表
|
||||
SceneId uint32 `bson:"sceneId"` // 场景
|
||||
Pos *Vector `bson:"pos"` // 玩家坐标
|
||||
Rot *Vector `bson:"rot"` // 玩家朝向
|
||||
ItemMap map[uint32]*Item `bson:"itemMap"` // 玩家统一大背包仓库
|
||||
WeaponMap map[uint64]*Weapon `bson:"weaponMap"` // 玩家武器背包
|
||||
ReliquaryMap map[uint64]*Reliquary `bson:"reliquaryMap"` // 玩家圣遗物背包
|
||||
TeamConfig *TeamInfo `bson:"teamConfig"` // 队伍配置
|
||||
AvatarMap map[uint32]*Avatar `bson:"avatarMap"` // 角色信息
|
||||
DropInfo *DropInfo `bson:"dropInfo"` // 掉落信息
|
||||
MainCharAvatarId uint32 `bson:"mainCharAvatarId"` // 主角id
|
||||
ChatMsgMap map[uint32][]*ChatMsg `bson:"chatMsgMap"` // 聊天信息
|
||||
// 在线数据
|
||||
EnterSceneToken uint32 `bson:"-"` // 玩家的世界进入令牌
|
||||
DbState int `bson:"-"` // 数据库存档状态
|
||||
WorldId uint32 `bson:"-"` // 所在的世界id
|
||||
PeerId uint32 `bson:"-"` // 多人世界的玩家编号
|
||||
GameObjectGuidCounter uint64 `bson:"-"` // 游戏对象guid计数器
|
||||
ClientTime uint32 `bson:"-"` // 玩家客户端的本地时钟
|
||||
ClientRTT uint32 `bson:"-"` // 玩家客户端往返时延
|
||||
GameObjectGuidMap map[uint64]GameObject `bson:"-"` // 游戏对象guid映射表
|
||||
Online bool `bson:"-"` // 在线状态
|
||||
Pause bool `bson:"-"` // 暂停状态
|
||||
SceneLoadState int `bson:"-"` // 场景加载状态
|
||||
CoopApplyMap map[uint32]int64 `bson:"-"` // 敲门申请的玩家uid及时间
|
||||
ClientSeq uint32 `bson:"-"`
|
||||
}
|
||||
|
||||
func (p *Player) GetNextGameObjectGuid() uint64 {
|
||||
p.GameObjectGuidCounter++
|
||||
return uint64(p.PlayerID)<<32 + p.GameObjectGuidCounter
|
||||
}
|
||||
|
||||
func (p *Player) InitAll() {
|
||||
p.GameObjectGuidMap = make(map[uint64]GameObject)
|
||||
p.CoopApplyMap = make(map[uint32]int64)
|
||||
p.InitAllAvatar()
|
||||
p.InitAllWeapon()
|
||||
p.InitAllItem()
|
||||
p.InitAllReliquary()
|
||||
}
|
||||
|
||||
func (p *Player) InitAllReliquary() {
|
||||
for reliquaryId, reliquary := range p.ReliquaryMap {
|
||||
reliquary.Guid = p.GetNextGameObjectGuid()
|
||||
p.ReliquaryMap[reliquaryId] = reliquary
|
||||
if reliquary.AvatarId != 0 {
|
||||
avatar := p.AvatarMap[reliquary.AvatarId]
|
||||
avatar.EquipGuidList[reliquary.Guid] = reliquary.Guid
|
||||
avatar.EquipReliquaryList = append(avatar.EquipReliquaryList, reliquary)
|
||||
}
|
||||
}
|
||||
}
|
||||
16
service/game-hk4e/model/reliquary.go
Normal file
16
service/game-hk4e/model/reliquary.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package model
|
||||
|
||||
type Reliquary struct {
|
||||
ReliquaryId uint64 `bson:"reliquaryId"` // 圣遗物的唯一id
|
||||
ItemId uint32 `bson:"itemId"` // 圣遗物的道具id
|
||||
Level uint8 `bson:"level"` // 等级
|
||||
Exp uint32 `bson:"exp"` // 当前经验值
|
||||
TotalExp uint32 `bson:"totalExp"` // 升级所需总经验值
|
||||
Promote uint8 `bson:"promote"` // 突破等阶
|
||||
Lock bool `bson:"lock"` // 锁定状态
|
||||
AffixIdList []uint32 `bson:"affixIdList"` // 词缀
|
||||
Refinement uint8 `bson:"refinement"` // 精炼等阶
|
||||
MainPropId uint32 `bson:"mainPropId"` // 主词条id
|
||||
AvatarId uint32 `bson:"avatarId"` // 装备角色id
|
||||
Guid uint64 `bson:"-"`
|
||||
}
|
||||
115
service/game-hk4e/model/team.go
Normal file
115
service/game-hk4e/model/team.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
gdc "game-hk4e/config"
|
||||
"game-hk4e/constant"
|
||||
)
|
||||
|
||||
type Team struct {
|
||||
Name string `bson:"name"`
|
||||
AvatarIdList []uint32 `bson:"avatarIdList"`
|
||||
}
|
||||
|
||||
type TeamInfo struct {
|
||||
TeamList []*Team `bson:"teamList"`
|
||||
CurrTeamIndex uint8 `bson:"currTeamIndex"`
|
||||
CurrAvatarIndex uint8 `bson:"currAvatarIndex"`
|
||||
TeamResonances map[uint16]bool `bson:"-"`
|
||||
TeamResonancesConfig map[int32]bool `bson:"-"`
|
||||
}
|
||||
|
||||
func NewTeamInfo() (r *TeamInfo) {
|
||||
r = &TeamInfo{
|
||||
TeamList: []*Team{
|
||||
{Name: "冒险", AvatarIdList: make([]uint32, 4)},
|
||||
{Name: "委托", AvatarIdList: make([]uint32, 4)},
|
||||
{Name: "秘境", AvatarIdList: make([]uint32, 4)},
|
||||
{Name: "联机", AvatarIdList: make([]uint32, 4)},
|
||||
},
|
||||
CurrTeamIndex: 0,
|
||||
CurrAvatarIndex: 0,
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (t *TeamInfo) UpdateTeam() {
|
||||
activeTeam := t.GetActiveTeam()
|
||||
// 队伍元素共鸣
|
||||
t.TeamResonances = make(map[uint16]bool)
|
||||
t.TeamResonancesConfig = make(map[int32]bool)
|
||||
teamElementTypeCountMap := make(map[uint16]uint8)
|
||||
avatarSkillDepotDataMapConfig := gdc.CONF.AvatarSkillDepotDataMap
|
||||
for _, avatarId := range activeTeam.AvatarIdList {
|
||||
if avatarId == 0 {
|
||||
break
|
||||
}
|
||||
skillData := avatarSkillDepotDataMapConfig[int32(avatarId)]
|
||||
if skillData != nil {
|
||||
teamElementTypeCountMap[skillData.ElementType.Value] += 1
|
||||
}
|
||||
}
|
||||
for k, v := range teamElementTypeCountMap {
|
||||
if v >= 2 {
|
||||
element := constant.ElementTypeConst.VALUE_MAP[k]
|
||||
if element.TeamResonanceId != 0 {
|
||||
t.TeamResonances[element.TeamResonanceId] = true
|
||||
t.TeamResonancesConfig[element.ConfigHash] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(t.TeamResonances) == 0 {
|
||||
t.TeamResonances[constant.ElementTypeConst.Default.TeamResonanceId] = true
|
||||
t.TeamResonancesConfig[int32(constant.ElementTypeConst.Default.TeamResonanceId)] = true
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TeamInfo) GetActiveTeamId() uint8 {
|
||||
return t.CurrTeamIndex + 1
|
||||
}
|
||||
|
||||
func (t *TeamInfo) GetTeamByIndex(teamIndex uint8) *Team {
|
||||
if t.TeamList == nil {
|
||||
return nil
|
||||
}
|
||||
if teamIndex >= uint8(len(t.TeamList)) {
|
||||
return nil
|
||||
}
|
||||
activeTeam := t.TeamList[teamIndex]
|
||||
return activeTeam
|
||||
}
|
||||
|
||||
func (t *TeamInfo) GetActiveTeam() *Team {
|
||||
return t.GetTeamByIndex(t.CurrTeamIndex)
|
||||
}
|
||||
|
||||
func (t *TeamInfo) ClearTeamAvatar(teamIndex uint8) {
|
||||
team := t.GetTeamByIndex(teamIndex)
|
||||
if team == nil {
|
||||
return
|
||||
}
|
||||
team.AvatarIdList = make([]uint32, 4)
|
||||
}
|
||||
|
||||
func (t *TeamInfo) AddAvatarToTeam(avatarId uint32, teamIndex uint8) {
|
||||
team := t.GetTeamByIndex(teamIndex)
|
||||
if team == nil {
|
||||
return
|
||||
}
|
||||
for i, v := range team.AvatarIdList {
|
||||
if v == 0 {
|
||||
team.AvatarIdList[i] = avatarId
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TeamInfo) GetActiveAvatarId() uint32 {
|
||||
activeTeam := t.GetActiveTeam()
|
||||
if activeTeam == nil {
|
||||
return 0
|
||||
}
|
||||
if t.CurrAvatarIndex >= uint8(len(activeTeam.AvatarIdList)) {
|
||||
return 0
|
||||
}
|
||||
return activeTeam.AvatarIdList[t.CurrAvatarIndex]
|
||||
}
|
||||
7
service/game-hk4e/model/vector.go
Normal file
7
service/game-hk4e/model/vector.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package model
|
||||
|
||||
type Vector struct {
|
||||
X float64 `bson:"x"`
|
||||
Y float64 `bson:"y"`
|
||||
Z float64 `bson:"z"`
|
||||
}
|
||||
76
service/game-hk4e/model/weapon.go
Normal file
76
service/game-hk4e/model/weapon.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
gdc "game-hk4e/config"
|
||||
)
|
||||
|
||||
type Weapon struct {
|
||||
WeaponId uint64 `bson:"weaponId"` // 武器的唯一id
|
||||
ItemId uint32 `bson:"itemId"` // 武器的道具id
|
||||
Level uint8 `bson:"level"` // 等级
|
||||
Exp uint32 `bson:"exp"` // 当前经验值
|
||||
TotalExp uint32 `bson:"totalExp"` // 升级所需总经验值
|
||||
Promote uint8 `bson:"promote"` // 突破等阶
|
||||
Lock bool `bson:"lock"` // 锁定状态
|
||||
AffixIdList []uint32 `bson:"affixIdList"` // 词缀
|
||||
Refinement uint8 `bson:"refinement"` // 精炼等阶
|
||||
MainPropId uint32 `bson:"mainPropId"` // 主词条id
|
||||
AvatarId uint32 `bson:"avatarId"` // 装备角色id
|
||||
Guid uint64 `bson:"-"`
|
||||
}
|
||||
|
||||
func (p *Player) InitWeapon(weapon *Weapon) {
|
||||
weapon.Guid = p.GetNextGameObjectGuid()
|
||||
p.GameObjectGuidMap[weapon.Guid] = GameObject(weapon)
|
||||
p.WeaponMap[weapon.WeaponId] = weapon
|
||||
if weapon.AvatarId != 0 {
|
||||
avatar := p.AvatarMap[weapon.AvatarId]
|
||||
avatar.EquipGuidList[weapon.Guid] = weapon.Guid
|
||||
avatar.EquipWeapon = weapon
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Player) InitAllWeapon() {
|
||||
for _, weapon := range p.WeaponMap {
|
||||
p.InitWeapon(weapon)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Player) GetWeaponGuid(weaponId uint64) uint64 {
|
||||
weaponInfo := p.WeaponMap[weaponId]
|
||||
if weaponInfo == nil {
|
||||
return 0
|
||||
}
|
||||
return weaponInfo.Guid
|
||||
}
|
||||
|
||||
func (p *Player) GetWeapon(weaponId uint64) *Weapon {
|
||||
return p.WeaponMap[weaponId]
|
||||
}
|
||||
|
||||
func (p *Player) AddWeapon(itemId uint32, weaponId uint64) {
|
||||
weapon := &Weapon{
|
||||
WeaponId: weaponId,
|
||||
ItemId: itemId,
|
||||
Level: 1,
|
||||
Exp: 0,
|
||||
TotalExp: 0,
|
||||
Promote: 0,
|
||||
Lock: false,
|
||||
AffixIdList: make([]uint32, 0),
|
||||
Refinement: 0,
|
||||
MainPropId: 0,
|
||||
Guid: 0,
|
||||
}
|
||||
itemDataConfig := gdc.CONF.ItemDataMap[int32(itemId)]
|
||||
if itemDataConfig.SkillAffix != nil {
|
||||
for _, skillAffix := range itemDataConfig.SkillAffix {
|
||||
if skillAffix > 0 {
|
||||
weapon.AffixIdList = append(weapon.AffixIdList, uint32(skillAffix))
|
||||
}
|
||||
}
|
||||
}
|
||||
p.InitWeapon(weapon)
|
||||
p.WeaponMap[weaponId] = weapon
|
||||
}
|
||||
91
service/game-hk4e/mq/mq.go
Normal file
91
service/game-hk4e/mq/mq.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package mq
|
||||
|
||||
import (
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/gate-hk4e-api/proto"
|
||||
"flswld.com/logger"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type MessageQueue struct {
|
||||
natsConn *nats.Conn
|
||||
natsMsgChan chan *nats.Msg
|
||||
netMsgInput chan *proto.NetMsg
|
||||
netMsgOutput chan *proto.NetMsg
|
||||
apiProtoMap *proto.ApiProtoMap
|
||||
}
|
||||
|
||||
func NewMessageQueue(netMsgInput chan *proto.NetMsg, netMsgOutput chan *proto.NetMsg) (r *MessageQueue) {
|
||||
r = new(MessageQueue)
|
||||
conn, err := nats.Connect(config.CONF.MQ.NatsUrl)
|
||||
if err != nil {
|
||||
logger.LOG.Error("connect nats error: %v", err)
|
||||
return nil
|
||||
}
|
||||
r.natsConn = conn
|
||||
r.natsMsgChan = make(chan *nats.Msg, 10000)
|
||||
_, err = r.natsConn.ChanSubscribe("GAME_HK4E", r.natsMsgChan)
|
||||
if err != nil {
|
||||
logger.LOG.Error("nats subscribe error: %v", err)
|
||||
return nil
|
||||
}
|
||||
r.netMsgInput = netMsgInput
|
||||
r.netMsgOutput = netMsgOutput
|
||||
r.apiProtoMap = proto.NewApiProtoMap()
|
||||
return r
|
||||
}
|
||||
|
||||
func (m *MessageQueue) Start() {
|
||||
go m.startRecvHandler()
|
||||
go m.startSendHandler()
|
||||
}
|
||||
|
||||
func (m *MessageQueue) Close() {
|
||||
m.natsConn.Close()
|
||||
}
|
||||
|
||||
func (m *MessageQueue) startRecvHandler() {
|
||||
for {
|
||||
natsMsg := <-m.natsMsgChan
|
||||
// msgpack NetMsg
|
||||
netMsg := new(proto.NetMsg)
|
||||
err := msgpack.Unmarshal(natsMsg.Data, netMsg)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse bin to net msg error: %v", err)
|
||||
continue
|
||||
}
|
||||
if netMsg.EventId == proto.NormalMsg || netMsg.EventId == proto.UserRegNotify {
|
||||
// protobuf PayloadMessage
|
||||
payloadMessage := m.apiProtoMap.GetProtoObjByApiId(netMsg.ApiId)
|
||||
err = pb.Unmarshal(netMsg.PayloadMessageData, payloadMessage)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse bin to payload msg error: %v", err)
|
||||
continue
|
||||
}
|
||||
netMsg.PayloadMessage = payloadMessage
|
||||
}
|
||||
m.netMsgOutput <- netMsg
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MessageQueue) startSendHandler() {
|
||||
for {
|
||||
netMsg := <-m.netMsgInput
|
||||
// protobuf PayloadMessage 已在上一层完成
|
||||
// msgpack NetMsg
|
||||
netMsgData, err := msgpack.Marshal(netMsg)
|
||||
if err != nil {
|
||||
logger.LOG.Error("parse net msg to bin error: %v", err)
|
||||
continue
|
||||
}
|
||||
natsMsg := nats.NewMsg("GATE_HK4E")
|
||||
natsMsg.Data = netMsgData
|
||||
err = m.natsConn.PublishMsg(natsMsg)
|
||||
if err != nil {
|
||||
logger.LOG.Error("nats publish msg error: %v", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
29
service/game-hk4e/rpc/rpc.go
Normal file
29
service/game-hk4e/rpc/rpc.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"flswld.com/gate-hk4e-api/gm"
|
||||
"flswld.com/light"
|
||||
)
|
||||
|
||||
type RpcManager struct {
|
||||
hk4eGatewayConsumer *light.Consumer
|
||||
}
|
||||
|
||||
func NewRpcManager(hk4eGatewayConsumer *light.Consumer) (r *RpcManager) {
|
||||
r = new(RpcManager)
|
||||
r.hk4eGatewayConsumer = hk4eGatewayConsumer
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *RpcManager) SendKickPlayerToHk4eGateway(userId uint32) {
|
||||
info := new(gm.KickPlayerInfo)
|
||||
info.UserId = userId
|
||||
// 客户端提示信息为服务器断开连接
|
||||
info.Reason = uint32(5)
|
||||
var result bool
|
||||
ok := r.hk4eGatewayConsumer.CallFunction("RpcManager", "KickPlayer", &info, &result)
|
||||
if ok == true && result == true {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
11
service/gm-hk4e/cmd/application.toml
Normal file
11
service/gm-hk4e/cmd/application.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
http_port = 9004
|
||||
|
||||
[logger]
|
||||
level = "DEBUG"
|
||||
method = "CONSOLE"
|
||||
track_line = true
|
||||
|
||||
[air]
|
||||
addr = "air"
|
||||
port = 8086
|
||||
service_name = "gm-hk4e-app"
|
||||
48
service/gm-hk4e/cmd/main.go
Normal file
48
service/gm-hk4e/cmd/main.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/light"
|
||||
"flswld.com/logger"
|
||||
"gm-hk4e/controller"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filePath := "./application.toml"
|
||||
config.InitConfig(filePath)
|
||||
|
||||
logger.InitLogger()
|
||||
logger.LOG.Info("gm hk4e start")
|
||||
|
||||
httpProvider := light.NewHttpProvider()
|
||||
|
||||
// 认证服务
|
||||
rpcWaterAuthConsumer := light.NewRpcConsumer("water-auth")
|
||||
|
||||
rpcHk4eGatewayConsumer := light.NewRpcConsumer("hk4e-gateway")
|
||||
|
||||
_ = controller.NewController(rpcWaterAuthConsumer, rpcHk4eGatewayConsumer)
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
|
||||
for {
|
||||
s := <-c
|
||||
logger.LOG.Info("get a signal %s", s.String())
|
||||
switch s {
|
||||
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
|
||||
rpcWaterAuthConsumer.CloseRpcConsumer()
|
||||
rpcHk4eGatewayConsumer.CloseRpcConsumer()
|
||||
httpProvider.CloseHttpProvider()
|
||||
logger.LOG.Info("gm hk4e exit")
|
||||
time.Sleep(time.Second)
|
||||
return
|
||||
case syscall.SIGHUP:
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
75
service/gm-hk4e/controller/controller.go
Normal file
75
service/gm-hk4e/controller/controller.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"flswld.com/common/config"
|
||||
"flswld.com/light"
|
||||
waterAuth "flswld.com/water-api/auth"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
rpcWaterAuthConsumer *light.Consumer
|
||||
rpcHk4eGatewayConsumer *light.Consumer
|
||||
}
|
||||
|
||||
func NewController(rpcWaterAuthConsumer *light.Consumer, rpcHk4eGatewayConsumer *light.Consumer) (r *Controller) {
|
||||
r = new(Controller)
|
||||
r.rpcWaterAuthConsumer = rpcWaterAuthConsumer
|
||||
r.rpcHk4eGatewayConsumer = rpcHk4eGatewayConsumer
|
||||
go r.registerRouter()
|
||||
return r
|
||||
}
|
||||
|
||||
func (c *Controller) getAccessToken(context *gin.Context) string {
|
||||
accessToken := context.GetHeader("Authorization")
|
||||
divIndex := strings.Index(accessToken, " ")
|
||||
if divIndex > 0 {
|
||||
payload := accessToken[divIndex+1:]
|
||||
return payload
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// access_token鉴权
|
||||
func (c *Controller) authorize() gin.HandlerFunc {
|
||||
return func(context *gin.Context) {
|
||||
valid, err := waterAuth.WaterVerifyAccessToken(c.rpcWaterAuthConsumer, c.getAccessToken(context))
|
||||
if err == nil && valid == true {
|
||||
// 验证通过
|
||||
context.Next()
|
||||
return
|
||||
}
|
||||
// 验证不通过
|
||||
context.Abort()
|
||||
context.JSON(http.StatusOK, gin.H{
|
||||
"code": "10001",
|
||||
"msg": "没有访问权限",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) registerRouter() {
|
||||
if config.CONF.Logger.Level == "DEBUG" {
|
||||
gin.SetMode(gin.DebugMode)
|
||||
} else {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
engine := gin.Default()
|
||||
// gacha
|
||||
engine.GET("/gm/gacha", c.gacha)
|
||||
engine.GET("/gm/gacha/details", c.gachaDetails)
|
||||
engine.Use(c.authorize())
|
||||
// gate
|
||||
engine.POST("/gm/gate/state", c.changeGateState)
|
||||
engine.POST("/gm/gate/kick", c.kickPlayer)
|
||||
engine.GET("/gm/gate/online", c.getOnlineUser)
|
||||
engine.POST("/gm/gate/forbid", c.forbidUser)
|
||||
engine.POST("/gm/gate/forbid/cancel", c.unForbidUser)
|
||||
port := strconv.FormatInt(int64(config.CONF.HttpPort), 10)
|
||||
portStr := ":" + port
|
||||
_ = engine.Run(portStr)
|
||||
}
|
||||
65
service/gm-hk4e/controller/gacha_controller.go
Normal file
65
service/gm-hk4e/controller/gacha_controller.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"flswld.com/common/entity/dto"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type UserInfo struct {
|
||||
UserId uint32 `json:"userId"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func (c *Controller) gacha(context *gin.Context) {
|
||||
jwtStr := context.Query("jwt")
|
||||
token, err := jwt.ParseWithClaims(jwtStr, new(UserInfo), func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte("flswld"), nil
|
||||
})
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10005, "验签失败", nil))
|
||||
return
|
||||
}
|
||||
if !token.Valid {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10005, "验签失败", nil))
|
||||
return
|
||||
}
|
||||
info, ok := token.Claims.(*UserInfo)
|
||||
if !ok {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10005, "验签失败", nil))
|
||||
return
|
||||
}
|
||||
gachaType := context.Query("gachaType")
|
||||
rsp := map[string]any{
|
||||
"uid": info.UserId,
|
||||
"gachaType": gachaType,
|
||||
}
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(0, "成功", rsp))
|
||||
}
|
||||
|
||||
func (c *Controller) gachaDetails(context *gin.Context) {
|
||||
jwtStr := context.Query("jwt")
|
||||
token, err := jwt.ParseWithClaims(jwtStr, new(UserInfo), func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte("flswld"), nil
|
||||
})
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10005, "验签失败", nil))
|
||||
return
|
||||
}
|
||||
if !token.Valid {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10005, "验签失败", nil))
|
||||
return
|
||||
}
|
||||
info, ok := token.Claims.(*UserInfo)
|
||||
if !ok {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10005, "验签失败", nil))
|
||||
return
|
||||
}
|
||||
scheduleId := context.Query("scheduleId")
|
||||
rsp := map[string]any{
|
||||
"uid": info.UserId,
|
||||
"scheduleId": scheduleId,
|
||||
}
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(0, "成功", rsp))
|
||||
}
|
||||
161
service/gm-hk4e/controller/gate_controller.go
Normal file
161
service/gm-hk4e/controller/gate_controller.go
Normal file
@@ -0,0 +1,161 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"flswld.com/common/entity/dto"
|
||||
"flswld.com/gate-hk4e-api/gm"
|
||||
waterAuth "flswld.com/water-api/auth"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (c *Controller) changeGateState(context *gin.Context) {
|
||||
accessToken := c.getAccessToken(context)
|
||||
user, err := waterAuth.WaterQueryUserByAccessToken(c.rpcWaterAuthConsumer, accessToken)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(1001, "服务器内部错误", nil))
|
||||
return
|
||||
}
|
||||
if !user.IsAdmin {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10001, "没有访问权限", nil))
|
||||
return
|
||||
}
|
||||
stateStr := context.Query("state")
|
||||
state, err := strconv.ParseBool(stateStr)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10003, "参数错误", nil))
|
||||
return
|
||||
}
|
||||
var res bool
|
||||
ok := c.rpcHk4eGatewayConsumer.CallFunction("RpcManager", "ChangeGateOpenState", &state, &res)
|
||||
if ok == true && res == true {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(0, "操作成功", nil))
|
||||
} else {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "操作失败", nil))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) kickPlayer(context *gin.Context) {
|
||||
accessToken := c.getAccessToken(context)
|
||||
user, err := waterAuth.WaterQueryUserByAccessToken(c.rpcWaterAuthConsumer, accessToken)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(1001, "服务器内部错误", nil))
|
||||
return
|
||||
}
|
||||
if !user.IsAdmin {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10001, "没有访问权限", nil))
|
||||
return
|
||||
}
|
||||
uidStr := context.Query("uid")
|
||||
reasonStr := context.Query("reason")
|
||||
uid, err := strconv.ParseInt(uidStr, 10, 64)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10003, "参数错误", nil))
|
||||
return
|
||||
}
|
||||
reason, err := strconv.ParseInt(reasonStr, 10, 64)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10003, "参数错误", nil))
|
||||
return
|
||||
}
|
||||
info := new(gm.KickPlayerInfo)
|
||||
info.UserId = uint32(uid)
|
||||
info.Reason = uint32(reason)
|
||||
var result bool
|
||||
ok := c.rpcHk4eGatewayConsumer.CallFunction("RpcManager", "KickPlayer", &info, &result)
|
||||
if ok == true && result == true {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(0, "操作成功", nil))
|
||||
} else {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "操作失败", nil))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) getOnlineUser(context *gin.Context) {
|
||||
accessToken := c.getAccessToken(context)
|
||||
user, err := waterAuth.WaterQueryUserByAccessToken(c.rpcWaterAuthConsumer, accessToken)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(1001, "服务器内部错误", nil))
|
||||
return
|
||||
}
|
||||
if !user.IsAdmin {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10001, "没有访问权限", nil))
|
||||
return
|
||||
}
|
||||
uidStr := context.Query("uid")
|
||||
uid, err := strconv.ParseInt(uidStr, 10, 64)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10003, "参数错误", nil))
|
||||
return
|
||||
}
|
||||
list := new(gm.OnlineUserList)
|
||||
list.UserList = make([]*gm.OnlineUserInfo, 0)
|
||||
userId := uint32(uid)
|
||||
ok := c.rpcHk4eGatewayConsumer.CallFunction("RpcManager", "GetOnlineUser", &userId, &list)
|
||||
if ok {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(0, "查询成功", list))
|
||||
} else {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "查询失败", nil))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) forbidUser(context *gin.Context) {
|
||||
accessToken := c.getAccessToken(context)
|
||||
user, err := waterAuth.WaterQueryUserByAccessToken(c.rpcWaterAuthConsumer, accessToken)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(1001, "服务器内部错误", nil))
|
||||
return
|
||||
}
|
||||
if !user.IsAdmin {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10001, "没有访问权限", nil))
|
||||
return
|
||||
}
|
||||
uidStr := context.Query("uid")
|
||||
uid, err := strconv.ParseInt(uidStr, 10, 64)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10003, "参数错误", nil))
|
||||
return
|
||||
}
|
||||
endTimeStr := context.Query("endTime")
|
||||
endTime, err := strconv.ParseInt(endTimeStr, 10, 64)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10003, "参数错误", nil))
|
||||
return
|
||||
}
|
||||
info := new(gm.ForbidUserInfo)
|
||||
info.UserId = uint32(uid)
|
||||
info.ForbidEndTime = uint64(endTime)
|
||||
var result bool
|
||||
ok := c.rpcHk4eGatewayConsumer.CallFunction("RpcManager", "ForbidUser", &info, &result)
|
||||
if ok == true && result == true {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(0, "操作成功", nil))
|
||||
} else {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "操作失败", nil))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) unForbidUser(context *gin.Context) {
|
||||
accessToken := c.getAccessToken(context)
|
||||
user, err := waterAuth.WaterQueryUserByAccessToken(c.rpcWaterAuthConsumer, accessToken)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(1001, "服务器内部错误", nil))
|
||||
return
|
||||
}
|
||||
if !user.IsAdmin {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10001, "没有访问权限", nil))
|
||||
return
|
||||
}
|
||||
uidStr := context.Query("uid")
|
||||
uid, err := strconv.ParseInt(uidStr, 10, 64)
|
||||
if err != nil {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(10003, "参数错误", nil))
|
||||
return
|
||||
}
|
||||
userId := uint32(uid)
|
||||
var result bool
|
||||
ok := c.rpcHk4eGatewayConsumer.CallFunction("RpcManager", "UnForbidUser", &userId, &result)
|
||||
if ok == true && result == true {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(0, "操作成功", nil))
|
||||
} else {
|
||||
context.JSON(http.StatusOK, dto.NewResponseResult(-1, "操作失败", nil))
|
||||
}
|
||||
}
|
||||
53
service/gm-hk4e/go.mod
Normal file
53
service/gm-hk4e/go.mod
Normal file
@@ -0,0 +1,53 @@
|
||||
module gm-hk4e
|
||||
|
||||
go 1.19
|
||||
|
||||
require flswld.com/common v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/common => ../../common
|
||||
|
||||
require flswld.com/logger v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/logger => ../../logger
|
||||
|
||||
require flswld.com/air-api v0.0.0-incompatible // indirect
|
||||
|
||||
replace flswld.com/air-api => ../../air-api
|
||||
|
||||
require flswld.com/light v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/light => ../../light
|
||||
|
||||
require flswld.com/gate-hk4e-api v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/gate-hk4e-api => ../../gate-hk4e-api
|
||||
|
||||
require (
|
||||
flswld.com/annie-user-api v0.0.0-incompatible // indirect
|
||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.2.0 // indirect
|
||||
github.com/golang/protobuf v1.3.3 // indirect
|
||||
github.com/json-iterator/go v1.1.9 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
|
||||
github.com/ugorji/go/codec v1.1.7 // indirect
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
)
|
||||
|
||||
replace flswld.com/annie-user-api => ../annie-user-api
|
||||
|
||||
require flswld.com/water-api v0.0.0-incompatible
|
||||
|
||||
replace flswld.com/water-api => ../../water-api
|
||||
|
||||
// gin
|
||||
require github.com/gin-gonic/gin v1.6.3
|
||||
|
||||
// jwt
|
||||
require github.com/golang-jwt/jwt/v4 v4.4.0
|
||||
50
service/gm-hk4e/go.sum
Normal file
50
service/gm-hk4e/go.sum
Normal file
@@ -0,0 +1,50 @@
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.0 h1:EmVIxB5jzbllGIjiCV5JG4VylbK3KE400tLGLI1cdfU=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
43
service/sql/annie_user.sql
Normal file
43
service/sql/annie_user.sql
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : MySQL-Dev
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 50727
|
||||
Source Host : 192.168.199.131:3306
|
||||
Source Schema : annie_user
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 50727
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 25/05/2022 00:38:54
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET
|
||||
FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for user
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `user`;
|
||||
CREATE TABLE `user`
|
||||
(
|
||||
`uid` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
`password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
`is_admin` tinyint(1) NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`uid`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of user
|
||||
-- ----------------------------
|
||||
INSERT INTO `user`
|
||||
VALUES (1, 'flswld', '25d55ad283aa400af464c76d713c07ad', 1);
|
||||
INSERT INTO `user`
|
||||
VALUES (2, 'fhqs', '25d55ad283aa400af464c76d713c07ad', 0);
|
||||
|
||||
SET
|
||||
FOREIGN_KEY_CHECKS = 1;
|
||||
59
service/sql/annie_wxmp.sql
Normal file
59
service/sql/annie_wxmp.sql
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : MySQL-Dev
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 50727
|
||||
Source Host : 192.168.199.131:3306
|
||||
Source Schema : annie_wxmp
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 50727
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 25/05/2022 00:39:11
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET
|
||||
FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fw_death_info
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fw_death_info`;
|
||||
CREATE TABLE `fw_death_info`
|
||||
(
|
||||
`fdid` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`fw_alive` tinyint(1) NULL DEFAULT NULL,
|
||||
`fw_cancel` tinyint(1) NULL DEFAULT NULL,
|
||||
`fw_info` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`fdid`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fw_death_info
|
||||
-- ----------------------------
|
||||
INSERT INTO `fw_death_info`
|
||||
VALUES (1, 1, 0, '你好');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fw_death_notify_user
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fw_death_notify_user`;
|
||||
CREATE TABLE `fw_death_notify_user`
|
||||
(
|
||||
`dnuid` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`wx_open_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
`email` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`dnuid`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fw_death_notify_user
|
||||
-- ----------------------------
|
||||
INSERT INTO `fw_death_notify_user`
|
||||
VALUES (1, 'oAuwFwB2-uoEeDQDUdleUbH5jAlI', '1782360262@qq.com');
|
||||
|
||||
SET
|
||||
FOREIGN_KEY_CHECKS = 1;
|
||||
Reference in New Issue
Block a user