first commit

This commit is contained in:
ytc1012
2025-11-18 18:08:48 +08:00
commit de90ad79ea
162 changed files with 28098 additions and 0 deletions

View File

@@ -0,0 +1,204 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"log/slog"
"slgserver/constant"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/chatserver/logic"
"slgserver/server/chatserver/proto"
"slgserver/util"
"sync"
)
var DefaultChat = Chat{
worldGroup: logic.NewGroup(),
unionGroups: make(map[int]*logic.Group),
ridToUnionGroups: make(map[int]int),
}
type Chat struct {
unionMutex sync.RWMutex
worldGroup *logic.Group //世界频道
unionGroups map[int]*logic.Group //联盟频道
ridToUnionGroups map[int]int //rid对应的联盟频道
}
func (this*Chat) InitRouter(r *net.Router) {
g := r.Group("chat").Use(middleware.ElapsedTime(), middleware.Log())
g.AddRouter("login", this.login)
g.AddRouter("logout", this.logout, middleware.CheckRId())
g.AddRouter("chat", this.chat, middleware.CheckRId())
g.AddRouter("history", this.history, middleware.CheckRId())
g.AddRouter("join", this.join, middleware.CheckRId())
g.AddRouter("exit", this.exit, middleware.CheckRId())
}
func (this*Chat) login(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.LoginReq{}
rspObj := &proto.LoginRsp{}
rsp.Body.Code = constant.OK
rsp.Body.Msg = rspObj
mapstructure.Decode(req.Body.Msg, reqObj)
rspObj.RId = reqObj.RId
rspObj.NickName = reqObj.NickName
sess, err := util.ParseSession(reqObj.Token)
if err != nil{
rsp.Body.Code = constant.InvalidParam
return
}
if sess.IsValid() == false || sess.Id != reqObj.RId{
rsp.Body.Code = constant.InvalidParam
return
}
net.ConnMgr.RoleEnter(req.Conn, reqObj.RId)
this.worldGroup.Enter(logic.NewUser(reqObj.RId, reqObj.NickName))
}
func (this*Chat) logout(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.LogoutReq{}
rspObj := &proto.LogoutRsp{}
rsp.Body.Code = constant.OK
rsp.Body.Msg = rspObj
mapstructure.Decode(req.Body.Msg, reqObj)
rspObj.RId = reqObj.RId
net.ConnMgr.UserLogout(req.Conn)
this.worldGroup.Exit(reqObj.RId)
}
func (this*Chat) chat(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ChatReq{}
rspObj := &proto.ChatMsg{}
rsp.Body.Code = constant.OK
rsp.Body.Msg = rspObj
mapstructure.Decode(req.Body.Msg, reqObj)
p, _ := req.Conn.GetProperty("rid")
rid := p.(int)
if reqObj.Type == 0 {
//世界聊天
rsp.Body.Msg = this.worldGroup.PutMsg(reqObj.Msg, rid, 0)
}else if reqObj.Type == 1{
//联盟聊天
this.unionMutex.RLock()
id, ok := this.ridToUnionGroups[rid]
if ok {
g, ok := this.unionGroups[id]
if ok {
g.PutMsg(reqObj.Msg, rid, 1)
}else{
slog.Warn("chat not found rid in unionGroups", "rid", rid)
}
}else{
slog.Warn("chat not found rid in ridToUnionGroups", "rid", rid)
}
this.unionMutex.RUnlock()
}
}
//历史记录
func (this*Chat) history(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.HistoryReq{}
rspObj := &proto.HistoryRsp{}
rsp.Body.Code = constant.OK
mapstructure.Decode(req.Body.Msg, reqObj)
rspObj.Msgs = []proto.ChatMsg{}
p, _ := req.Conn.GetProperty("rid")
rid := p.(int)
if reqObj.Type == 0 {
r := this.worldGroup.History()
rspObj.Msgs = r
}else if reqObj.Type == 1 {
this.unionMutex.RLock()
id, ok := this.ridToUnionGroups[rid]
if ok {
g, ok := this.unionGroups[id]
if ok {
rspObj.Msgs = g.History()
}
}
this.unionMutex.RUnlock()
}
rspObj.Type = reqObj.Type
rsp.Body.Msg = rspObj
}
func (this*Chat) join(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.JoinReq{}
rspObj := &proto.JoinRsp{}
rsp.Body.Code = constant.OK
rsp.Body.Msg = rspObj
rspObj.Type = reqObj.Type
mapstructure.Decode(req.Body.Msg, reqObj)
p, _ := req.Conn.GetProperty("rid")
rid := p.(int)
if reqObj.Type == 1 {
u := this.worldGroup.GetUser(rid)
if u == nil {
rsp.Body.Code = constant.InvalidParam
return
}
this.unionMutex.Lock()
gId, ok := this.ridToUnionGroups[rid]
if ok {
if gId != reqObj.Id {
//联盟聊天只能有一个,顶掉旧的
if g,ok := this.unionGroups[gId]; ok {
g.Exit(rid)
}
_, ok = this.unionGroups[reqObj.Id]
if ok == false {
this.unionGroups[reqObj.Id] = logic.NewGroup()
}
this.ridToUnionGroups[rid] = reqObj.Id
this.unionGroups[reqObj.Id].Enter(u)
}
}else{
//新加入
_, ok = this.unionGroups[reqObj.Id]
if ok == false {
this.unionGroups[reqObj.Id] = logic.NewGroup()
}
this.ridToUnionGroups[rid] = reqObj.Id
this.unionGroups[reqObj.Id].Enter(u)
}
this.unionMutex.Unlock()
}
}
func (this*Chat) exit(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ExitReq{}
rspObj := &proto.ExitRsp{}
rsp.Body.Code = constant.OK
rsp.Body.Msg = rspObj
rspObj.Type = reqObj.Type
mapstructure.Decode(req.Body.Msg, reqObj)
p, _ := req.Conn.GetProperty("rid")
rid := p.(int)
if reqObj.Type == 1 {
this.unionMutex.Lock()
id, ok := this.ridToUnionGroups[rid]
if ok {
g, ok := this.unionGroups[id]
if ok {
g.Exit(rid)
}
}
delete(this.ridToUnionGroups, rid)
this.unionMutex.Unlock()
}
}

20
server/chatserver/init.go Normal file
View File

@@ -0,0 +1,20 @@
package chatserver
import (
"slgserver/db"
"slgserver/net"
"slgserver/server/chatserver/controller"
)
var MyRouter = &net.Router{}
func Init() {
db.TestDB()
//全部初始化完才注册路由,防止服务器还没启动就绪收到请求
initRouter()
}
func initRouter() {
controller.DefaultChat.InitRouter(MyRouter)
}

View File

@@ -0,0 +1,22 @@
package logic
import "time"
type User struct {
rid int
nickName string
}
func NewUser(rid int, nickName string) *User {
return &User{
rid: rid,
nickName: nickName,
}
}
type Msg struct {
RId int `json:"rid"`
NickName string `json:"nickName"`
Msg string `json:"msg"`
Time time.Time `json:"time"`
}

View File

@@ -0,0 +1,79 @@
package logic
import (
"slgserver/net"
"slgserver/server/chatserver/proto"
"sync"
"time"
)
type Group struct {
userMutex sync.RWMutex
msgMutex sync.RWMutex
users map[int]*User
msgs ItemQueue
}
func NewGroup() *Group {
return &Group{users: map[int]*User{}}
}
func (this*Group) Enter(u *User) {
this.userMutex.Lock()
defer this.userMutex.Unlock()
this.users[u.rid] = u
}
func (this*Group) Exit(rid int) {
this.userMutex.Lock()
defer this.userMutex.Unlock()
delete(this.users, rid)
}
func (this*Group) GetUser(rid int) *User {
this.userMutex.Lock()
defer this.userMutex.Unlock()
return this.users[rid]
}
func (this*Group) PutMsg(text string, rid int, t int8) *proto.ChatMsg {
this.userMutex.RLock()
u, ok := this.users[rid]
this.userMutex.RUnlock()
if ok == false{
return nil
}
msg := &Msg{Msg: text, RId: rid, Time: time.Now(), NickName: u.nickName}
this.msgMutex.Lock()
size := this.msgs.Size()
if size > 100 {
this.msgs.Dequeue()
}
this.msgs.Enqueue(msg)
this.msgMutex.Unlock()
//广播
this.userMutex.RLock()
c := &proto.ChatMsg{RId: msg.RId, NickName: msg.NickName, Time: msg.Time.Unix(), Msg: msg.Msg, Type: t}
for _, user := range this.users {
net.ConnMgr.PushByRoleId(user.rid, "chat.push", c)
}
this.userMutex.RUnlock()
return c
}
func (this*Group) History() []proto.ChatMsg {
r := make([]proto.ChatMsg, 0)
this.msgMutex.RLock()
items := this.msgs.items
for _, item := range items {
msg := item.(*Msg)
c := proto.ChatMsg{RId: msg.RId, NickName: msg.NickName, Time: msg.Time.Unix(), Msg: msg.Msg}
r = append(r, c)
}
this.msgMutex.RUnlock()
return r
}

View File

@@ -0,0 +1,45 @@
package logic
type Item interface {
}
// Item the type of the queue
type ItemQueue struct {
items []Item
}
type ItemQueuer interface {
New() ItemQueue
Enqueue(t Item)
Dequeue() *Item
IsEmpty() bool
Size() int
}
// New creates a new ItemQueue
func (s *ItemQueue) New() *ItemQueue {
s.items = []Item{}
return s
}
// Enqueue adds an Item to the end of the queue
func (s *ItemQueue) Enqueue(t Item) {
s.items = append(s.items, t)
}
// dequeue
func (s *ItemQueue) Dequeue() *Item {
item := s.items[0] // 先进先出
s.items = s.items[1:len(s.items)]
return &item
}
func (s *ItemQueue) IsEmpty() bool {
return len(s.items) == 0
}
// Size returns the number of Items in the queue
func (s *ItemQueue) Size() int {
return len(s.items)
}

View File

@@ -0,0 +1,64 @@
package proto
type LoginReq struct {
RId int `json:"rid"`
NickName string `json:"nickName"`
Token string `json:"token"`
}
type LoginRsp struct {
RId int `json:"rid"`
NickName string `json:"nickName"`
}
type LogoutReq struct {
RId int `json:"RId"`
}
type LogoutRsp struct {
RId int `json:"RId"`
}
type ChatReq struct {
Type int8 `json:"type"` //0世界聊天、1联盟聊天
Msg string `json:"msg"`
}
type ChatMsg struct {
RId int `json:"rid"`
NickName string `json:"nickName"`
Type int8 `json:"type"` //0世界聊天、1联盟聊天
Msg string `json:"msg"`
Time int64 `json:"time"`
}
type HistoryReq struct {
Type int8 `json:"type"` //0世界聊天、1联盟聊天
}
type HistoryRsp struct {
Type int8 `json:"type"` //0世界聊天、1联盟聊天
Msgs []ChatMsg `json:"msgs"`
}
type JoinReq struct {
Type int8 `json:"type"` //0世界聊天、1联盟聊天
Id int `json:"id"`
}
type JoinRsp struct {
Type int8 `json:"type"` //0世界聊天、1联盟聊天
Id int `json:"id"`
}
type ExitReq struct {
Type int8 `json:"type"` //0世界聊天、1联盟聊天
Id int `json:"id"`
}
type ExitRsp struct {
Type int8 `json:"type"` //0世界聊天、1联盟聊天
Id int `json:"id"`
}

View File

@@ -0,0 +1,205 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"log/slog"
"slgserver/config"
"slgserver/constant"
"slgserver/middleware"
"slgserver/net"
chat_proto "slgserver/server/chatserver/proto"
"slgserver/server/slgserver/proto"
"strings"
"sync"
)
var GHandle = Handle{
proxys: make(map[string]map[int64]*net.ProxyClient),
}
type Handle struct {
proxyMutex sync.Mutex
proxys map[string]map[int64]*net.ProxyClient
slgProxy string
chatProxy string
loginProxy string
}
func isAccount(msgName string) bool {
sArr := strings.Split(msgName, ".")
prefix := ""
if len(sArr) == 2{
prefix = sArr[0]
}
if prefix == "account"{
return true
}else{
return false
}
}
func isChat(msgName string) bool {
sArr := strings.Split(msgName, ".")
prefix := ""
if len(sArr) == 2{
prefix = sArr[0]
}
if prefix == "chat"{
return true
}else{
return false
}
}
func (this*Handle) InitRouter(r *net.Router) {
this.init()
g := r.Group("*").Use(middleware.ElapsedTime(), middleware.Log())
g.AddRouter("*", this.all)
}
func (this*Handle) init() {
this.slgProxy = config.GetString("gateserver.slg_proxy", "ws://127.0.0.1:8001")
this.chatProxy = config.GetString("gateserver.chat_proxy", "ws://127.0.0.1:8002")
this.loginProxy = config.GetString("gateserver.login_proxy", "ws://127.0.0.1:8003")
}
func (this*Handle) onPush(conn *net.ClientConn, body *net.RspBody) {
gc, err := conn.GetProperty("gateConn")
if err != nil{
return
}
gateConn := gc.(net.WSConn)
gateConn.Push(body.Name, body.Msg)
}
func (this*Handle) onProxyClose(conn *net.ClientConn) {
p, err := conn.GetProperty("proxy")
if err == nil {
proxyStr := p.(string)
this.proxyMutex.Lock()
_, ok := this.proxys[proxyStr]
if ok {
c, err := conn.GetProperty("cid")
if err == nil{
cid := c.(int64)
delete(this.proxys[proxyStr], cid)
}
}
this.proxyMutex.Unlock()
}
}
func (this*Handle) OnServerConnClose (conn net.WSConn){
c, err := conn.GetProperty("cid")
arr := make([]*net.ProxyClient, 0)
if err == nil{
cid := c.(int64)
this.proxyMutex.Lock()
for _, m := range this.proxys {
proxy, ok := m[cid]
if ok {
arr = append(arr, proxy)
}
delete(m, cid)
}
this.proxyMutex.Unlock()
}
for _, client := range arr {
client.Close()
}
}
func (this*Handle) all(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
slog.Info("gateserver handle all begin",
"proxyStr", req.Body.Proxy,
"msgName", req.Body.Name)
this.deal(req, rsp)
if req.Body.Name == "role.enterServer" && rsp.Body.Code == constant.OK {
//登录聊天服
rspObj := &proto.EnterServerRsp{}
mapstructure.Decode(rsp.Body.Msg, rspObj)
r := &chat_proto.LoginReq{RId: rspObj.Role.RId, NickName: rspObj.Role.NickName, Token: rspObj.Token}
reqBody := &net.ReqBody{Seq: 0, Name: "chat.login", Msg: r, Proxy: ""}
rspBody := &net.RspBody{Seq: 0, Name: "chat.login", Msg: r, Code: 0}
this.deal(&net.WsMsgReq{Body: reqBody, Conn:req.Conn}, &net.WsMsgRsp{Body: rspBody})
}
slog.Info("gateserver handle all end",
"proxyStr", req.Body.Proxy,
"msgName", req.Body.Name)
}
func (this*Handle) deal(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
//协议转发
proxyStr := req.Body.Proxy
if isAccount(req.Body.Name){
proxyStr = this.loginProxy
}else if isChat(req.Body.Name){
proxyStr = this.chatProxy
} else{
proxyStr = this.slgProxy
}
if proxyStr == ""{
rsp.Body.Code = constant.ProxyNotInConnect
return
}
this.proxyMutex.Lock()
_, ok := this.proxys[proxyStr]
if ok == false {
this.proxys[proxyStr] = make(map[int64]*net.ProxyClient)
}
var err error
var proxy *net.ProxyClient
d, _ := req.Conn.GetProperty("cid")
cid := d.(int64)
proxy, ok = this.proxys[proxyStr][cid]
this.proxyMutex.Unlock()
if ok == false {
proxy = net.NewProxyClient(proxyStr)
this.proxyMutex.Lock()
this.proxys[proxyStr][cid] = proxy
this.proxyMutex.Unlock()
//发起链接,这里是阻塞的,所以不要上锁
err = proxy.Connect()
if err == nil{
proxy.SetProperty("cid", cid)
proxy.SetProperty("proxy", proxyStr)
proxy.SetProperty("gateConn", req.Conn)
proxy.SetOnPush(this.onPush)
proxy.SetOnClose(this.onProxyClose)
}
}
if err != nil {
this.proxyMutex.Lock()
delete(this.proxys[proxyStr], cid)
this.proxyMutex.Unlock()
rsp.Body.Code = constant.ProxyConnectError
return
}
rsp.Body.Seq = req.Body.Seq
rsp.Body.Name = req.Body.Name
r, err := proxy.Send(req.Body.Name, req.Body.Msg)
if err == nil{
rsp.Body.Code = r.Code
rsp.Body.Msg = r.Msg
}else{
rsp.Body.Code = constant.ProxyConnectError
rsp.Body.Msg = nil
}
}

19
server/gateserver/init.go Normal file
View File

@@ -0,0 +1,19 @@
package gateserver
import (
"slgserver/net"
"slgserver/server/gateserver/controller"
)
var MyRouter = &net.Router{}
func Init() {
//全部初始化完才注册路由,防止服务器还没启动就绪收到请求
initRouter()
}
func initRouter() {
controller.GHandle.InitRouter(MyRouter)
}

View File

@@ -0,0 +1,59 @@
package controller
import (
"github.com/gin-gonic/gin"
"net/http"
"log/slog"
"slgserver/constant"
myhttp "slgserver/server/httpserver"
"slgserver/server/httpserver/logic"
"slgserver/server/httpserver/middleware"
)
type AccountController struct{}
func (self AccountController) RegisterRoutes(g *gin.RouterGroup) {
g.Use(middleware.Cors())
g.Any("/account/register", self.register)
g.Any("/account/changepwd", self.changePwd)
g.Any("/account/forgetpwd", self.forgetPwd)
g.Any("/account/resetpwd", self.resetPwd)
}
func (self AccountController) register(ctx *gin.Context) {
slog.Info("register")
data := make(map[string]interface{})
if err := logic.DefaultUser.CreateUser(ctx); err != nil {
data["code"] = err.(*myhttp.MyError).Id()
data["errmsg"] = err.(*myhttp.MyError).Error()
}else{
data["code"] = constant.OK
}
ctx.JSON(http.StatusOK, data)
}
func (self AccountController) forgetPwd(ctx *gin.Context) {
slog.Info("forgetPwd")
ctx.String(http.StatusOK, "forgetPwd")
}
func (self AccountController) changePwd(ctx *gin.Context) {
slog.Info("changePwd")
data := make(map[string]interface{})
if err := logic.DefaultUser.ChangePassword(ctx); err != nil {
data["code"] = err.(*myhttp.MyError).Id()
data["errmsg"] = err.(*myhttp.MyError).Error()
}else{
data["code"] = constant.OK
}
ctx.JSON(http.StatusOK, data)
}
func (self AccountController) resetPwd(ctx *gin.Context) {
slog.Info("resetPwd")
ctx.String(http.StatusOK, "resetPwd")
}

View File

@@ -0,0 +1,88 @@
package logic
import (
"fmt"
"github.com/gin-gonic/gin"
"math/rand"
"slgserver/constant"
"slgserver/db"
myhttp "slgserver/server/httpserver"
"slgserver/server/loginserver/model"
"slgserver/util"
"time"
)
type UserLogic struct{}
var DefaultUser = UserLogic{}
func (self UserLogic) CreateUser(ctx *gin.Context) error {
account := ctx.Query("username")
pwd := ctx.Query("password")
hardware := ctx.Query("hardware")
if len(account) > 0 && len(pwd) > 0 {
if self.UserExists("username", account) {
return myhttp.New("账号已经存在", constant.UserExist)
}
passcode := fmt.Sprintf("%x", rand.Int31())
user := &model.User{
Username: account,
Passcode: passcode,
Passwd: util.Password(pwd, passcode),
Hardware: hardware,
Ctime: time.Now(),
Mtime: time.Now()}
if _, err := db.MasterDB.Insert(user); err != nil {
return myhttp.New("数据库出错", constant.DBError)
} else{
return nil
}
}else{
return myhttp.New("用户名或密码是空", constant.InvalidParam)
}
}
func (self UserLogic) ChangePassword(ctx *gin.Context) error {
account := ctx.Query("username")
pwd := ctx.Query("password")
newpwd := ctx.Query("newpassword")
user := &model.User{}
if len(account) > 0 && len(pwd) > 0 && len(newpwd) > 0{
if _, err := db.MasterDB.Where("username=?", account).Get(user); err != nil {
return myhttp.New("数据库出错", constant.DBError)
}else{
if util.Password(pwd, user.Passcode) == user.Passwd {
passcode := fmt.Sprintf("%x", rand.Int31())
changeData := map[string]interface{}{
"passwd": util.Password(newpwd, passcode),
"passcode": passcode,
"Mtime": time.Now(),
}
if _, err := db.MasterDB.Table(user).Where("username=?", account).Update(changeData); err !=nil {
return myhttp.New("数据库出错", constant.DBError)
}else{
return nil
}
}else{
return myhttp.New("原密码错误", constant.PwdIncorrect)
}
}
}else{
return myhttp.New("用户名或密码是空", constant.InvalidParam)
}
}
func (UserLogic) UserExists(field, val string) bool {
userLogin := &model.User{}
_, err := db.MasterDB.Where(field+"=?", val).Get(userLogin)
if err != nil || userLogin.UId == 0 {
return false
}
return true
}

View File

@@ -0,0 +1,22 @@
package middleware
import (
"github.com/gin-gonic/gin"
)
func Cors() gin.HandlerFunc {
return func(ctx *gin.Context) {
ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
ctx.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
ctx.Writer.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS, POST, PUT, DELETE")
ctx.Writer.Header().Set("Content-Type", "application/json")
if ctx.Request.Method == "OPTIONS" {
ctx.AbortWithStatus(204)
return
}
ctx.Next()
}
}

View File

@@ -0,0 +1,21 @@
package httpserver
type MyError struct {
err string
id int
}
func New(err string, id int) error {
return &MyError{err: err, id: id}
}
func (self *MyError) Error() string {
return self.err
}
func (self *MyError) Id() int {
return self.id
}

View File

@@ -0,0 +1,189 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"slgserver/constant"
"slgserver/db"
"log/slog"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/loginserver/model"
"slgserver/server/loginserver/proto"
"slgserver/util"
"time"
)
var DefaultAccount = Account{}
type Account struct {
}
func (this*Account) InitRouter(r *net.Router) {
g := r.Group("account").Use(middleware.ElapsedTime(), middleware.Log())
g.AddRouter("login", this.login)
g.AddRouter("reLogin", this.reLogin)
g.AddRouter("logout", this.logout, middleware.CheckLogin())
g.AddRouter("serverList", this.serverList, middleware.CheckLogin())
}
func (this*Account) login(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.LoginReq{}
rspObj := &proto.LoginRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
user := &model.User{}
ok, err := db.MasterDB.Table(user).Where("username=?", reqObj.Username).Get(user)
if err!= nil {
slog.Error("login db error",
"username", reqObj.Username,
"error", err)
rsp.Body.Code = constant.DBError
}else{
if ok {
pwd := util.Password(reqObj.Password, user.Passcode)
if pwd != user.Passwd{
//密码不正确
slog.Warn("login password not right",
"username", user.Username)
rsp.Body.Code = constant.PwdIncorrect
}else{
tt := time.Now()
s := util.NewSession(user.UId, tt)
sessStr := s.String()
slog.Info("login",
"username", user.Username,
"session", sessStr)
//登录成功,写记录
lh := &model.LoginHistory{UId: user.UId, CTime: tt, Ip: reqObj.Ip,
Hardware: reqObj.Hardware, State: model.Login}
db.MasterDB.Insert(lh)
ll := &model.LoginLast{}
ok, _ := db.MasterDB.Table(ll).Where("uid=?", user.UId).Get(ll)
if ok {
ll.IsLogout = 0
ll.Ip = reqObj.Ip
ll.LoginTime = time.Now()
ll.Session = sessStr
ll.Hardware = reqObj.Hardware
_, err := db.MasterDB.ID(ll.Id).Cols(
"is_logout", "ip", "login_time", "session", "hardware").Update(ll)
if err != nil {
slog.Error("update login_last table fail", "error", err)
}
}else{
ll = &model.LoginLast{UId: user.UId, LoginTime: tt,
Ip: reqObj.Ip, Session: sessStr,
Hardware: reqObj.Hardware, IsLogout: 0}
db.MasterDB.Insert(ll)
}
rspObj.Session = sessStr
rspObj.Password = reqObj.Password
rspObj.Username = reqObj.Username
rspObj.UId = user.UId
rsp.Body.Code = constant.OK
net.ConnMgr.UserLogin(req.Conn, sessStr, ll.UId)
}
}else{
//数据库出错
slog.Warn("login username not found", "username", reqObj.Username)
rsp.Body.Code = constant.UserNotExist
}
}
}
func (this*Account) reLogin(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ReLoginReq{}
rspObj := &proto.ReLoginRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
if reqObj.Session == ""{
rsp.Body.Code = constant.SessionInvalid
return
}
rsp.Body.Msg = rspObj
rspObj.Session = reqObj.Session
sess, err := util.ParseSession(reqObj.Session)
if err != nil{
rsp.Body.Code = constant.SessionInvalid
}else{
if sess.IsValid() {
//数据库验证一下
ll := &model.LoginLast{}
db.MasterDB.Table(ll).Where("uid=?", sess.Id).Get(ll)
if ll.Session == reqObj.Session {
if ll.Hardware == reqObj.Hardware {
rsp.Body.Code = constant.OK
net.ConnMgr.UserLogin(req.Conn, reqObj.Session, ll.UId)
}else{
rsp.Body.Code = constant.HardwareIncorrect
}
}else{
rsp.Body.Code = constant.SessionInvalid
}
}else{
rsp.Body.Code = constant.SessionInvalid
}
}
}
func (this*Account) logout(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.LogoutReq{}
rspObj := &proto.LogoutRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rspObj.UId = reqObj.UId
rsp.Body.Code = constant.OK
slog.Info("logout", "uid", reqObj.UId)
tt := time.Now()
//登出,写记录
lh := &model.LoginHistory{UId: reqObj.UId, CTime: tt, State: model.Logout}
db.MasterDB.Insert(lh)
ll := &model.LoginLast{}
ok, _ := db.MasterDB.Table(ll).Where("uid=?", reqObj.UId).Get(ll)
if ok {
ll.IsLogout = 1
ll.LogoutTime = time.Now()
db.MasterDB.ID(ll.Id).Cols("is_logout", "logout_time").Update(ll)
}else{
ll = &model.LoginLast{UId: reqObj.UId, LogoutTime: tt, IsLogout: 0}
db.MasterDB.Insert(ll)
}
net.ConnMgr.UserLogout(req.Conn)
}
func (this*Account) serverList(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ServerListReq{}
rspObj := &proto.ServerListRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Code = constant.OK
s := proto.Server{Id: 1, Slg: "ws://127.0.0.1:8001", Chat: "ws://127.0.0.1:8002"}
r := make([]proto.Server, 0)
rspObj.Lists = append(r, s)
rsp.Body.Msg = rspObj
}

View File

@@ -0,0 +1,21 @@
package loginserver
import (
"slgserver/db"
"slgserver/net"
"slgserver/server/loginserver/controller"
)
var MyRouter = &net.Router{}
func Init() {
db.TestDB()
//全部初始化完才注册路由,防止服务器还没启动就绪收到请求
initRouter()
}
func initRouter() {
controller.DefaultAccount.InitRouter(MyRouter)
}

View File

@@ -0,0 +1,39 @@
package model
import (
"time"
)
const (
Login = iota
Logout
)
type LoginHistory struct {
Id int `xorm:"id pk autoincr"`
UId int `xorm:"uid"`
CTime time.Time `xorm:"ctime"`
Ip string `xorm:"ip"`
State int8 `xorm:"state"`
Hardware string `xorm:"hardware"`
}
func (this *LoginHistory) TableName() string {
return "tb_login_history"
}
type LoginLast struct {
Id int `xorm:"id pk autoincr"`
UId int `xorm:"uid"`
LoginTime time.Time `xorm:"login_time"`
LogoutTime time.Time `xorm:"logout_time"`
Ip string `xorm:"ip"`
Session string `xorm:"session"`
IsLogout int8 `xorm:"is_logout"`
Hardware string `xorm:"hardware"`
}
func (this *LoginLast) TableName() string {
return "tb_login_last"
}

View File

@@ -0,0 +1,19 @@
package model
import "time"
type User struct {
UId int `xorm:"uid pk autoincr"`
Username string `xorm:"username" validate:"min=4,max=20,regexp=^[a-zA-Z0-9_]*$"`
Passcode string `xorm:"passcode"`
Passwd string `xorm:"passwd"`
Hardware string `xorm:"hardware"`
Status int `xorm:"status"`
Ctime time.Time `xorm:"ctime"`
Mtime time.Time `xorm:"mtime"`
IsOnline bool `xorm:"-"`
}
func (this *User) TableName() string {
return "tb_user_info"
}

View File

@@ -0,0 +1,47 @@
package proto
type LoginReq struct {
Username string `json:"username"`
Password string `json:"password"`
Ip string `json:"ip"`
Hardware string `json:"hardware"`
}
type LoginRsp struct {
Username string `json:"username"`
Password string `json:"password"`
Session string `json:"session"`
UId int `json:"uid"`
}
type ReLoginReq struct {
Session string `json:"session"`
Ip string `json:"ip"`
Hardware string `json:"hardware"`
}
type ReLoginRsp struct {
Session string `json:"session"`
}
type LogoutReq struct {
UId int `json:"uid"`
}
type LogoutRsp struct {
UId int `json:"uid"`
}
type Server struct {
Id int `json:"id"`
Slg string `json:"slg"`
Chat string `json:"chat"`
}
type ServerListReq struct {
}
type ServerListRsp struct {
Lists []Server
}

View File

@@ -0,0 +1,12 @@
package conn
type PushSync interface {
IsCellView() bool //是否格子视野
IsCanView(rid, x, y int)bool //是否能出现在视野
BelongToRId() []int //属于的rid
PushMsgName() string //推送名字
Position() (int, int) //x, y
TPosition() (int, int) //目标x, y
ToProto() interface{} //转成proto
Push() //推送
}

View File

@@ -0,0 +1,569 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"slgserver/constant"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/slgserver/global"
"slgserver/server/slgserver/logic"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf"
"slgserver/server/slgserver/static_conf/facility"
"slgserver/server/slgserver/static_conf/general"
"time"
)
var DefaultArmy = Army{
}
type Army struct {
}
func (this*Army) InitRouter(r *net.Router) {
g := r.Group("army").Use(middleware.ElapsedTime(), middleware.Log(),
middleware.CheckLogin(), middleware.CheckRole())
g.AddRouter("myList", this.myList)
g.AddRouter("myOne", this.myOne)
g.AddRouter("dispose", this.dispose)
g.AddRouter("conscript", this.conscript)
g.AddRouter("assign", this.assign)
}
//我的军队列表
func (this*Army) myList(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ArmyListReq{}
rspObj := &proto.ArmyListRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
rspObj.CityId = reqObj.CityId
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
city,ok := mgr.RCMgr.Get(reqObj.CityId)
if ok == false{
rsp.Body.Code = constant.CityNotExist
return
}
if city.RId != role.RId {
rsp.Body.Code = constant.CityNotMe
return
}
as, _ := mgr.AMgr.GetByCity(reqObj.CityId)
rspObj.Armys = make([]proto.Army, len(as))
for i, v := range as {
rspObj.Armys[i] = v.ToProto().(proto.Army)
}
}
//我的某一个军队
func (this*Army) myOne(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ArmyOneReq{}
rspObj := &proto.ArmyOneRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
city, ok := mgr.RCMgr.Get(reqObj.CityId)
if ok == false{
rsp.Body.Code = constant.CityNotExist
return
}
if city.RId != role.RId {
rsp.Body.Code = constant.CityNotMe
return
}
a, ok := mgr.AMgr.GetByCityOrder(reqObj.CityId, reqObj.Order)
if ok {
rspObj.Army = a.ToProto().(proto.Army)
}else{
rsp.Body.Code = constant.ArmyNotFound
}
}
//配置武将
func (this*Army) dispose(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.DisposeReq{}
rspObj := &proto.DisposeRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if reqObj.Order <= 0 || reqObj.Order > 5 || reqObj.Position < -1 || reqObj.Position >2 {
rsp.Body.Code = constant.InvalidParam
return
}
city, ok := mgr.RCMgr.Get(reqObj.CityId)
if ok == false {
rsp.Body.Code = constant.CityNotExist
return
}
if city.RId != role.RId {
rsp.Body.Code = constant.CityNotMe
return
}
//校场每升一级一个队伍
jc, ok := mgr.RFMgr.GetFacility(city.CityId, facility.JiaoChang)
if ok == false || jc.GetLevel() < reqObj.Order {
rsp.Body.Code = constant.ArmyNotEnough
return
}
newG, ok := mgr.GMgr.GetByGId(reqObj.GeneralId)
if ok == false{
rsp.Body.Code = constant.GeneralNotFound
return
}
if newG.RId != role.RId{
rsp.Body.Code = constant.GeneralNotMe
return
}
army, err := mgr.AMgr.GetOrCreate(role.RId, reqObj.CityId, reqObj.Order)
if err != nil{
rsp.Body.Code = constant.DBError
return
}
if army.FromX != city.X || army.FromY != city.Y {
rsp.Body.Code = constant.ArmyIsOutside
return
}
//下阵
if reqObj.Position == -1{
for pos, g := range army.Gens {
if g != nil && g.Id == newG.Id{
//征兵中不能下阵
if army.PositionCanModify(pos) == false{
if army.Cmd == model.ArmyCmdConscript{
rsp.Body.Code = constant.GeneralBusy
}else{
rsp.Body.Code = constant.ArmyBusy
}
return
}
army.GeneralArray[pos] = 0
army.SoldierArray[pos] = 0
army.Gens[pos] = nil
army.SyncExecute()
break
}
}
newG.Order = 0
newG.CityId = 0
newG.SyncExecute()
}else{
//征兵中不能下阵
if army.PositionCanModify(reqObj.Position) == false{
if army.Cmd == model.ArmyCmdConscript{
rsp.Body.Code = constant.GeneralBusy
}else{
rsp.Body.Code = constant.ArmyBusy
}
return
}
if newG.CityId != 0{
rsp.Body.Code = constant.GeneralBusy
return
}
if mgr.AMgr.IsRepeat(role.RId, newG.CfgId) == false{
rsp.Body.Code = constant.GeneralRepeat
return
}
//判断是否能配前锋
tst, ok := mgr.RFMgr.GetFacility(city.CityId, facility.TongShuaiTing)
if reqObj.Position == 2 && ( ok == false || tst.GetLevel() < reqObj.Order) {
rsp.Body.Code = constant.TongShuaiNotEnough
return
}
//判断cost
cost := general.General.Cost(newG.CfgId)
for i, g := range army.Gens {
if g == nil || i == reqObj.Position {
continue
}
cost += general.General.Cost(g.CfgId)
}
if mgr.GetCityCost(city.CityId) < cost{
rsp.Body.Code = constant.CostNotEnough
return
}
oldG := army.Gens[reqObj.Position]
if oldG != nil {
//旧的下阵
oldG.CityId = 0
oldG.Order = 0
oldG.SyncExecute()
}
//新的上阵
army.GeneralArray[reqObj.Position] = reqObj.GeneralId
army.Gens[reqObj.Position] = newG
army.SoldierArray[reqObj.Position] = 0
newG.Order = reqObj.Order
newG.CityId = reqObj.CityId
newG.SyncExecute()
}
army.FromX = city.X
army.FromY = city.Y
army.SyncExecute()
//队伍
rspObj.Army = army.ToProto().(proto.Army)
}
//征兵
func (this*Army) conscript(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ConscriptReq{}
rspObj := &proto.ConscriptRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
if reqObj.ArmyId <= 0 || len(reqObj.Cnts) != 3 ||
reqObj.Cnts[0] < 0 || reqObj.Cnts[1] < 0 || reqObj.Cnts[2] < 0{
rsp.Body.Code = constant.InvalidParam
return
}
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
army,ok := mgr.AMgr.Get(reqObj.ArmyId)
if ok == false{
rsp.Body.Code = constant.ArmyNotFound
return
}
if role.RId != army.RId{
rsp.Body.Code = constant.ArmyNotMe
return
}
//判断该位置是否能征兵
for pos, cnt := range reqObj.Cnts {
if cnt > 0{
if army.Gens[pos] == nil{
rsp.Body.Code = constant.InvalidParam
return
}
if army.PositionCanModify(pos) == false{
rsp.Body.Code = constant.GeneralBusy
return
}
}
}
lv := mgr.RFMgr.GetFacilityLv(army.CityId, facility.MBS)
if lv <= 0{
rsp.Body.Code = constant.BuildMBSNotFound
return
}
//判断是否超过上限
for i, g := range army.Gens {
if g == nil {
continue
}
l, e := general.GenBasic.GetLevel(g.Level)
add := mgr.RFMgr.GetAdditions(army.CityId, facility.TypeSoldierLimit)
if e == nil{
if l.Soldiers + add[0] < reqObj.Cnts[i]+army.SoldierArray[i]{
rsp.Body.Code = constant.OutArmyLimit
return
}
}else{
rsp.Body.Code = constant.InvalidParam
return
}
}
//开始征兵
total := 0
for _, n := range reqObj.Cnts {
total += n
}
conscript := static_conf.Basic.ConScript
needWood := total*conscript.CostWood
needGrain := total*conscript.CostGrain
needIron := total*conscript.CostIron
needStone := total*conscript.CostStone
needGold := total*conscript.CostGold
nr := facility.NeedRes{Grain: needGrain, Wood: needWood,
Gold: needGold, Iron: needIron, Decree: 0,
Stone: needStone}
if code := mgr.RResMgr.TryUseNeed(army.RId, nr); code == constant.OK {
curTime := time.Now().Unix()
for i, _ := range army.SoldierArray {
if reqObj.Cnts[i] > 0{
army.ConscriptCntArray[i] = reqObj.Cnts[i]
army.ConscriptTimeArray[i] = int64(reqObj.Cnts[i]*conscript.CostTime) + curTime - 2
}
}
army.Cmd = model.ArmyCmdConscript
army.SyncExecute()
//队伍
rspObj.Army = army.ToProto().(proto.Army)
//资源
if rRes, ok := mgr.RResMgr.Get(role.RId); ok {
rspObj.RoleRes = rRes.ToProto().(proto.RoleRes)
}
rsp.Body.Code = constant.OK
}else{
rsp.Body.Code = constant.ResNotEnough
}
}
//派遣队伍
func (this*Army) assign(req *net.WsMsgReq, rsp *net.WsMsgRsp){
reqObj := &proto.AssignArmyReq{}
rspObj := &proto.AssignArmyRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
army,ok := mgr.AMgr.Get(reqObj.ArmyId)
if ok == false{
rsp.Body.Code = constant.ArmyNotFound
return
}
if role.RId != army.RId{
rsp.Body.Code = constant.ArmyNotMe
return
}
if reqObj.Cmd == model.ArmyCmdBack{
rsp.Body.Code = this.__back__(army)
}else if reqObj.Cmd == model.ArmyCmdAttack {
rsp.Body.Code = this.__attack__(reqObj, army, role)
}else if reqObj.Cmd == model.ArmyCmdDefend {
rsp.Body.Code = this.__defend__(reqObj, army, role)
}else if reqObj.Cmd == model.ArmyCmdReclamation {
rsp.Body.Code = this.__reclamation__(reqObj, army, role)
}else if reqObj.Cmd == model.ArmyCmdTransfer {
rsp.Body.Code = this.__transfer__(reqObj, army, role)
}
rspObj.Army = army.ToProto().(proto.Army)
}
func (this*Army) __pre__(reqObj *proto.AssignArmyReq, army* model.Army, role *model.Role) int{
if reqObj.X < 0 || reqObj.X >= global.MapWith ||
reqObj.Y < 0 || reqObj.Y >= global.MapHeight {
return constant.InvalidParam
}
if army.IsCanOutWar() == false{
if army.Cmd != model.ArmyCmdIdle{
return constant.ArmyBusy
}else{
return constant.ArmyNotMain
}
}
if army.IsIdle() == false {
return constant.ArmyBusy
}
//判断该地是否是能攻击类型
cfg, ok := mgr.NMMgr.PositionBuild(reqObj.X, reqObj.Y)
if ok == false || cfg.Type == 0 {
return constant.InvalidParam
}
if logic.IsCanArrive(reqObj.X, reqObj.Y, role.RId) == false{
return constant.UnReachable
}
return constant.OK
}
func (this*Army) __after__(reqObj *proto.AssignArmyReq, army* model.Army) int{
//最后才消耗体力
cost := static_conf.Basic.General.CostPhysicalPower
ok := mgr.GMgr.PhysicalPowerIsEnough(army, cost)
if ok == false{
return constant.PhysicalPowerNotEnough
}
if reqObj.Cmd == model.ArmyCmdReclamation || reqObj.Cmd == model.ArmyCmdTransfer {
cost := static_conf.Basic.General.ReclamationCost
if mgr.RResMgr.DecreeIsEnough(army.RId, cost) == false{
return constant.DecreeNotEnough
}else{
mgr.RResMgr.TryUseDecree(army.RId, cost)
}
}
mgr.GMgr.TryUsePhysicalPower(army, cost)
army.ToX = reqObj.X
army.ToY = reqObj.Y
army.Cmd = reqObj.Cmd
army.State = model.ArmyRunning
//speed := mgr.AMgr.GetSpeed(army)
//t := mgr.TravelTime(speed, army.FromX, army.FromY, army.ToX, army.ToY)
army.Start = time.Now()
//army.End = time.Now().Add(time.Duration(t) * time.Millisecond)
army.End = time.Now().Add(40*time.Second)
logic.ArmyLogic.PushAction(army)
return constant.OK
}
//返回
func (this*Army) __back__(army* model.Army) int{
if army.Cmd == model.ArmyCmdAttack ||
army.Cmd == model.ArmyCmdDefend ||
army.Cmd == model.ArmyCmdReclamation {
logic.ArmyLogic.ArmyBack(army)
}else if army.IsIdle(){
city, ok := mgr.RCMgr.Get(army.CityId)
if ok {
if city.X != army.FromX || city.Y != army.FromY{
logic.ArmyLogic.ArmyBack(army)
}
}
}
return constant.OK
}
//攻击
func (this*Army) __attack__(reqObj *proto.AssignArmyReq, army* model.Army, role *model.Role) int{
code := this.__pre__(reqObj, army, role)
if code != constant.OK {
return code
}
if logic.IsCanArrive(reqObj.X, reqObj.Y, role.RId) == false{
return constant.UnReachable
}
//免战
if logic.IsWarFree(reqObj.X, reqObj.Y){
return constant.BuildWarFree
}
if logic.IsCanDefend(reqObj.X, reqObj.Y, role.RId) == true {
return constant.BuildCanNotAttack
}
return this.__after__(reqObj, army)
}
//驻守
func (this*Army) __defend__(reqObj *proto.AssignArmyReq, army* model.Army, role *model.Role) int{
code := this.__pre__(reqObj, army, role)
if code != constant.OK {
return code
}
if logic.IsCanDefend(reqObj.X, reqObj.Y, role.RId) == false {
return constant.BuildCanNotDefend
}
return this.__after__(reqObj, army)
}
func (this*Army) __reclamation__(reqObj *proto.AssignArmyReq, army* model.Army, role *model.Role) int{
code := this.__pre__(reqObj, army, role)
if code != constant.OK {
return code
}
if mgr.RBMgr.BuildIsRId(reqObj.X, reqObj.Y, role.RId) == false {
return constant.BuildNotMe
}
return this.__after__(reqObj, army)
}
func (this*Army) __transfer__(reqObj *proto.AssignArmyReq, army* model.Army, role *model.Role) int{
code := this.__pre__(reqObj, army, role)
if code != constant.OK {
return code
}
if army.FromX == reqObj.X && army.FromY == reqObj.Y{
return constant.CanNotTransfer
}
if mgr.RBMgr.BuildIsRId(reqObj.X, reqObj.Y, role.RId) == false {
return constant.BuildNotMe
}
b, ok := mgr.RBMgr.PositionBuild(reqObj.X, reqObj.Y)
if ok == false {
return constant.BuildNotMe
}
if b.Level <= 0 || b.IsHasTransferAuth() == false {
return constant.CanNotTransfer
}
cnt := 0
if b.IsRoleFortress() {
cnt = static_conf.MapBCConf.GetHoldArmyCnt(b.Type, b.Level)
}else{
cnt = 5
}
if cnt > mgr.AMgr.BelongPosArmyCnt(b.RId, b.X, b.Y) {
return this.__after__(reqObj, army)
}else{
return constant.HoldIsFull
}
}

View File

@@ -0,0 +1,109 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"slgserver/constant"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/proto"
)
var DefaultCity = City{
}
type City struct {
}
func (this*City) InitRouter(r *net.Router) {
g := r.Group("city").Use(middleware.ElapsedTime(), middleware.Log(),
middleware.CheckLogin(), middleware.CheckRole())
g.AddRouter("facilities", this.facilities)
g.AddRouter("upFacility", this.upFacility)
}
func (this*City) facilities(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.FacilitiesReq{}
rspObj := &proto.FacilitiesRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rspObj.CityId = reqObj.CityId
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
city, ok := mgr.RCMgr.Get(reqObj.CityId)
if ok == false {
rsp.Body.Code = constant.CityNotExist
return
}
role := r.(*model.Role)
if city.RId != role.RId {
rsp.Body.Code = constant.CityNotMe
return
}
f, ok := mgr.RFMgr.Get(reqObj.CityId)
if ok == false {
rsp.Body.Code = constant.CityNotExist
return
}
t := f.Facility()
rspObj.Facilities = make([]proto.Facility, len(t))
for i, v := range t {
rspObj.Facilities[i].Name = v.Name
rspObj.Facilities[i].Level = v.GetLevel()
rspObj.Facilities[i].Type = v.Type
rspObj.Facilities[i].UpTime = v.UpTime
}
}
//升级需要耗费时间,为了减少定时任务,升级这里做成被动触发产生,不做定时任务
func (this*City) upFacility(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.UpFacilityReq{}
rspObj := &proto.UpFacilityRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rspObj.CityId = reqObj.CityId
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
city, ok := mgr.RCMgr.Get(reqObj.CityId)
if ok == false {
rsp.Body.Code = constant.CityNotExist
return
}
role := r.(*model.Role)
if city.RId != role.RId {
rsp.Body.Code = constant.CityNotMe
return
}
_, ok = mgr.RFMgr.Get(reqObj.CityId)
if ok == false {
rsp.Body.Code = constant.CityNotExist
return
}
out, errCode := mgr.RFMgr.UpFacility(role.RId ,reqObj.CityId, reqObj.FType)
rsp.Body.Code = errCode
if errCode == constant.OK{
rspObj.Facility.Level = out.GetLevel()
rspObj.Facility.Type = out.Type
rspObj.Facility.Name = out.Name
rspObj.Facility.UpTime = out.UpTime
if roleRes, ok:= mgr.RResMgr.Get(role.RId); ok {
rspObj.RoleRes = roleRes.ToProto().(proto.RoleRes)
}
}
}

View File

@@ -0,0 +1,688 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"log/slog"
"slgserver/constant"
"slgserver/db"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/slgserver/logic"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf"
"time"
)
var DefaultCoalition= coalition{
}
type coalition struct {
}
func (this *coalition) InitRouter(r *net.Router) {
g := r.Group("union").Use(middleware.ElapsedTime(), middleware.Log(),
middleware.CheckLogin(), middleware.CheckRole())
g.AddRouter("create", this.create)
g.AddRouter("list", this.list)
g.AddRouter("join", this.join)
g.AddRouter("verify", this.verify)
g.AddRouter("member", this.member)
g.AddRouter("applyList", this.applyList)
g.AddRouter("exit", this.exit)
g.AddRouter("dismiss", this.dismiss)
g.AddRouter("notice", this.notice)
g.AddRouter("modNotice", this.modNotice)
g.AddRouter("kick", this.kick)
g.AddRouter("appoint", this.appoint)
g.AddRouter("abdicate", this.abdicate)
g.AddRouter("info", this.info)
g.AddRouter("log", this.log)
}
//创建联盟
func (this *coalition) create(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.CreateReq{}
rspObj := &proto.CreateRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
rspObj.Name = reqObj.Name
has := mgr.RAttrMgr.IsHasUnion(role.RId)
if has {
rsp.Body.Code = constant.UnionAlreadyHas
return
}
c, ok := mgr.UnionMgr.Create(reqObj.Name, role.RId)
if ok {
rspObj.Id = c.Id
logic.Union.MemberEnter(role.RId, c.Id)
model.NewCreate(role.NickName, c.Id, role.RId)
}else{
rsp.Body.Code = constant.UnionCreateError
}
}
//联盟列表
func (this *coalition) list(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ListReq{}
rspObj := &proto.ListRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
l := mgr.UnionMgr.List()
rspObj.List = make([]proto.Union, len(l))
for i, u := range l {
rspObj.List[i] = u.ToProto().(proto.Union)
main := make([]proto.Major, 0)
if r, ok := mgr.RMgr.Get(u.Chairman); ok {
m := proto.Major{Name: r.NickName, RId: r.RId, Title: proto.UnionChairman}
main = append(main, m)
}
if r, ok := mgr.RMgr.Get(u.ViceChairman); ok {
m := proto.Major{Name: r.NickName, RId: r.RId, Title: proto.UnionViceChairman}
main = append(main, m)
}
rspObj.List[i].Major = main
}
}
//加入
func (this *coalition) join(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.JoinReq{}
rspObj := &proto.JoinRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
has := mgr.RAttrMgr.IsHasUnion(role.RId)
if has {
rsp.Body.Code = constant.UnionAlreadyHas
return
}
u, ok := mgr.UnionMgr.Get(reqObj.Id)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
if len(u.MemberArray) >= static_conf.Basic.Union.MemberLimit{
rsp.Body.Code = constant.PeopleIsFull
return
}
//判断当前是否已经有申请
has, _ = db.MasterDB.Table(model.CoalitionApply{}).Where(
"union_id=? and state=? and rid=?",
reqObj.Id, proto.UnionUntreated, role.RId).Get(&model.CoalitionApply{})
if has {
rsp.Body.Code = constant.HasApply
return
}
//写入申请列表
apply := &model.CoalitionApply{
RId: role.RId,
UnionId: reqObj.Id,
Ctime: time.Now(),
State: proto.UnionUntreated}
_, err := db.MasterDB.InsertOne(apply)
if err != nil{
rsp.Body.Code = constant.DBError
slog.Warn("db error", "error", err)
return
}
//推送主、副盟主
apply.SyncExecute()
}
//审核
func (this *coalition) verify(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.VerifyReq{}
rspObj := &proto.VerifyRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rspObj.Id = reqObj.Id
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
apply := &model.CoalitionApply{}
ok, err := db.MasterDB.Table(model.CoalitionApply{}).Where(
"id=? and state=?", reqObj.Id, proto.UnionUntreated).Get(apply)
if ok && err == nil{
targetRole, ok := mgr.RMgr.Get(apply.RId)
if ok == false{
rsp.Body.Code = constant.RoleNotExist
return
}
if u, ok := mgr.UnionMgr.Get(apply.UnionId); ok {
if u.Chairman != role.RId && u.ViceChairman != role.RId {
rsp.Body.Code = constant.PermissionDenied
return
}
if len(u.MemberArray) >= static_conf.Basic.Union.MemberLimit{
rsp.Body.Code = constant.PeopleIsFull
return
}
if ok := mgr.RAttrMgr.IsHasUnion(apply.RId); ok {
rsp.Body.Code = constant.UnionAlreadyHas
}else{
if reqObj.Decide == proto.UnionAdopt {
//同意
c, ok := mgr.UnionMgr.Get(apply.UnionId)
if ok {
c.MemberArray = append(c.MemberArray, apply.RId)
logic.Union.MemberEnter(apply.RId, apply.UnionId)
c.SyncExecute()
model.NewJoin(targetRole.NickName, apply.UnionId, role.RId, apply.RId)
}
}
}
apply.State = reqObj.Decide
db.MasterDB.Table(apply).ID(apply.Id).Cols("state").Update(apply)
}else{
rsp.Body.Code = constant.UnionNotFound
return
}
}else{
rsp.Body.Code = constant.InvalidParam
}
}
//成员列表
func (this *coalition) member(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.MemberReq{}
rspObj := &proto.MemberRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rspObj.Id = reqObj.Id
rsp.Body.Code = constant.OK
union, ok := mgr.UnionMgr.Get(reqObj.Id)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
rspObj.Members = make([]proto.Member, 0)
for _, rid := range union.MemberArray {
if role, ok := mgr.RMgr.Get(rid); ok {
m := proto.Member{RId: role.RId, Name: role.NickName }
if main, ok := mgr.RCMgr.GetMainCity(role.RId); ok {
m.X = main.X
m.Y = main.Y
}
if rid == union.Chairman {
m.Title = proto.UnionChairman
}else if rid == union.ViceChairman {
m.Title = proto.UnionViceChairman
}else {
m.Title = proto.UnionCommon
}
rspObj.Members = append(rspObj.Members, m)
}
}
}
//申请列表
func (this *coalition) applyList(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ApplyReq{}
rspObj := &proto.ApplyRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
u, ok := mgr.UnionMgr.Get(reqObj.Id)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
if u.Chairman != role.RId && u.ViceChairman != role.RId {
rspObj.Applys = make([]proto.ApplyItem, 0)
return
}
applys := make([]*model.CoalitionApply, 0)
err := db.MasterDB.Table(model.CoalitionApply{}).Where(
"union_id=? and state=?", reqObj.Id, 0).Find(&applys)
if err != nil{
rsp.Body.Code = constant.DBError
return
}
rspObj.Id = reqObj.Id
rspObj.Applys = make([]proto.ApplyItem, 0)
for _, apply := range applys {
if r, ok := mgr.RMgr.Get(apply.RId);ok{
a := proto.ApplyItem{Id: apply.Id, RId: apply.RId, NickName: r.NickName}
rspObj.Applys = append(rspObj.Applys, a)
}
}
}
//退出
func (this *coalition) exit(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ExitReq{}
rspObj := &proto.ExitRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if ok := mgr.RAttrMgr.IsHasUnion(role.RId); ok == false {
rsp.Body.Code = constant.UnionNotFound
return
}
attribute, _ := mgr.RAttrMgr.Get(role.RId)
u, ok := mgr.UnionMgr.Get(attribute.UnionId)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
//盟主不能退出
if u.Chairman == role.RId {
rsp.Body.Code = constant.UnionNotAllowExit
return
}
for i, rid := range u.MemberArray {
if rid == role.RId{
u.MemberArray = append(u.MemberArray[:i], u.MemberArray[i+1:]...)
}
}
if u.ViceChairman == role.RId{
u.ViceChairman = 0
}
logic.Union.MemberExit(role.RId)
u.SyncExecute()
model.NewExit(role.NickName, u.Id, role.RId)
}
//解散
func (this *coalition) dismiss(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.DismissReq{}
rspObj := &proto.DismissRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if ok := mgr.RAttrMgr.IsHasUnion(role.RId); ok == false {
rsp.Body.Code = constant.UnionNotFound
return
}
attribute, _ := mgr.RAttrMgr.Get(role.RId)
u, ok := mgr.UnionMgr.Get(attribute.UnionId)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
//盟主才能解散
if u.Chairman != role.RId {
rsp.Body.Code = constant.PermissionDenied
return
}
unionId := attribute.UnionId
logic.Union.Dismiss(unionId)
model.NewDismiss(role.NickName, unionId, role.RId)
}
//公告
func (this *coalition) notice(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.NoticeReq{}
rspObj := &proto.NoticeRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
u, ok := mgr.UnionMgr.Get(reqObj.Id)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
rspObj.Text = u.Notice
}
//修改公告
func (this *coalition) modNotice(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ModNoticeReq{}
rspObj := &proto.ModNoticeRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if len(reqObj.Text) > 200 {
rsp.Body.Code = constant.ContentTooLong
return
}
if ok := mgr.RAttrMgr.IsHasUnion(role.RId); ok == false {
rsp.Body.Code = constant.UnionNotFound
return
}
attribute, _ := mgr.RAttrMgr.Get(role.RId)
u, ok := mgr.UnionMgr.Get(attribute.UnionId)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
if u.Chairman != role.RId && u.ViceChairman != role.RId {
rsp.Body.Code = constant.PermissionDenied
return
}
rspObj.Text = reqObj.Text
rspObj.Id = u.Id
u.Notice = reqObj.Text
u.SyncExecute()
model.NewModNotice(role.NickName, u.Id, role.RId)
}
//踢人
func (this *coalition) kick(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.KickReq{}
rspObj := &proto.KickRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rspObj.RId = reqObj.RId
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if ok := mgr.RAttrMgr.IsHasUnion(role.RId); ok == false {
rsp.Body.Code = constant.UnionNotFound
return
}
opAr, _ := mgr.RAttrMgr.Get(role.RId)
u, ok := mgr.UnionMgr.Get(opAr.UnionId)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
if u.Chairman != role.RId && u.ViceChairman != role.RId {
rsp.Body.Code = constant.PermissionDenied
return
}
if role.RId == reqObj.RId {
rsp.Body.Code = constant.PermissionDenied
return
}
targetRole, ok := mgr.RMgr.Get(reqObj.RId)
if ok == false {
rsp.Body.Code = constant.RoleNotExist
return
}
target, ok := mgr.RAttrMgr.Get(reqObj.RId)
if ok {
if target.UnionId == u.Id{
for i, rid := range u.MemberArray {
if rid == reqObj.RId{
u.MemberArray = append(u.MemberArray[:i], u.MemberArray[i+1:]...)
}
}
if u.ViceChairman == reqObj.RId{
u.ViceChairman = 0
}
logic.Union.MemberExit(reqObj.RId)
target.UnionId = 0
u.SyncExecute()
model.NewKick(role.NickName, targetRole.NickName, u.Id, role.RId, target.RId)
}else{
rsp.Body.Code = constant.NotBelongUnion
}
}else{
rsp.Body.Code = constant.NotBelongUnion
}
}
//任命
func (this *coalition) appoint(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.AppointReq{}
rspObj := &proto.AppointRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rspObj.RId = reqObj.RId
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if ok := mgr.RAttrMgr.IsHasUnion(role.RId); ok == false {
rsp.Body.Code = constant.UnionNotFound
return
}
opAr, _ := mgr.RAttrMgr.Get(role.RId)
u, ok := mgr.UnionMgr.Get(opAr.UnionId)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
if u.Chairman != role.RId {
rsp.Body.Code = constant.PermissionDenied
return
}
targetRole, ok := mgr.RMgr.Get(reqObj.RId)
if ok == false {
rsp.Body.Code = constant.RoleNotExist
return
}
target, ok := mgr.RAttrMgr.Get(reqObj.RId)
if ok {
if target.UnionId == u.Id{
if reqObj.Title == proto.UnionViceChairman {
u.ViceChairman = reqObj.RId
rspObj.Title = reqObj.Title
u.SyncExecute()
model.NewAppoint(role.NickName, targetRole.NickName, u.Id, role.RId, targetRole.RId, reqObj.Title)
}else if reqObj.Title == proto.UnionCommon {
if u.ViceChairman == reqObj.RId{
u.ViceChairman = 0
}
rspObj.Title = reqObj.Title
model.NewAppoint(role.NickName, targetRole.NickName, u.Id, role.RId, targetRole.RId, reqObj.Title)
}else{
rsp.Body.Code = constant.InvalidParam
}
}else{
rsp.Body.Code = constant.NotBelongUnion
}
}else{
rsp.Body.Code = constant.NotBelongUnion
}
}
//禅让
func (this *coalition) abdicate(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.AbdicateReq{}
rspObj := &proto.AbdicateRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if ok := mgr.RAttrMgr.IsHasUnion(role.RId); ok == false {
rsp.Body.Code = constant.UnionNotFound
return
}
opAr, _ := mgr.RAttrMgr.Get(role.RId)
u, ok := mgr.UnionMgr.Get(opAr.UnionId)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
targetRole, ok := mgr.RMgr.Get(reqObj.RId)
if ok == false {
rsp.Body.Code = constant.RoleNotExist
return
}
if u.Chairman != role.RId && u.ViceChairman != role.RId {
rsp.Body.Code = constant.PermissionDenied
return
}
target, ok := mgr.RAttrMgr.Get(reqObj.RId)
if ok {
if target.UnionId == u.Id{
if role.RId == u.Chairman{
u.Chairman = reqObj.RId
if u.ViceChairman == reqObj.RId{
u.ViceChairman = 0
}
u.SyncExecute()
model.NewAbdicate(role.NickName, targetRole.NickName, u.Id,
role.RId, targetRole.RId, proto.UnionChairman)
}else if role.RId == u.ViceChairman {
u.ViceChairman = reqObj.RId
u.SyncExecute()
model.NewAbdicate(role.NickName, targetRole.NickName, u.Id,
role.RId, targetRole.RId, proto.UnionViceChairman)
}
}else{
rsp.Body.Code = constant.NotBelongUnion
}
}else{
rsp.Body.Code = constant.NotBelongUnion
}
}
//联盟信息
func (this *coalition) info(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.InfoReq{}
rspObj := &proto.InfoRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rspObj.Id = reqObj.Id
rsp.Body.Code = constant.OK
u, ok := mgr.UnionMgr.Get(reqObj.Id)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
}else{
rspObj.Info = u.ToProto().(proto.Union)
main := make([]proto.Major, 0)
if r, ok := mgr.RMgr.Get(u.Chairman); ok {
m := proto.Major{Name: r.NickName, RId: r.RId, Title: proto.UnionChairman}
main = append(main, m)
}
if r, ok := mgr.RMgr.Get(u.ViceChairman); ok {
m := proto.Major{Name: r.NickName, RId: r.RId, Title: proto.UnionViceChairman}
main = append(main, m)
}
rspObj.Info.Major = main
}
}
//联盟日志
func (this *coalition) log(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.LogReq{}
rspObj := &proto.LogRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rspObj.Logs = make([]proto.UnionLog, 0)
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
opAr, _ := mgr.RAttrMgr.Get(role.RId)
u, ok := mgr.UnionMgr.Get(opAr.UnionId)
if ok == false{
rsp.Body.Code = constant.UnionNotFound
return
}
//开始查询日志
logs := make([]*model.CoalitionLog, 0)
err := db.MasterDB.Table(model.CoalitionLog{}).Where(
"union_id=?", u.Id).Desc("ctime").Find(&logs)
if err != nil{
slog.Warn("db error", "error", err)
}
for _, cLog := range logs {
rspObj.Logs = append(rspObj.Logs, cLog.ToProto().(proto.UnionLog))
}
}

View File

@@ -0,0 +1,385 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"slgserver/constant"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf"
"slgserver/server/slgserver/static_conf/skill"
)
var DefaultGeneral = General{
}
type General struct {
}
func (this*General) InitRouter(r *net.Router) {
g := r.Group("general").Use(middleware.ElapsedTime(), middleware.Log(),
middleware.CheckLogin(), middleware.CheckRole())
g.AddRouter("myGenerals", this.myGenerals)
g.AddRouter("drawGeneral", this.drawGenerals)
g.AddRouter("composeGeneral", this.composeGeneral)
g.AddRouter("addPrGeneral", this.addPrGeneral)
g.AddRouter("convert", this.convert)
g.AddRouter("upSkill", this.upSkill)
g.AddRouter("downSkill", this.downSkill)
g.AddRouter("lvSkill", this.lvSkill)
}
func (this*General) myGenerals(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.MyGeneralReq{}
rspObj := &proto.MyGeneralRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
gs, ok := mgr.GMgr.GetOrCreateByRId(role.RId)
if ok {
rsp.Body.Code = constant.OK
rspObj.Generals = make([]proto.General, 0)
for _, v := range gs {
rspObj.Generals = append(rspObj.Generals, v.ToProto().(proto.General))
}
}else{
rsp.Body.Code = constant.DBError
}
}
func (this*General) drawGenerals(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.DrawGeneralReq{}
rspObj := &proto.DrawGeneralRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
cost := static_conf.Basic.General.DrawGeneralCost * reqObj.DrawTimes
ok := mgr.RResMgr.GoldIsEnough(role.RId,cost)
if ok == false{
rsp.Body.Code = constant.GoldNotEnough
return
}
limit := static_conf.Basic.General.Limit
cnt := mgr.GMgr.Count(role.RId)
if cnt + reqObj.DrawTimes > limit{
rsp.Body.Code = constant.OutGeneralLimit
return
}
gs, ok := mgr.GMgr.RandCreateGeneral(role.RId,reqObj.DrawTimes)
if ok {
mgr.RResMgr.TryUseGold(role.RId, cost)
rsp.Body.Code = constant.OK
rspObj.Generals = make([]proto.General, len(gs))
for i, v := range gs {
rspObj.Generals[i] = v.ToProto().(proto.General)
}
}else{
rsp.Body.Code = constant.DBError
}
}
func (this*General) composeGeneral(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ComposeGeneralReq{}
rspObj := &proto.ComposeGeneralRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
gs, ok := mgr.GMgr.HasGeneral(role.RId,reqObj.CompId)
//是否有这个武将
if ok == false{
rsp.Body.Code = constant.GeneralNoHas
return
}
//是否都有这个武将
gss ,ok := mgr.GMgr.HasGenerals(role.RId,reqObj.GIds)
if ok == false{
rsp.Body.Code = constant.GeneralNoHas
return
}
ok = true
for _, v := range gss {
t := v
if t.CfgId != gs.CfgId {
ok = false
}
}
//是否同一个类型的武将
if ok == false {
rsp.Body.Code = constant.GeneralNoSame
return
}
//是否超过武将星级
if int(gs.Star - gs.StarLv) < len(gss){
rsp.Body.Code = constant.GeneralStarMax
return
}
gs.StarLv += int8(len(gss))
gs.HasPrPoint += static_conf.Basic.General.PrPoint * len(gss)
gs.SyncExecute()
for _, v := range gss {
t := v
t.ParentId = gs.Id
t.State = model.GeneralComposeStar
t.SyncExecute()
}
rspObj.Generals = make([]proto.General, len(gss))
for i, v := range gss {
rspObj.Generals[i] = v.ToProto().(proto.General)
}
rspObj.Generals = append(rspObj.Generals,gs.ToProto().(proto.General))
}
func (this*General) addPrGeneral(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.AddPrGeneralReq{}
rspObj := &proto.AddPrGeneralRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
gs, ok := mgr.GMgr.HasGeneral(role.RId,reqObj.CompId)
//是否有这个武将
if ok == false{
rsp.Body.Code = constant.GeneralNoHas
return
}
all:= reqObj.ForceAdd + reqObj.StrategyAdd + reqObj.DefenseAdd + reqObj.SpeedAdd + reqObj.DestroyAdd
if gs.HasPrPoint < all{
rsp.Body.Code = constant.DBError
return
}
gs.ForceAdded = reqObj.ForceAdd
gs.StrategyAdded = reqObj.StrategyAdd
gs.DefenseAdded = reqObj.DefenseAdd
gs.SpeedAdded = reqObj.SpeedAdd
gs.DestroyAdded = reqObj.DestroyAdd
gs.UsePrPoint = all
gs.SyncExecute()
rsp.Body.Code = constant.OK
rspObj.Generals = gs.ToProto().(proto.General)
}
func (this*General) convert(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ConvertReq{}
rspObj := &proto.ConvertRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
roleRes, ok:= mgr.RResMgr.Get(role.RId)
if ok == false {
rsp.Body.Code = constant.DBError
return
}
gold := 0
okArray := make([]int, 0)
for _, gid := range reqObj.GIds {
g, ok := mgr.GMgr.GetByGId(gid)
if ok && g.Order == 0{
okArray = append(okArray, gid)
gold += 10* int(g.Star)*(1 + int(g.StarLv))
g.State = model.GeneralConvert
g.SyncExecute()
}
}
roleRes.Gold += gold
rspObj.AddGold = gold
rspObj.Gold = roleRes.Gold
rspObj.GIds = okArray
roleRes.SyncExecute()
}
func (this*General) upSkill(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.UpDownSkillReq{}
rspObj := &proto.UpDownSkillRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
rspObj.Pos = reqObj.Pos
rspObj.CfgId = reqObj.CfgId
rspObj.GId = reqObj.GId
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if reqObj.Pos <0 || reqObj.Pos >= model.SkillLimit {
rsp.Body.Code = constant.InvalidParam
return
}
g,ok := mgr.GMgr.GetByGId(reqObj.GId)
if ok == false{
rsp.Body.Code = constant.GeneralNotFound
return
}
if g.RId != role.RId{
rsp.Body.Code = constant.GeneralNotMe
return
}
skill, ok := mgr.SkillMgr.GetSkillOrCreate(role.RId, reqObj.CfgId)
if ok == false {
rsp.Body.Code = constant.DBError
return
}
if skill.IsInLimit() == false{
rsp.Body.Code = constant.OutSkillLimit
return
}
if skill.ArmyIsIn(g.CurArms) == false{
rsp.Body.Code = constant.OutArmNotMatch
return
}
if g.UpSkill(skill.Id, reqObj.CfgId, reqObj.Pos) == false{
rsp.Body.Code = constant.UpSkillError
return
}
skill.UpSkill(g.Id)
g.SyncExecute()
skill.SyncExecute()
}
func (this*General) downSkill(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.UpDownSkillReq{}
rspObj := &proto.UpDownSkillRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
rspObj.Pos = reqObj.Pos
rspObj.CfgId = reqObj.CfgId
rspObj.GId = reqObj.GId
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if reqObj.Pos <0 || reqObj.Pos >= model.SkillLimit {
rsp.Body.Code = constant.InvalidParam
return
}
g,ok := mgr.GMgr.GetByGId(reqObj.GId)
if ok == false{
rsp.Body.Code = constant.GeneralNotFound
return
}
if g.RId != role.RId{
rsp.Body.Code = constant.GeneralNotMe
return
}
skill, ok := mgr.SkillMgr.GetSkillOrCreate(role.RId, reqObj.CfgId)
if ok == false{
rsp.Body.Code = constant.DBError
return
}
if g.DownSkill(skill.Id, reqObj.Pos) == false{
rsp.Body.Code = constant.DownSkillError
return
}
skill.DownSkill(g.Id)
g.SyncExecute()
skill.SyncExecute()
}
func (this*General) lvSkill(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.LvSkillReq{}
rspObj := &proto.LvSkillRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
rspObj.Pos = reqObj.Pos
rspObj.GId = reqObj.GId
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
g, ok := mgr.GMgr.GetByGId(reqObj.GId)
if ok == false{
rsp.Body.Code = constant.GeneralNotFound
return
}
if g.RId != role.RId {
rsp.Body.Code = constant.GeneralNotMe
return
}
gSkill, err := g.PosSkill(reqObj.Pos)
if err != nil{
rsp.Body.Code = constant.PosNotSkill
return
}
skillCfg, ok := skill.Skill.GetCfg(gSkill.CfgId)
if ok == false{
rsp.Body.Code = constant.PosNotSkill
return
}
if gSkill.Lv > len(skillCfg.Levels){
rsp.Body.Code = constant.SkillLevelFull
return
}
gSkill.Lv += 1
g.SyncExecute()
}

View File

@@ -0,0 +1,200 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"slgserver/constant"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf"
"slgserver/server/slgserver/static_conf/facility"
"time"
)
var DefaultInterior = Interior{}
type Interior struct {
}
func (this*Interior) InitRouter(r *net.Router) {
g := r.Group("interior").Use(middleware.ElapsedTime(),
middleware.Log(), middleware.CheckRole())
g.AddRouter("collect", this.collect)
g.AddRouter("openCollect", this.openCollect)
g.AddRouter("transform", this.transform)
}
func (this*Interior) collect(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.CollectionReq{}
rspObj := &proto.CollectionRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
roleRes, ok:= mgr.RResMgr.Get(role.RId)
if ok == false {
rsp.Body.Code = constant.DBError
return
}
roleAttr, ok:= mgr.RAttrMgr.Get(role.RId)
if ok == false {
rsp.Body.Code = constant.DBError
return
}
curTime := time.Now()
lastTime := roleAttr.LastCollectTime
if curTime.YearDay() != lastTime.YearDay() || curTime.Year() != lastTime.Year(){
roleAttr.CollectTimes = 0
roleAttr.LastCollectTime = time.Time{}
}
timeLimit := static_conf.Basic.Role.CollectTimesLimit
//是否超过征收次数上限
if roleAttr.CollectTimes >= timeLimit{
rsp.Body.Code = constant.OutCollectTimesLimit
return
}
//cd内不能操作
need := lastTime.Add(time.Duration(static_conf.Basic.Role.CollectTimesLimit)*time.Second)
if curTime.Before(need){
rsp.Body.Code = constant.InCdCanNotOperate
return
}
gold := mgr.GetYield(roleRes.RId).Gold
rspObj.Gold = gold
roleRes.Gold += gold
//更新
roleRes.SyncExecute()
roleAttr.LastCollectTime = curTime
roleAttr.CollectTimes += 1
roleAttr.SyncExecute()
interval := static_conf.Basic.Role.CollectInterval
if roleAttr.CollectTimes >= timeLimit {
y, m, d := roleAttr.LastCollectTime.Add(24*time.Hour).Date()
nextTime := time.Date(y, m, d, 0, 0, 0, 0, time.FixedZone("IST", 3600))
rspObj.NextTime = nextTime.UnixNano()/1e6
}else{
nextTime := roleAttr.LastCollectTime.Add(time.Duration(interval)*time.Second)
rspObj.NextTime = nextTime.UnixNano()/1e6
}
rspObj.CurTimes = roleAttr.CollectTimes
rspObj.Limit = timeLimit
}
func (this*Interior) openCollect(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.OpenCollectionReq{}
rspObj := &proto.OpenCollectionRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
roleAttr, ok:= mgr.RAttrMgr.Get(role.RId)
if ok == false {
rsp.Body.Code = constant.DBError
return
}
interval := static_conf.Basic.Role.CollectInterval
timeLimit := static_conf.Basic.Role.CollectTimesLimit
rspObj.Limit = timeLimit
rspObj.CurTimes = roleAttr.CollectTimes
if roleAttr.LastCollectTime.IsZero() {
rspObj.NextTime = 0
}else{
if roleAttr.CollectTimes >= timeLimit {
y, m, d := roleAttr.LastCollectTime.Add(24*time.Hour).Date()
nextTime := time.Date(y, m, d, 0, 0, 0, 0, time.FixedZone("IST", 3600))
rspObj.NextTime = nextTime.UnixNano()/1e6
}else{
nextTime := roleAttr.LastCollectTime.Add(time.Duration(interval)*time.Second)
rspObj.NextTime = nextTime.UnixNano()/1e6
}
}
}
func (this*Interior) transform(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.TransformReq{}
rspObj := &proto.TransformRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
roleRes, ok:= mgr.RResMgr.Get(role.RId)
if ok == false {
rsp.Body.Code = constant.DBError
return
}
main, _ := mgr.RCMgr.GetMainCity(role.RId)
lv := mgr.RFMgr.GetFacilityLv(main.CityId, facility.JiShi)
if lv <= 0{
rsp.Body.Code = constant.NotHasJiShi
return
}
len := 4
ret := make([]int, len)
for i := 0 ;i < len; i++{
//ret[i] = reqObj.To[i] - reqObj.From[i]
if reqObj.From[i] > 0{
ret[i] = -reqObj.From[i]
}
if reqObj.To[i] > 0{
ret[i] = reqObj.To[i]
}
}
if roleRes.Wood + ret[0] < 0{
rsp.Body.Code = constant.InvalidParam
return
}
if roleRes.Iron + ret[1] < 0{
rsp.Body.Code = constant.InvalidParam
return
}
if roleRes.Stone + ret[2] < 0{
rsp.Body.Code = constant.InvalidParam
return
}
if roleRes.Grain + ret[3] < 0{
rsp.Body.Code = constant.InvalidParam
return
}
roleRes.Wood += ret[0]
roleRes.Iron += ret[1]
roleRes.Stone += ret[2]
roleRes.Grain += ret[3]
roleRes.SyncExecute()
}

View File

@@ -0,0 +1,274 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"slgserver/constant"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/slgserver/logic"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf"
)
var DefaultMap = NationMap{}
type NationMap struct {
}
func (this*NationMap) InitRouter(r *net.Router) {
g := r.Group("nationMap").Use(middleware.ElapsedTime(), middleware.Log())
g.AddRouter("config", this.config)
g.AddRouter("scan", this.scan, middleware.CheckRole())
g.AddRouter("scanBlock", this.scanBlock, middleware.CheckRole())
g.AddRouter("giveUp", this.giveUp, middleware.CheckRole())
g.AddRouter("build", this.build, middleware.CheckRole())
g.AddRouter("upBuild", this.upBuild, middleware.CheckRole())
g.AddRouter("delBuild", this.delBuild, middleware.CheckRole())
}
/*
获取配置
*/
func (this*NationMap) config(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ConfigReq{}
rspObj := &proto.ConfigRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
m := static_conf.MapBuildConf.Cfg
rspObj.Confs = make([]proto.Conf, len(m))
i := 0
for _, v := range m {
rspObj.Confs[i].Type = v.Type
rspObj.Confs[i].Name = v.Name
rspObj.Confs[i].Level = v.Level
rspObj.Confs[i].Defender = v.Defender
rspObj.Confs[i].Durable = v.Durable
rspObj.Confs[i].Grain = v.Grain
rspObj.Confs[i].Iron = v.Iron
rspObj.Confs[i].Stone = v.Stone
rspObj.Confs[i].Wood = v.Wood
i++
}
}
/*
扫描地图
*/
func (this*NationMap) scan(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ScanReq{}
rspObj := &proto.ScanRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
x := reqObj.X
y := reqObj.Y
rb := mgr.RBMgr.Scan(x, y)
rspObj.MRBuilds = make([]proto.MapRoleBuild, len(rb))
for i, v := range rb {
rspObj.MRBuilds[i] = v.ToProto().(proto.MapRoleBuild)
}
cb := mgr.RCMgr.Scan(x, y)
rspObj.MCBuilds = make([]proto.MapRoleCity, len(cb))
for i, v := range cb {
rspObj.MCBuilds[i] = v.ToProto().(proto.MapRoleCity)
}
}
func (this*NationMap) scanBlock(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.ScanBlockReq{}
rspObj := &proto.ScanRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
x := reqObj.X
y := reqObj.Y
rb := mgr.RBMgr.ScanBlock(x, y, reqObj.Length)
rspObj.MRBuilds = make([]proto.MapRoleBuild, len(rb))
for i, v := range rb {
rspObj.MRBuilds[i] = v.ToProto().(proto.MapRoleBuild)
}
cb := mgr.RCMgr.ScanBlock(x, y, reqObj.Length)
rspObj.MCBuilds = make([]proto.MapRoleCity, len(cb))
for i, v := range cb {
rspObj.MCBuilds[i] = v.ToProto().(proto.MapRoleCity)
}
armys := logic.ArmyLogic.ScanBlock(role.RId, x, y, reqObj.Length)
rspObj.Armys = make([]proto.Army, len(armys))
for i, v := range armys {
rspObj.Armys[i] = v.ToProto().(proto.Army)
}
}
func (this*NationMap) giveUp(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.GiveUpReq{}
rspObj := &proto.GiveUpRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
x := reqObj.X
y := reqObj.Y
rspObj.X = x
rspObj.Y = y
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if mgr.RBMgr.BuildIsRId(x, y, role.RId) == false{
rsp.Body.Code = constant.BuildNotMe
return
}
rsp.Body.Code = mgr.RBMgr.GiveUp(x, y)
}
//建造
func (this*NationMap) build(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.BuildReq{}
rspObj := &proto.BuildRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
x := reqObj.X
y := reqObj.Y
rspObj.X = x
rspObj.Y = y
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if mgr.RBMgr.BuildIsRId(x, y, role.RId) == false{
rsp.Body.Code = constant.BuildNotMe
return
}
b, ok := mgr.RBMgr.PositionBuild(x, y)
if ok == false {
rsp.Body.Code = constant.BuildNotMe
return
}
if b.IsResBuild() == false || b.IsBusy(){
rsp.Body.Code = constant.CanNotBuildNew
return
}
cnt := mgr.RBMgr.RoleFortressCnt(role.RId)
if cnt >= static_conf.Basic.Build.FortressLimit{
rsp.Body.Code = constant.CanNotBuildNew
return
}
cfg, ok := static_conf.MapBCConf.BuildConfig(reqObj.Type, 1)
if ok == false{
rsp.Body.Code = constant.InvalidParam
return
}
code := mgr.RResMgr.TryUseNeed(role.RId, cfg.Need)
if code != constant.OK {
rsp.Body.Code = code
return
}
b.BuildOrUp(*cfg)
b.SyncExecute()
}
func (this*NationMap) upBuild(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.UpBuildReq{}
rspObj := &proto.UpBuildRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
x := reqObj.X
y := reqObj.Y
rspObj.X = x
rspObj.Y = y
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if mgr.RBMgr.BuildIsRId(x, y, role.RId) == false{
rsp.Body.Code = constant.BuildNotMe
return
}
b, ok := mgr.RBMgr.PositionBuild(x, y)
if ok == false {
rsp.Body.Code = constant.BuildNotMe
return
}
if b.IsHaveModifyLVAuth() == false || b.IsInGiveUp() || b.IsBusy(){
rsp.Body.Code = constant.CanNotUpBuild
return
}
cfg, ok := static_conf.MapBCConf.BuildConfig(b.Type, b.Level+1)
if ok == false{
rsp.Body.Code = constant.InvalidParam
return
}
code := mgr.RResMgr.TryUseNeed(role.RId, cfg.Need)
if code != constant.OK {
rsp.Body.Code = code
return
}
b.BuildOrUp(*cfg)
b.SyncExecute()
rspObj.Build = b.ToProto().(proto.MapRoleBuild)
}
func (this*NationMap) delBuild(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.UpBuildReq{}
rspObj := &proto.UpBuildRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
x := reqObj.X
y := reqObj.Y
rspObj.X = x
rspObj.Y = y
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if mgr.RBMgr.BuildIsRId(x, y, role.RId) == false{
rsp.Body.Code = constant.BuildNotMe
return
}
rsp.Body.Code = mgr.RBMgr.Destroy(x, y)
b, ok := mgr.RBMgr.PositionBuild(x, y)
if ok {
rspObj.Build = b.ToProto().(proto.MapRoleBuild)
}
}

View File

@@ -0,0 +1,412 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"log/slog"
"math/rand"
"slgserver/constant"
"slgserver/db"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/slgserver/global"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/pos"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf"
"slgserver/util"
"time"
)
var DefaultRole = Role{}
type Role struct {
}
func (this*Role) InitRouter(r *net.Router) {
g := r.Group("role").Use(middleware.ElapsedTime(), middleware.Log())
g.AddRouter("enterServer", this.enterServer)
g.AddRouter("create", this.create, middleware.CheckLogin())
g.AddRouter("roleList", this.roleList, middleware.CheckLogin())
g.AddRouter("myCity", this.myCity, middleware.CheckRole())
g.AddRouter("myRoleRes", this.myRoleRes, middleware.CheckRole())
g.AddRouter("myRoleBuild", this.myRoleBuild, middleware.CheckRole())
g.AddRouter("myProperty", this.myProperty, middleware.CheckRole())
g.AddRouter("upPosition", this.upPosition, middleware.CheckRole())
g.AddRouter("posTagList", this.posTagList, middleware.CheckRole())
g.AddRouter("opPosTag", this.opPosTag, middleware.CheckRole())
}
func (this*Role) create(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.CreateRoleReq{}
rspObj := &proto.CreateRoleRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
uid, _ := req.Conn.GetProperty("uid")
reqObj.UId = uid.(int)
rspObj.Role.UId = reqObj.UId
r := make([]model.Role, 0)
has, _ := db.MasterDB.Table(r).Where("uid=?", reqObj.UId).Get(r)
if has {
slog.Info("role has create", "uid", reqObj.UId)
rsp.Body.Code = constant.RoleAlreadyCreate
}else {
role := &model.Role{UId: reqObj.UId, HeadId: reqObj.HeadId, Sex: reqObj.Sex,
NickName: reqObj.NickName, CreatedAt: time.Now()}
if _, err := db.MasterDB.Insert(role); err != nil {
slog.Info("role create error",
"uid", reqObj.UId, "error", err)
rsp.Body.Code = constant.DBError
}else{
rspObj.Role.RId = role.RId
rspObj.Role.UId = reqObj.UId
rspObj.Role.NickName = reqObj.NickName
rspObj.Role.Sex = reqObj.Sex
rspObj.Role.HeadId = reqObj.HeadId
rsp.Body.Code = constant.OK
}
}
}
func (this*Role) roleList(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.RoleListReq{}
rspObj := &proto.RoleListRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
uid, _ := req.Conn.GetProperty("uid")
uid = uid.(int)
r := make([]*model.Role, 0)
err := db.MasterDB.Table(r).Where("uid=?", uid).Find(&r)
if err == nil{
rl := make([]proto.Role, len(r))
for i, v := range r {
rl[i] = v.ToProto().(proto.Role)
}
rspObj.Roles = rl
rsp.Body.Code = constant.OK
}else{
rsp.Body.Code = constant.DBError
}
}
func (this*Role) enterServer(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.EnterServerReq{}
rspObj := &proto.EnterServerRsp{}
rspObj.Time = time.Now().UnixNano()/1e6
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
//校验session是否合法
sess, err := util.ParseSession(reqObj.Session)
if err != nil || sess.IsValid() == false{
rsp.Body.Code = constant.SessionInvalid
return
}
uid := sess.Id
req.Conn.SetProperty("uid", uid)
//查询角色
role := &model.Role{}
b, err := db.MasterDB.Table(role).Where("uid=?", uid).Get(role)
if err != nil{
slog.Warn("enterServer db error", "error", err)
rsp.Body.Code = constant.DBError
return
}
if b {
rsp.Body.Code = constant.OK
rspObj.Role = role.ToProto().(proto.Role)
req.Conn.SetProperty("role", role)
net.ConnMgr.RoleEnter(req.Conn, role.RId)
var e error = nil
roleRes, ok := mgr.RResMgr.Get(role.RId)
if ok == false{
roleRes = &model.RoleRes{RId: role.RId,
Wood: static_conf.Basic.Role.Wood,
Iron: static_conf.Basic.Role.Iron,
Stone: static_conf.Basic.Role.Stone,
Grain: static_conf.Basic.Role.Grain,
Gold: static_conf.Basic.Role.Gold,
Decree: static_conf.Basic.Role.Decree}
_ ,e = db.MasterDB.Insert(roleRes)
if e != nil {
slog.Error("insert rres error", "error", e)
}
}
if e == nil {
mgr.RResMgr.Add(roleRes)
rspObj.RoleRes = roleRes.ToProto().(proto.RoleRes)
rsp.Body.Code = constant.OK
}else{
rsp.Body.Code = constant.DBError
return
}
//玩家的一些属性
if _, ok := mgr.RAttrMgr.TryCreate(role.RId); ok == false{
rsp.Body.Code = constant.DBError
return
}
//查询是否有城市
_, ok = mgr.RCMgr.GetByRId(role.RId)
if ok == false{
citys := make([]*model.MapRoleCity, 0)
//随机生成一个城市
for true {
x := rand.Intn(global.MapWith)
y := rand.Intn(global.MapHeight)
if mgr.NMMgr.IsCanBuildCity(x, y){
//建立城市
c := &model.MapRoleCity{RId: role.RId, X: x, Y: y,
IsMain: 1,
CurDurable: static_conf.Basic.City.Durable,
Name: role.NickName,
CreatedAt: time.Now(),
}
//插入
_, err := db.MasterDB.Table(c).Insert(c)
if err != nil{
rsp.Body.Code = constant.DBError
}else{
citys = append(citys, c)
//更新城市缓存
mgr.RCMgr.Add(c)
}
//生成城市里面的设施
mgr.RFMgr.GetAndTryCreate(c.CityId, c.RId)
break
}
}
}
rspObj.Token = util.NewSession(role.RId, time.Now()).String()
}else{
rsp.Body.Code = constant.RoleNotExist
}
}
func (this*Role) myCity(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.MyCityReq{}
rspObj := &proto.MyCityRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role, _ := r.(*model.Role)
citys,ok := mgr.RCMgr.GetByRId(role.RId)
if ok {
rspObj.Citys = make([]proto.MapRoleCity, len(citys))
//赋值发送
for i, v := range citys {
rspObj.Citys[i] = v.ToProto().(proto.MapRoleCity)
}
}else{
rspObj.Citys = make([]proto.MapRoleCity, 0)
}
}
func (this*Role) myRoleRes(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.MyRoleResReq{}
rspObj := &proto.MyRoleResRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
roleRes, ok := mgr.RResMgr.Get(role.RId)
if ok == false{
rsp.Body.Code = constant.RoleNotExist
return
}else{
rspObj.RoleRes = roleRes.ToProto().(proto.RoleRes)
rsp.Body.Code = constant.OK
}
}
func (this*Role) myProperty(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.MyRolePropertyReq{}
rspObj := &proto.MyRolePropertyRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
//城市
c, ok := mgr.RCMgr.GetByRId(role.RId)
if ok {
rspObj.Citys = make([]proto.MapRoleCity, len(c))
for i, v := range c {
rspObj.Citys[i] = v.ToProto().(proto.MapRoleCity)
}
}else{
rspObj.Citys = make([]proto.MapRoleCity, 0)
}
//建筑
ra, ok := mgr.RBMgr.GetRoleBuild(role.RId)
if ok {
rspObj.MRBuilds = make([]proto.MapRoleBuild, len(ra))
for i, v := range ra {
rspObj.MRBuilds[i] = v.ToProto().(proto.MapRoleBuild)
}
}else{
rspObj.MRBuilds = make([]proto.MapRoleBuild, 0)
}
//资源
roleRes, ok := mgr.RResMgr.Get(role.RId)
if ok {
rspObj.RoleRes = roleRes.ToProto().(proto.RoleRes)
}else{
rsp.Body.Code = constant.RoleNotExist
return
}
//武将
gs, ok := mgr.GMgr.GetOrCreateByRId(role.RId)
if ok {
rspObj.Generals = make([]proto.General, 0)
for _, v := range gs {
rspObj.Generals = append(rspObj.Generals, v.ToProto().(proto.General))
}
}else{
rsp.Body.Code = constant.DBError
return
}
//军队
ar, ok := mgr.AMgr.GetByRId(role.RId)
if ok {
rspObj.Armys = make([]proto.Army, len(ar))
for i, v := range ar {
rspObj.Armys[i] = v.ToProto().(proto.Army)
}
}else{
rspObj.Armys = make([]proto.Army, 0)
}
}
func (this*Role) myRoleBuild(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.MyRoleBuildReq{}
rspObj := &proto.MyRoleBuildRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
ra, ok := mgr.RBMgr.GetRoleBuild(role.RId)
if ok {
rspObj.MRBuilds = make([]proto.MapRoleBuild, len(ra))
for i, v := range ra {
rspObj.MRBuilds[i] = v.ToProto().(proto.MapRoleBuild)
}
}else{
rspObj.MRBuilds = make([]proto.MapRoleBuild, 0)
}
}
func (this*Role) upPosition(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.UpPositionReq{}
rspObj := &proto.UpPositionRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
rspObj.X = reqObj.X
rspObj.Y = reqObj.Y
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
pos.RPMgr.Push(reqObj.X, reqObj.Y, role.RId)
}
func (this*Role) posTagList(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.PosTagListReq{}
rspObj := &proto.PosTagListRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
attr, ok := mgr.RAttrMgr.Get(role.RId)
if ok == false {
rsp.Body.Code = constant.RoleNotExist
return
}
rspObj.PosTags = attr.PosTagArray
}
func (this*Role) opPosTag(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.PosTagReq{}
rspObj := &proto.PosTagRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
rspObj.X = reqObj.X
rspObj.Y = reqObj.Y
rspObj.Type = reqObj.Type
rspObj.Name = reqObj.Name
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
attr, ok := mgr.RAttrMgr.Get(role.RId)
if ok == false {
rsp.Body.Code = constant.RoleNotExist
return
}
if reqObj.Type == 0{
attr.RemovePosTag(reqObj.X, reqObj.Y)
attr.SyncExecute()
}else if reqObj.Type == 1{
limit := static_conf.Basic.Role.PosTagLimit
if int(limit) >= len(attr.PosTagArray){
attr.AddPosTag(reqObj.X, reqObj.Y, reqObj.Name)
attr.SyncExecute()
}else{
rsp.Body.Code = constant.OutPosTagLimit
}
}else{
rsp.Body.Code = constant.InvalidParam
}
}

View File

@@ -0,0 +1,42 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"slgserver/constant"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/proto"
)
var DefaultSkill = Skill{
}
type Skill struct {
}
func (this*Skill) InitRouter(r *net.Router) {
g := r.Group("skill").Use(middleware.ElapsedTime(), middleware.Log(),
middleware.CheckLogin(), middleware.CheckRole())
g.AddRouter("list", this.list)
}
func (this*Skill) list(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.SkillListReq{}
rspObj := &proto.SkillListRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
rspObj.List = make([]proto.Skill, 0)
skills, _ := mgr.SkillMgr.Get(role.RId)
for _, skill := range skills {
rspObj.List = append(rspObj.List, skill.ToProto().(proto.Skill))
}
}

View File

@@ -0,0 +1,103 @@
package controller
import (
"github.com/mitchellh/mapstructure"
"log/slog"
"slgserver/constant"
"slgserver/db"
"slgserver/middleware"
"slgserver/net"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/proto"
)
var DefaultWar = War{}
type War struct {
}
func (this*War) InitRouter(r *net.Router) {
g := r.Group("war").Use(middleware.ElapsedTime(),
middleware.Log(), middleware.CheckRole())
g.AddRouter("report", this.report)
g.AddRouter("read", this.read)
}
func (this*War) report(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.WarReportReq{}
rspObj := &proto.WarReportRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
//查询最近30条战报吧
l := make([]*model.WarReport, 0)
err := db.MasterDB.Table(model.WarReport{}).Where("a_rid=? or d_rid=?",
role.RId, role.RId).Desc("ctime").Limit(100, 0).Find(&l)
if err != nil{
slog.Warn("db error", "error", err)
rsp.Body.Code = constant.DBError
return
}
rspObj.List = make([]proto.WarReport, len(l))
for i, v := range l {
rspObj.List[i] = v.ToProto().(proto.WarReport)
}
}
func (this*War) read(req *net.WsMsgReq, rsp *net.WsMsgRsp) {
reqObj := &proto.WarReadReq{}
rspObj := &proto.WarReadRsp{}
mapstructure.Decode(req.Body.Msg, reqObj)
rsp.Body.Msg = rspObj
rsp.Body.Code = constant.OK
rspObj.Id = reqObj.Id
r, _ := req.Conn.GetProperty("role")
role := r.(*model.Role)
if reqObj.Id == 0 {
m := model.WarReport{AttackIsRead: true, DefenseIsRead: true}
_, err := db.MasterDB.Table(model.WarReport{}).Where("a_rid=?", role.RId).Cols("a_is_read").Update(m)
if err != nil {
slog.Error("db error", "error", err)
}
_, err = db.MasterDB.Table(model.WarReport{}).Where("d_rid=?", role.RId).Cols("d_is_read").Update(m)
if err != nil {
slog.Error("db error", "error", err)
}
}else{
wr := &model.WarReport{}
ok, err := db.MasterDB.Table(model.WarReport{}).Where("id=?",
reqObj.Id).Get(wr)
if err != nil {
slog.Warn("db error", "error", err)
rsp.Body.Code = constant.DBError
return
}
if ok {
if wr.AttackRid == role.RId {
wr.AttackIsRead = true
db.MasterDB.Table(wr).ID(wr.Id).Cols("a_is_read").Update(wr)
rsp.Body.Code = constant.OK
}else if wr.DefenseRid == role.RId {
wr.DefenseIsRead = true
db.MasterDB.Table(wr).ID(wr.Id).Cols("d_is_read").Update(wr)
rsp.Body.Code = constant.OK
}else{
rsp.Body.Code = constant.InvalidParam
}
}
}
}

View File

@@ -0,0 +1,8 @@
package global
var MapWith = 200
var MapHeight = 200
func ToPosition(x, y int) int {
return x+ MapHeight*y
}

View File

@@ -0,0 +1,456 @@
package logic
import (
"slgserver/server/slgserver/global"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/static_conf"
"slgserver/util"
"sync"
"time"
)
type armyLogic struct {
sys *sysArmyLogic
passBy sync.RWMutex
stop sync.RWMutex
out sync.RWMutex
endTime sync.RWMutex
interruptId chan int
giveUpId chan int
arriveArmys chan *model.Army
updateArmys chan *model.Army
outArmys map[int]*model.Army //城外的军队
endTimeArmys map[int64][]*model.Army //key:到达时间
stopInPosArmys map[int]map[int]*model.Army //玩家停留位置的军队 key:posId,armyId
passByPosArmys map[int]map[int]*model.Army //玩家路过位置的军队 key:posId,armyId
}
func (this *armyLogic) init(){
armys := mgr.AMgr.All()
for _, army := range armys {
//恢复已经执行行动的军队
if army.Cmd != model.ArmyCmdIdle {
e := army.End.Unix()
_, ok := this.endTimeArmys[e]
if ok == false{
this.endTimeArmys[e] = make([]*model.Army, 0)
}
this.endTimeArmys[e] = append(this.endTimeArmys[e], army)
}
}
curTime := time.Now().Unix()
for kT, armys := range this.endTimeArmys {
if kT <= curTime {
for _, a := range armys {
if a.Cmd == model.ArmyCmdAttack {
this.Arrive(a)
}else if a.Cmd == model.ArmyCmdDefend {
this.Arrive(a)
}else if a.Cmd == model.ArmyCmdBack {
if curTime >= a.End.Unix() {
a.ToX = a.FromX
a.ToY = a.FromY
a.Cmd = model.ArmyCmdIdle
a.State = model.ArmyStop
}
}
a.SyncExecute()
}
delete(this.endTimeArmys, kT)
}else{
for _, a := range armys {
a.State = model.ArmyRunning
}
}
}
}
func (this*armyLogic) check() {
for true {
t := time.Now().Unix()
time.Sleep(100*time.Millisecond)
this.endTime.Lock()
for k, armies := range this.endTimeArmys {
if k <= t{
for _, army := range armies {
this.Arrive(army)
}
delete(this.endTimeArmys, k)
}
}
this.endTime.Unlock()
}
}
func (this *armyLogic) running(){
passbyTimer := time.NewTicker(10 * time.Second)
for {
select {
case <-passbyTimer.C:{
this.updatePassBy()
}
case army := <-this.updateArmys:{
this.exeUpdate(army)
}
case army := <-this.arriveArmys:{
this.exeArrive(army)
}
case giveId := <- this.giveUpId:{
//在该位置驻守、调动的都需要返回
this.stop.RLock()
armys, ok := this.stopInPosArmys[giveId]
this.stop.RUnlock()
if ok {
for _, army := range armys {
this.ArmyBack(army)
}
this.deleteStopArmy(giveId)
}
}
case interruptId := <- this.interruptId:{
//只有调动到该位置的军队需要返回
var targets []*model.Army
this.stop.Lock()
armys, ok := this.stopInPosArmys[interruptId]
if ok {
for key, army := range armys {
if army.FromX == army.ToX && army.FromY == army.ToY{
targets = append(targets, army)
delete(armys, key)
}
}
}
this.stop.Unlock()
for _, target := range targets {
this.ArmyBack(target)
}
}
}
}
}
func (this* armyLogic) updatePassBy() {
temp := make(map[int]map[int]*model.Army)
this.out.RLock()
for _, army := range this.outArmys {
if army.State == model.ArmyRunning {
x, y := army.Position()
posId := global.ToPosition(x, y)
if _, ok := temp[posId]; ok == false {
temp[posId] = make(map[int]*model.Army)
}
temp[posId][army.Id] = army
army.CheckSyncCell()
}
}
this.out.RUnlock()
this.stop.RLock()
for posId, armys := range this.stopInPosArmys {
for _, army := range armys {
if _, ok := temp[posId]; ok == false {
temp[posId] = make(map[int]*model.Army)
}
temp[posId][army.Id] = army
}
}
this.stop.RUnlock()
this.passBy.Lock()
this.passByPosArmys = temp
this.passBy.Unlock()
}
func (this *armyLogic) exeUpdate(army *model.Army) {
army.SyncExecute()
if army.Cmd == model.ArmyCmdBack {
this.stop.Lock()
posId := global.ToPosition(army.ToX, army.ToY)
armys, ok := this.stopInPosArmys[posId]
if ok {
delete(armys, army.Id)
this.stopInPosArmys[posId] = armys
}
this.stop.Unlock()
}
this.out.Lock()
if army.Cmd != model.ArmyCmdIdle {
this.outArmys[army.Id] = army
}else{
delete(this.outArmys, army.RId)
}
this.out.Unlock()
}
func (this *armyLogic) exeArrive(army *model.Army) {
if army.Cmd == model.ArmyCmdAttack {
if IsCanArrive(army.ToX, army.ToY, army.RId) &&
IsWarFree(army.ToX, army.ToY) == false &&
IsCanDefend(army.ToX, army.ToY, army.RId) == false{
newBattle(army)
} else{
war := NewEmptyWar(army)
war.SyncExecute()
}
this.ArmyBack(army)
}else if army.Cmd == model.ArmyCmdDefend {
//呆在哪里不动
ok := IsCanDefend(army.ToX, army.ToY, army.RId)
if ok {
//目前是自己的领地才能驻守
army.State = model.ArmyStop
this.addStopArmy(army)
this.Update(army)
}else{
war := NewEmptyWar(army)
war.SyncExecute()
this.ArmyBack(army)
}
}else if army.Cmd == model.ArmyCmdReclamation {
if army.State == model.ArmyRunning {
ok := mgr.RBMgr.BuildIsRId(army.ToX, army.ToY, army.RId)
if ok {
//目前是自己的领地才能屯田
this.addStopArmy(army)
this.Reclamation(army)
}else{
war := NewEmptyWar(army)
war.SyncExecute()
this.ArmyBack(army)
}
}else {
this.ArmyBack(army)
//增加场量
rr, ok := mgr.RResMgr.Get(army.RId)
if ok {
b, ok1 := mgr.RBMgr.PositionBuild(army.ToX, army.ToY)
if ok1 {
rr.Stone += b.Stone
rr.Iron += b.Iron
rr.Wood += b.Wood
rr.Gold += rr.Gold
rr.Grain += rr.Grain
rr.SyncExecute()
}
}
}
}else if army.Cmd == model.ArmyCmdBack {
army.State = model.ArmyStop
army.Cmd = model.ArmyCmdIdle
army.ToX = army.FromX
army.ToY = army.FromY
this.Update(army)
}else if army.Cmd == model.ArmyCmdTransfer {
//调动到位置了
if army.State == model.ArmyRunning{
ok := mgr.RBMgr.BuildIsRId(army.ToX, army.ToY, army.RId)
if ok == false{
this.ArmyBack(army)
}else{
b, _ := mgr.RBMgr.PositionBuild(army.ToX, army.ToY)
if b.IsHasTransferAuth(){
army.State = model.ArmyStop
army.Cmd = model.ArmyCmdIdle
x := army.ToX
y := army.ToY
army.FromX = x
army.FromY = y
army.ToX = x
army.ToY = y
this.addStopArmy(army)
this.Update(army)
}else{
this.ArmyBack(army)
}
}
}
}
}
func (this *armyLogic) ScanBlock(rid, x, y, length int) []*model.Army {
if x < 0 || x >= global.MapWith || y < 0 || y >= global.MapHeight {
return nil
}
maxX := util.MinInt(global.MapWith, x+length-1)
maxY := util.MinInt(global.MapHeight, y+length-1)
out := make([]*model.Army, 0)
this.passBy.RLock()
for i := x; i <= maxX; i++ {
for j := y; j <= maxY; j++ {
posId := global.ToPosition(i, j)
armys, ok := this.passByPosArmys[posId]
if ok {
is := armyIsInView(rid, i, j)
if is == false{
continue
}
for _, army := range armys {
out = append(out, army)
}
}
}
}
this.passBy.RUnlock()
return out
}
func (this *armyLogic) Arrive(army *model.Army) {
this.arriveArmys <- army
}
func (this *armyLogic) Update(army *model.Army) {
this.updateArmys <- army
}
func (this *armyLogic) Interrupt(posId int) {
this.interruptId <- posId
}
func (this *armyLogic) GiveUp(posId int) {
this.giveUpId <- posId
}
func (this* armyLogic) GetStopArmys(posId int)[]*model.Army {
ret := make([]*model.Army, 0)
this.stop.RLock()
armys, ok := this.stopInPosArmys[posId]
if ok {
for _, army := range armys {
ret = append(ret, army)
}
}
this.stop.RUnlock()
return ret
}
func (this *armyLogic) deleteStopArmy(posId int) {
this.stop.Lock()
delete(this.stopInPosArmys, posId)
this.stop.Unlock()
}
func (this*armyLogic) addStopArmy(army *model.Army) {
posId := global.ToPosition(army.ToX, army.ToY)
this.stop.Lock()
if _, ok := this.stopInPosArmys[posId]; ok == false {
this.stopInPosArmys[posId] = make(map[int]*model.Army)
}
this.stopInPosArmys[posId][army.Id] = army
this.stop.Unlock()
}
func (this*armyLogic) addAction(t int64, army *model.Army) {
this.endTime.Lock()
defer this.endTime.Unlock()
_, ok := this.endTimeArmys[t]
if ok == false {
this.endTimeArmys[t] = make([]*model.Army, 0)
}
this.endTimeArmys[t] = append(this.endTimeArmys[t], army)
}
//把行动丢进来
func (this*armyLogic) PushAction(army *model.Army) {
if army.Cmd == model.ArmyCmdAttack ||
army.Cmd == model.ArmyCmdDefend ||
army.Cmd == model.ArmyCmdTransfer{
t := army.End.Unix()
this.addAction(t, army)
}else if army.Cmd == model.ArmyCmdReclamation {
if army.State == model.ArmyRunning {
t := army.End.Unix()
this.addAction(t, army)
}else{
costTime := static_conf.Basic.General.ReclamationTime
t := army.End.Unix()+int64(costTime)
this.addAction(t, army)
}
}else if army.Cmd == model.ArmyCmdBack {
if army.FromX == army.ToX && army.FromY == army.ToY {
//处理调动到其他地方待命的情况,会归属的城池
city, ok := mgr.RCMgr.Get(army.CityId)
if ok {
army.FromX = city.X
army.FromY = city.Y
//计算回去的时间
//speed := mgr.AMgr.GetSpeed(army)
//t := mgr.TravelTime(speed, army.FromX, army.FromY, army.ToX, army.ToY)
army.Start = time.Now()
//army.End = time.Now().Add(time.Duration(t) * time.Millisecond)
army.End = time.Now().Add(40*time.Second)
}
}else{
cur := time.Now()
diff := army.End.Unix()-army.Start.Unix()
if cur.Unix() < army.End.Unix(){
diff = cur.Unix()-army.Start.Unix()
}
army.Start = cur
army.End = cur.Add(time.Duration(diff) * time.Second)
}
army.Cmd = model.ArmyCmdBack
this.addAction(army.End.Unix(), army)
}
this.Update(army)
}
func (this*armyLogic) ArmyBack(army *model.Army) {
army.ClearConscript()
army.State = model.ArmyRunning
army.Cmd = model.ArmyCmdBack
this.endTime.Lock()
t := army.End.Unix()
if actions, ok := this.endTimeArmys[t]; ok {
for i, v := range actions {
if v.Id == army.Id{
actions = append(actions[:i], actions[i+1:]...)
this.endTimeArmys[t] = actions
break
}
}
}
this.endTime.Unlock()
this.PushAction(army)
}
func (this*armyLogic) Reclamation(army *model.Army) {
army.State = model.ArmyStop
army.Cmd = model.ArmyCmdReclamation
this.PushAction(army)
}

View File

@@ -0,0 +1,575 @@
package logic
import (
"encoding/json"
"log/slog"
"math/rand"
"slgserver/server/slgserver/global"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf"
"slgserver/server/slgserver/static_conf/facility"
"slgserver/server/slgserver/static_conf/general"
"slgserver/util"
"time"
)
// 战斗位置的属性
type armyPosition struct {
general *model.General
soldiers int //兵力
force int //武力
strategy int //策略
defense int //防御
speed int //速度
destroy int //破坏
arms int //兵种
position int //位置
}
const maxRound = 10
type armyWar struct {
attack *model.Army
defense *model.Army
attackPos []*armyPosition
defensePos []*armyPosition
}
type battle struct {
AId int `json:"a_id"` //本回合发起攻击的武将id
DId int `json:"d_id"` //本回合防御方的武将id
ALoss int `json:"a_loss"` //本回合攻击方损失的兵力
DLoss int `json:"d_loss"` //本回合防守方损失的兵力
}
func (this *battle) to() []int {
r := make([]int, 0)
r = append(r, this.AId)
r = append(r, this.DId)
r = append(r, this.ALoss)
r = append(r, this.DLoss)
return r
}
type warRound struct {
Battle [][]int `json:"b"`
}
type WarResult struct {
round []*warRound
result int //0失败1平2胜利
}
func NewWar(attack *model.Army, defense *model.Army) *WarResult {
w := armyWar{attack: attack, defense: defense}
w.init()
wars := w.battle()
result := &WarResult{round: wars}
if w.attackPos[0].soldiers == 0 {
result.result = 0
} else if w.defensePos[0] != nil && w.defensePos[0].soldiers != 0 {
result.result = 1
} else {
result.result = 2
}
return result
}
// 初始化军队和武将属性、兵种、加成等
func (this *armyWar) init() {
//城内设施加成
attackAdds := []int{0, 0, 0, 0}
if this.attack.CityId > 0 {
attackAdds = mgr.RFMgr.GetAdditions(this.attack.CityId,
facility.TypeForce,
facility.TypeDefense,
facility.TypeSpeed,
facility.TypeStrategy)
}
defenseAdds := []int{0, 0, 0, 0}
if this.defense.CityId > 0 {
defenseAdds = mgr.RFMgr.GetAdditions(this.defense.CityId,
facility.TypeForce,
facility.TypeDefense,
facility.TypeSpeed,
facility.TypeStrategy)
}
//阵营加成
aCampAdds := []int{0}
aCamp := this.attack.GetCamp()
if aCamp > 0 {
aCampAdds = mgr.RFMgr.GetAdditions(this.attack.CityId, facility.TypeHanAddition-1+aCamp)
}
dCampAdds := []int{0}
dCamp := this.attack.GetCamp()
if dCamp > 0 {
dCampAdds = mgr.RFMgr.GetAdditions(this.defense.CityId, facility.TypeHanAddition-1+aCamp)
}
this.attackPos = make([]*armyPosition, 0)
this.defensePos = make([]*armyPosition, 0)
for i, g := range this.attack.Gens {
if g == nil {
this.attackPos = append(this.attackPos, nil)
} else {
pos := &armyPosition{
general: g,
soldiers: this.attack.SoldierArray[i],
force: g.GetForce() + attackAdds[0] + aCampAdds[0],
defense: g.GetDefense() + attackAdds[1] + aCampAdds[0],
speed: g.GetSpeed() + attackAdds[2] + aCampAdds[0],
strategy: g.GetStrategy() + attackAdds[3] + aCampAdds[0],
destroy: g.GetDestroy() + aCampAdds[0],
arms: g.CurArms,
position: i,
}
this.attackPos = append(this.attackPos, pos)
}
}
for i, g := range this.defense.Gens {
if g == nil {
this.defensePos = append(this.defensePos, nil)
} else {
pos := &armyPosition{
general: g,
soldiers: this.defense.SoldierArray[i],
force: g.GetForce() + defenseAdds[0] + dCampAdds[0],
defense: g.GetDefense() + defenseAdds[1] + dCampAdds[0],
speed: g.GetSpeed() + defenseAdds[2] + dCampAdds[0],
strategy: g.GetStrategy() + defenseAdds[3] + dCampAdds[0],
destroy: g.GetDestroy() + dCampAdds[0],
arms: g.CurArms,
position: i,
}
this.defensePos = append(this.defensePos, pos)
}
}
slog.Debug("army defense positions initialized", "positions", this.defensePos)
}
func (this *armyWar) battle() []*warRound {
rounds := make([]*warRound, 0)
cur := 0
for true {
r, isEnd := this.round()
rounds = append(rounds, r)
cur += 1
if cur >= maxRound || isEnd {
break
}
}
for i := 0; i < 3; i++ {
if this.attackPos[i] != nil {
this.attack.SoldierArray[i] = this.attackPos[i].soldiers
}
if this.defensePos[i] != nil {
this.defense.SoldierArray[i] = this.defensePos[i].soldiers
}
}
return rounds
}
// 回合
func (this *armyWar) round() (*warRound, bool) {
war := &warRound{}
n := rand.Intn(10)
attack := this.attackPos
defense := this.defensePos
isEnd := false
//随机先手
if n%2 == 0 {
attack = this.defensePos
defense = this.attackPos
}
for _, att := range attack {
////////攻击方begin//////////
if att == nil || att.soldiers == 0 {
continue
}
def, _ := this.randArmyPosition(defense)
if def == nil {
isEnd = true
goto end
}
attHarmRatio := general.GenArms.GetHarmRatio(att.arms, def.arms)
attHarm := float64(util.AbsInt(att.force-def.defense)*att.soldiers) * attHarmRatio * 0.0005
attKill := int(attHarm)
attKill = util.MinInt(attKill, def.soldiers)
def.soldiers -= attKill
att.general.Exp += attKill * 5
//大营干死了,直接结束
if def.position == 0 && def.soldiers == 0 {
isEnd = true
goto end
}
////////攻击方end//////////
////////防守方begin//////////
if def.soldiers == 0 || att.soldiers == 0 {
continue
}
defHarmRatio := general.GenArms.GetHarmRatio(def.arms, att.arms)
defHarm := float64(util.AbsInt(def.force-att.defense)*def.soldiers) * defHarmRatio * 0.0005
defKill := int(defHarm)
defKill = util.MinInt(defKill, att.soldiers)
att.soldiers -= defKill
def.general.Exp += defKill * 5
b := battle{AId: att.general.Id, ALoss: defKill, DId: def.general.Id, DLoss: attKill}
war.Battle = append(war.Battle, b.to())
//大营干死了,直接结束
if att.position == 0 && att.soldiers == 0 {
isEnd = true
goto end
}
////////防守方end//////////
}
end:
return war, isEnd
}
// 随机一个目标队伍
func (this *armyWar) randArmyPosition(pos []*armyPosition) (*armyPosition, int) {
isEmpty := true
for _, v := range pos {
if v != nil && v.soldiers != 0 {
isEmpty = false
break
}
}
if isEmpty {
return nil, -1
}
for true {
r := rand.Intn(100)
index := r % len(pos)
if pos[index] != nil && pos[index].soldiers != 0 {
return pos[index], index
}
}
return nil, -1
}
func NewEmptyWar(attack *model.Army) *model.WarReport {
//战报处理
pArmy := attack.ToProto().(proto.Army)
begArmy, _ := json.Marshal(pArmy)
//武将战斗前
begGeneral := make([][]int, 0)
for _, g := range attack.Gens {
if g != nil {
pg := g.ToProto().(proto.General)
begGeneral = append(begGeneral, pg.ToArray())
}
}
begGeneralData, _ := json.Marshal(begGeneral)
wr := &model.WarReport{X: attack.ToX, Y: attack.ToY, AttackRid: attack.RId,
AttackIsRead: false, DefenseIsRead: true, DefenseRid: 0,
BegAttackArmy: string(begArmy), BegDefenseArmy: "",
EndAttackArmy: string(begArmy), EndDefenseArmy: "",
BegAttackGeneral: string(begGeneralData),
EndAttackGeneral: string(begGeneralData),
BegDefenseGeneral: "",
EndDefenseGeneral: "",
Rounds: "",
Result: 0,
CTime: time.Now(),
}
return wr
}
func checkCityOccupy(wr *model.WarReport, attackArmy *model.Army, city *model.MapRoleCity) {
destory := mgr.GMgr.GetDestroy(attackArmy)
wr.DestroyDurable = util.MinInt(destory, city.CurDurable)
city.DurableChange(-destory)
if city.CurDurable == 0 {
aAttr, _ := mgr.RAttrMgr.Get(attackArmy.RId)
if aAttr.UnionId != 0 {
//有联盟才能俘虏玩家
wr.Occupy = 1
dAttr, _ := mgr.RAttrMgr.Get(city.RId)
dAttr.ParentId = aAttr.UnionId
Union.PutChild(aAttr.UnionId, city.RId)
dAttr.SyncExecute()
city.OccupyTime = time.Now()
} else {
wr.Occupy = 0
}
} else {
wr.Occupy = 0
}
city.SyncExecute()
}
// 简单战斗
func newBattle(attackArmy *model.Army) {
city, ok := mgr.RCMgr.PositionCity(attackArmy.ToX, attackArmy.ToY)
if ok {
//驻守队伍被打
posId := global.ToPosition(attackArmy.ToX, attackArmy.ToY)
enemys := ArmyLogic.GetStopArmys(posId)
//城内空闲的队伍被打
if armys, ok := mgr.AMgr.GetByCity(city.CityId); ok {
for _, enemy := range armys {
if enemy.IsCanOutWar() {
enemys = append(enemys, enemy)
}
}
}
if len(enemys) == 0 {
//没有队伍
destory := mgr.GMgr.GetDestroy(attackArmy)
city.DurableChange(-destory)
city.SyncExecute()
wr := NewEmptyWar(attackArmy)
wr.Result = 2
wr.DefenseRid = city.RId
wr.DefenseIsRead = false
checkCityOccupy(wr, attackArmy, city)
wr.SyncExecute()
} else {
lastWar, warReports := trigger(attackArmy, enemys, true)
if lastWar.result > 1 {
wr := warReports[len(warReports)-1]
checkCityOccupy(wr, attackArmy, city)
}
for _, wr := range warReports {
wr.SyncExecute()
}
}
} else {
//打建筑
executeBuild(attackArmy)
}
}
func trigger(army *model.Army, enemys []*model.Army, isRoleEnemy bool) (*WarResult, []*model.WarReport) {
posId := global.ToPosition(army.ToX, army.ToY)
warReports := make([]*model.WarReport, 0)
var lastWar *WarResult = nil
for _, enemy := range enemys {
//战报处理
pArmy := army.ToProto().(proto.Army)
pEnemy := enemy.ToProto().(proto.Army)
begArmy1, _ := json.Marshal(pArmy)
begArmy2, _ := json.Marshal(pEnemy)
//武将战斗前
begGeneral1 := make([][]int, 0)
for _, g := range army.Gens {
if g != nil {
pg := g.ToProto().(proto.General)
begGeneral1 = append(begGeneral1, pg.ToArray())
}
}
begGeneralData1, _ := json.Marshal(begGeneral1)
begGeneral2 := make([][]int, 0)
for _, g := range enemy.Gens {
if g != nil {
pg := g.ToProto().(proto.General)
begGeneral2 = append(begGeneral2, pg.ToArray())
}
}
begGeneralData2, _ := json.Marshal(begGeneral2)
lastWar = NewWar(army, enemy)
//武将战斗后
endGeneral1 := make([][]int, 0)
for _, g := range army.Gens {
if g != nil {
pg := g.ToProto().(proto.General)
endGeneral1 = append(endGeneral1, pg.ToArray())
level, exp := general.GenBasic.ExpToLevel(g.Exp)
g.Level = level
g.Exp = exp
g.SyncExecute()
}
}
endGeneralData1, _ := json.Marshal(endGeneral1)
endGeneral2 := make([][]int, 0)
for _, g := range enemy.Gens {
if g != nil {
pg := g.ToProto().(proto.General)
endGeneral2 = append(endGeneral2, pg.ToArray())
level, exp := general.GenBasic.ExpToLevel(g.Exp)
g.Level = level
g.Exp = exp
g.SyncExecute()
}
}
endGeneralData2, _ := json.Marshal(endGeneral2)
pArmy = army.ToProto().(proto.Army)
pEnemy = enemy.ToProto().(proto.Army)
endArmy1, _ := json.Marshal(pArmy)
endArmy2, _ := json.Marshal(pEnemy)
rounds, _ := json.Marshal(lastWar.round)
wr := &model.WarReport{X: army.ToX, Y: army.ToY, AttackRid: army.RId,
AttackIsRead: false, DefenseIsRead: false, DefenseRid: enemy.RId,
BegAttackArmy: string(begArmy1), BegDefenseArmy: string(begArmy2),
EndAttackArmy: string(endArmy1), EndDefenseArmy: string(endArmy2),
BegAttackGeneral: string(begGeneralData1),
BegDefenseGeneral: string(begGeneralData2),
EndAttackGeneral: string(endGeneralData1),
EndDefenseGeneral: string(endGeneralData2),
Rounds: string(rounds),
Result: lastWar.result,
CTime: time.Now(),
}
warReports = append(warReports, wr)
enemy.ToSoldier()
enemy.ToGeneral()
if isRoleEnemy {
if lastWar.result > 1 {
if isRoleEnemy {
ArmyLogic.deleteStopArmy(posId)
}
ArmyLogic.ArmyBack(enemy)
}
enemy.SyncExecute()
} else {
wr.DefenseIsRead = true
}
}
army.SyncExecute()
return lastWar, warReports
}
func executeBuild(army *model.Army) {
roleBuild, _ := mgr.RBMgr.PositionBuild(army.ToX, army.ToY)
posId := global.ToPosition(army.ToX, army.ToY)
posArmys := ArmyLogic.GetStopArmys(posId)
isRoleEnemy := len(posArmys) != 0
var enemys []*model.Army
if isRoleEnemy == false {
enemys = ArmyLogic.sys.GetArmy(army.ToX, army.ToY)
} else {
for _, v := range posArmys {
enemys = append(enemys, v)
}
}
lastWar, warReports := trigger(army, enemys, isRoleEnemy)
if lastWar.result > 1 {
if roleBuild != nil {
destory := mgr.GMgr.GetDestroy(army)
wr := warReports[len(warReports)-1]
wr.DestroyDurable = util.MinInt(destory, roleBuild.CurDurable)
roleBuild.CurDurable = util.MaxInt(0, roleBuild.CurDurable-destory)
if roleBuild.CurDurable == 0 {
//攻占了玩家的领地
bLimit := static_conf.Basic.Role.BuildLimit
if bLimit > mgr.RBMgr.BuildCnt(army.RId) {
wr.Occupy = 1
mgr.RBMgr.RemoveFromRole(roleBuild)
mgr.RBMgr.AddBuild(army.RId, army.ToX, army.ToY)
OccupyRoleBuild(army.RId, army.ToX, army.ToY)
} else {
wr.Occupy = 0
}
} else {
wr.Occupy = 0
}
} else {
//占领系统领地
wr := warReports[len(warReports)-1]
blimit := static_conf.Basic.Role.BuildLimit
if blimit > mgr.RBMgr.BuildCnt(army.RId) {
OccupySystemBuild(army.RId, army.ToX, army.ToY)
wr.DestroyDurable = 10000
wr.Occupy = 1
} else {
wr.Occupy = 0
}
ArmyLogic.sys.DelArmy(army.ToX, army.ToY)
}
}
//领地发生变化
if newRoleBuild, ok := mgr.RBMgr.PositionBuild(army.ToX, army.ToY); ok {
newRoleBuild.SyncExecute()
}
for _, wr := range warReports {
wr.SyncExecute()
}
}
func OccupyRoleBuild(rid, x, y int) {
newId := rid
if b, ok := mgr.RBMgr.PositionBuild(x, y); ok {
b.CurDurable = b.MaxDurable
b.OccupyTime = time.Now()
oldId := b.RId
slog.Info("battle in role build",
"oldRId", oldId,
"newRId", newId)
b.RId = rid
}
}
func OccupySystemBuild(rid, x, y int) {
if _, ok := mgr.RBMgr.PositionBuild(x, y); ok {
return
}
if mgr.NMMgr.IsCanBuild(x, y) {
rb, ok := mgr.RBMgr.AddBuild(rid, x, y)
if ok {
rb.OccupyTime = time.Now()
}
}
}

View File

@@ -0,0 +1,99 @@
package logic
import (
"slgserver/server/slgserver/logic/mgr"
"slgserver/util"
)
//是否能到达
func IsCanArrive(x, y, rid int) bool {
var radius = 0
unionId := getUnionId(rid)
b, ok := mgr.RBMgr.PositionBuild(x, y)
if ok {
radius = b.CellRadius()
}
c, ok := mgr.RCMgr.PositionCity(x, y)
if ok {
radius = c.CellRadius()
}
//查找10格半径
for tx := x-10; tx <= x+10; tx++ {
for ty := y-10; ty <= y+10; ty++ {
b1, ok := mgr.RBMgr.PositionBuild(tx, ty)
if ok {
absX := util.AbsInt(x-tx)
absY := util.AbsInt(y-ty)
if absX <= radius+b1.CellRadius()+1 && absY <= radius+b1.CellRadius()+1{
unionId1 := getUnionId(b1.RId)
parentId := getParentId(b1.RId)
if b1.RId == rid || (unionId != 0 && (unionId == unionId1 || unionId == parentId)){
return true
}
}
}
c1, ok := mgr.RCMgr.PositionCity(tx, ty)
if ok {
absX := util.AbsInt(x-tx)
absY := util.AbsInt(y-ty)
if absX <= radius+c1.CellRadius()+1 && absY <= radius+c1.CellRadius()+1{
unionId1 := getUnionId(c1.RId)
parentId := getParentId(c1.RId)
if c1.RId == rid || (unionId != 0 && (unionId == unionId1 || unionId == parentId)){
return true
}
}
}
}
}
return false
}
func IsCanDefend(x, y, rid int) bool{
unionId := getUnionId(rid)
b, ok := mgr.RBMgr.PositionBuild(x, y)
if ok {
tUnionId := getUnionId(b.RId)
tParentId := getParentId(b.RId)
if b.RId == rid{
return true
}else if tUnionId > 0 {
return tUnionId == unionId
}else if tParentId > 0 {
return tParentId == unionId
}
}
c, ok := mgr.RCMgr.PositionCity(x, y)
if ok {
tUnionId := getUnionId(c.RId)
tParentId := getParentId(c.RId)
if c.RId == rid{
return true
}else if tUnionId > 0 {
return tUnionId == unionId
}else if tParentId > 0 {
return tParentId == unionId
}
}
return false
}
//是否是免战
func IsWarFree(x, y int) bool{
b, ok := mgr.RBMgr.PositionBuild(x, y)
if ok {
return b.IsWarFree()
}
c, ok := mgr.RCMgr.PositionCity(x, y)
if ok && getParentId(c.RId) > 0 {
return c.IsWarFree()
}
return false
}

View File

@@ -0,0 +1,169 @@
package logic
import (
"log/slog"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"sync"
)
func getUnionId(rid int) int {
attr, ok := mgr.RAttrMgr.Get(rid)
if ok {
return attr.UnionId
}else{
return 0
}
}
func getUnionName(unionId int) string {
if unionId <= 0{
return ""
}
u, ok := mgr.UnionMgr.Get(unionId)
if ok {
return u.Name
}else{
return ""
}
}
func getParentId(rid int) int {
attr, ok := mgr.RAttrMgr.Get(rid)
if ok {
return attr.ParentId
}else{
return 0
}
}
func getMainMembers(unionId int) []int {
u, ok := mgr.UnionMgr.Get(unionId)
r := make([]int, 0)
if ok {
if u.Chairman != 0{
r = append(r, u.Chairman)
}
if u.ViceChairman != 0{
r = append(r, u.ViceChairman)
}
}
return r
}
type coalitionLogic struct {
mutex sync.RWMutex
children map[int]map[int]int //key:unionId,key&value:child rid
}
func NewCoalitionLogic() *coalitionLogic {
c := &coalitionLogic{
children: make(map[int]map[int]int),
}
c.init()
return c
}
func (this*coalitionLogic) init() {
//初始化下属玩家
attrs := mgr.RAttrMgr.List()
for _, attr := range attrs {
if attr.ParentId !=0 {
this.PutChild(attr.ParentId, attr.RId)
}
}
}
func (this*coalitionLogic) MemberEnter(rid, unionId int) {
attr, ok := mgr.RAttrMgr.TryCreate(rid)
if ok {
attr.UnionId = unionId
if attr.ParentId == unionId{
this.DelChild(unionId, attr.RId)
}
}else{
slog.Warn("EnterUnion not found roleAttribute", "rid", rid)
}
if rcs, ok := mgr.RCMgr.GetByRId(rid); ok {
for _, rc := range rcs {
rc.SyncExecute()
}
}
}
func (this*coalitionLogic) MemberExit(rid int) {
if ra, ok := mgr.RAttrMgr.Get(rid); ok {
ra.UnionId = 0
}
if rcs, ok := mgr.RCMgr.GetByRId(rid); ok {
for _, rc := range rcs {
rc.SyncExecute()
}
}
}
//解散
func (this*coalitionLogic) Dismiss(unionId int) {
u, ok := mgr.UnionMgr.Get(unionId)
if ok {
mgr.UnionMgr.Remove(unionId)
for _, rid := range u.MemberArray {
this.MemberExit(rid)
this.DelUnionAllChild(unionId)
}
u.State = model.UnionDismiss
u.MemberArray = []int{}
u.SyncExecute()
}
}
func (this*coalitionLogic) PutChild(unionId, rid int) {
this.mutex.Lock()
_, ok := this.children[unionId]
if ok == false {
this.children[unionId] = make(map[int]int)
}
this.children[unionId][rid] = rid
this.mutex.Unlock()
}
func (this*coalitionLogic) DelChild(unionId, rid int) {
this.mutex.Lock()
children, ok := this.children[unionId]
if ok {
attr, ok := mgr.RAttrMgr.Get(rid)
if ok {
attr.ParentId = 0
attr.SyncExecute()
}
delete(children, rid)
}
this.mutex.Unlock()
}
func (this*coalitionLogic) DelUnionAllChild(unionId int) {
this.mutex.Lock()
children, ok := this.children[unionId]
if ok {
for _, child := range children {
attr, ok := mgr.RAttrMgr.Get(child)
if ok {
attr.ParentId = 0
attr.SyncExecute()
}
city, ok := mgr.RCMgr.GetMainCity(child)
if ok {
city.SyncExecute()
}
}
delete(this.children, unionId)
}
this.mutex.Unlock()
}

View File

@@ -0,0 +1,65 @@
package logic
import (
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"time"
)
var Union *coalitionLogic
var ArmyLogic *armyLogic
func BeforeInit() {
//初始化一些方法
model.ArmyIsInView = armyIsInView
model.GetUnionId = getUnionId
model.GetRoleNickName = mgr.RoleNickName
model.GetParentId = getParentId
model.GetMainMembers = getMainMembers
model.GetUnionName = getUnionName
model.GetYield = mgr.GetYield
model.GetDepotCapacity = mgr.GetDepotCapacity
model.GetCityCost = mgr.GetCityCost
model.GetMaxDurable = mgr.GetMaxDurable
model.GetCityLv = mgr.GetCityLV
model.MapResTypeLevel = mgr.NMMgr.MapResTypeLevel
}
//逻辑相关的初始化放在这里
func Init() {
Union = NewCoalitionLogic()
ArmyLogic = &armyLogic{
arriveArmys: make(chan *model.Army, 100),
interruptId: make(chan int, 100),
giveUpId: make(chan int, 100),
updateArmys: make(chan *model.Army, 100),
outArmys: make(map[int]*model.Army),
endTimeArmys: make(map[int64][]*model.Army),
stopInPosArmys: make(map[int]map[int]*model.Army),
passByPosArmys: make(map[int]map[int]*model.Army),
sys: NewSysArmy()}
ArmyLogic.init()
go ArmyLogic.check()
go ArmyLogic.running()
}
func AfterInit() {
go func() {
for true {
time.Sleep(1*time.Second)
buildIds := mgr.RBMgr.CheckGiveUp()
for _, buildId := range buildIds {
ArmyLogic.GiveUp(buildId)
}
buildIds = mgr.RBMgr.CheckDestroy()
for _, buildId := range buildIds {
ArmyLogic.Interrupt(buildId)
}
}
}()
}

View File

@@ -0,0 +1,286 @@
package mgr
import (
"log/slog"
"slgserver/db"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/static_conf/facility"
"sync"
)
type armyMgr struct {
mutex sync.RWMutex
armyById map[int]*model.Army //key:armyId
armyByCityId map[int][]*model.Army //key:cityId
armyByRId map[int][]*model.Army //key:rid
}
var AMgr = &armyMgr{
armyById: make(map[int]*model.Army),
armyByCityId: make(map[int][]*model.Army),
armyByRId: make(map[int][]*model.Army),
}
func (this*armyMgr) Load() {
db.MasterDB.Table(model.Army{}).Find(this.armyById)
for _, army := range this.armyById {
//处理征兵
army.CheckConscript()
cid := army.CityId
c,ok:= this.armyByCityId[cid]
if ok {
this.armyByCityId[cid] = append(c, army)
}else{
this.armyByCityId[cid] = make([]*model.Army, 0)
this.armyByCityId[cid] = append(this.armyByCityId[cid], army)
}
//rid
if _, ok := this.armyByRId[army.RId]; ok == false{
this.armyByRId[army.RId] = make([]*model.Army, 0)
}
this.armyByRId[army.RId] = append(this.armyByRId[army.RId], army)
this.updateGenerals(army)
}
}
func (this*armyMgr) insertOne(army *model.Army) {
aid := army.Id
cid := army.CityId
this.armyById[aid] = army
if _, r:= this.armyByCityId[cid]; r == false{
this.armyByCityId[cid] = make([]*model.Army, 0)
}
this.armyByCityId[cid] = append(this.armyByCityId[cid], army)
if _, ok := this.armyByRId[army.RId]; ok == false{
this.armyByRId[army.RId] = make([]*model.Army, 0)
}
this.armyByRId[army.RId] = append(this.armyByRId[army.RId], army)
this.updateGenerals(army)
}
func (this*armyMgr) insertMutil(armys []*model.Army) {
for _, v := range armys {
this.insertOne(v)
}
}
func (this*armyMgr) Get(aid int) (*model.Army, bool){
this.mutex.RLock()
a, ok := this.armyById[aid]
this.mutex.RUnlock()
if ok {
a.CheckConscript()
return a, true
}else{
army := &model.Army{}
ok, err := db.MasterDB.Table(model.Army{}).Where("id=?", aid).Get(army)
if ok {
this.mutex.Lock()
this.insertOne(army)
this.mutex.Unlock()
return army, true
}else{
if err == nil{
slog.Warn("armyMgr GetByRId armyId db not found",
"armyId", aid)
return nil, false
}else{
slog.Warn("armyMgr GetByRId db error", "armyId", aid)
return nil, false
}
}
}
}
func (this*armyMgr) GetByCity(cid int) ([]*model.Army, bool){
this.mutex.RLock()
as, ok := this.armyByCityId[cid]
this.mutex.RUnlock()
if ok {
for _, a := range as {
a.CheckConscript()
}
return as, true
}else{
m := make([]*model.Army, 0)
err := db.MasterDB.Table(model.Army{}).Where("cityId=?", cid).Find(&m)
if err!=nil{
slog.Warn("armyMgr GetByCity db error", "cityId", cid)
return m, false
}else{
this.mutex.Lock()
this.insertMutil(m)
this.mutex.Unlock()
return m, true
}
}
}
func (this*armyMgr) GetByCityOrder(cid int, order int8) (*model.Army, bool){
rs, ok := this.GetByCity(cid)
if ok {
for _, r := range rs {
if r.Order == order{
return r, true
}
}
}else{
return nil, false
}
return nil, false
}
func (this*armyMgr) GetByRId(rid int) ([]*model.Army, bool){
this.mutex.RLock()
as, ok := this.armyByRId[rid]
this.mutex.RUnlock()
if ok {
for _, a := range as {
a.CheckConscript()
}
}
return as, ok
}
//归属于该位置的军队数量
func (this*armyMgr) BelongPosArmyCnt(rid int, x, y int) int{
cnt := 0
armys, ok := this.GetByRId(rid)
if ok {
for _, army := range armys {
if army.FromX == x && army.FromY == y{
cnt += 1
}else if army.Cmd == model.ArmyCmdTransfer && army.ToX == x && army.ToY == y {
cnt += 1
}
}
}
return cnt
}
func (this*armyMgr) GetOrCreate(rid int, cid int, order int8) (*model.Army, error){
this.mutex.RLock()
armys, ok := this.armyByCityId[cid]
this.mutex.RUnlock()
if ok {
for _, v := range armys {
if v.Order == order{
return v, nil
}
}
}
//需要创建
army := &model.Army{RId: rid,
Order: order,
CityId: cid,
Generals: `[0,0,0]`,
Soldiers: `[0,0,0]`,
GeneralArray: []int{0,0,0},
SoldierArray: []int{0,0,0},
ConscriptCnts: `[0,0,0]`,
ConscriptTimes: `[0,0,0]`,
ConscriptCntArray: []int{0,0,0},
ConscriptTimeArray: []int64{0,0,0},
}
city, ok := RCMgr.Get(cid)
if ok {
army.FromX = city.X
army.FromY = city.Y
army.ToX = city.X
army.ToY = city.Y
}
_, err := db.MasterDB.Insert(army)
if err == nil{
this.mutex.Lock()
this.insertOne(army)
this.mutex.Unlock()
return army, nil
}else{
slog.Warn("db error", "error", err)
return nil, err
}
}
func (this*armyMgr) GetSpeed(army*model.Army) int{
speed := 100000
for _, g := range army.Gens {
if g != nil {
s := g.GetSpeed()
if s < speed {
speed = s
}
}
}
//阵营加成
camp := army.GetCamp()
campAdds := []int{0}
if camp > 0{
campAdds = RFMgr.GetAdditions(army.CityId, facility.TypeHanAddition-1+camp)
}
return speed + campAdds[0]
}
//能否已经重复上阵了
func (this*armyMgr) IsRepeat(rid int, cfgId int) bool{
armys, ok := this.GetByRId(rid)
if ok == false{
return true
}
for _, army := range armys {
for _, g := range army.Gens {
if g != nil {
if g.CfgId == cfgId && g.CityId != 0{
return false
}
}
}
}
return true
}
func (this*armyMgr) updateGenerals(armys... *model.Army) {
for _, army := range armys {
army.Gens = make([]*model.General, 0)
for _, gid := range army.GeneralArray {
if gid == 0{
army.Gens = append(army.Gens, nil)
}else{
g, _ := GMgr.GetByGId(gid)
army.Gens = append(army.Gens, g)
}
}
}
}
func (this*armyMgr) All()[]*model.Army {
this.mutex.RLock()
defer this.mutex.RUnlock()
armys := make([]*model.Army, 0)
for _, army := range this.armyById {
armys = append(armys, army)
}
return armys
}

View File

@@ -0,0 +1,326 @@
package mgr
import (
"encoding/json"
"log/slog"
"slgserver/constant"
"slgserver/db"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/static_conf/facility"
"sync"
"time"
)
var RFMgr = facilityMgr{
facilities: make(map[int]*model.CityFacility),
facilitiesByRId: make(map[int][]*model.CityFacility),
}
type facilityMgr struct {
mutex sync.RWMutex
facilities map[int]*model.CityFacility
facilitiesByRId map[int][]*model.CityFacility //key:rid
}
func (this*facilityMgr) Load() {
err := db.MasterDB.Find(this.facilities)
if err != nil {
slog.Error("facilityMgr load city_facility table error")
}
for _, cityFacility := range this.facilities {
rid := cityFacility.RId
_, ok := this.facilitiesByRId[rid]
if ok == false {
this.facilitiesByRId[rid] = make([]*model.CityFacility, 0)
}
this.facilitiesByRId[rid] = append(this.facilitiesByRId[rid], cityFacility)
}
}
func (this*facilityMgr) GetByRId(rid int) ([]*model.CityFacility, bool){
this.mutex.RLock()
r, ok := this.facilitiesByRId[rid]
this.mutex.RUnlock()
return r, ok
}
func (this*facilityMgr) Get(cid int) (*model.CityFacility, bool){
this.mutex.RLock()
r, ok := this.facilities[cid]
this.mutex.RUnlock()
if ok {
return r, true
}
r = &model.CityFacility{}
ok, err := db.MasterDB.Table(r).Where("cityId=?", cid).Get(r)
if err != nil{
slog.Warn("db error", "error", err)
}
if ok {
this.mutex.Lock()
this.facilities[cid] = r
this.mutex.Unlock()
return r, true
}else{
return nil, false
}
}
func (this*facilityMgr) GetFacility(cid int, fType int8) (*model.Facility, bool){
cf, ok := this.Get(cid)
if ok == false{
return nil, false
}
facilities := cf.Facility()
for _, v := range facilities {
if v.Type == fType{
return &v, true
}
}
return nil, false
}
func (this*facilityMgr) GetFacilityLv(cid int, fType int8) int8{
f, ok := this.GetFacility(cid, fType)
if ok {
return f.GetLevel()
}else{
return 0
}
}
/*
获取城内设施加成
*/
func (this*facilityMgr) GetAdditions(cid int, additionType... int8 ) []int{
cf, ok := this.Get(cid)
ret := make([]int, len(additionType))
if ok == false{
return ret
}
for i, at := range additionType {
total := 0
facilities := cf.Facility()
for _, f := range facilities {
if f.GetLevel() > 0{
adds := facility.FConf.GetAdditions(f.Type)
values := facility.FConf.GetValues(f.Type, f.GetLevel())
for i, add := range adds {
if add == at {
total += values[i]
}
}
}
}
ret[i] = total
}
return ret
}
/*
如果不存在尝试去创建
*/
func (this*facilityMgr) GetAndTryCreate(cid, rid int) (*model.CityFacility, bool){
r, ok := this.Get(cid)
if ok {
return r, true
}else{
if _, ok:= RCMgr.Get(cid); ok {
//创建
fs := make([]model.Facility, len(facility.FConf.List))
for i, v := range facility.FConf.List {
f := model.Facility{Type: v.Type, PrivateLevel: 0, Name: v.Name}
fs[i] = f
}
sdata, _ := json.Marshal(fs)
cf := &model.CityFacility{CityId: cid, RId: rid, Facilities: string(sdata)}
db.MasterDB.Table(cf).Insert(cf)
this.mutex.Lock()
this.facilities[cid] = cf
this.mutex.Unlock()
return cf, true
}else{
slog.Warn("cid not found", "cid", cid)
return nil, false
}
}
}
func (this*facilityMgr) UpFacility(rid, cid int, fType int8) (*model.Facility, int){
this.mutex.RLock()
f, ok := this.facilities[cid]
this.mutex.RUnlock()
if ok == false{
slog.Warn("UpFacility cityId not found",
"cityId", cid,
"type", int(fType))
return nil, constant.CityNotExist
}else{
facilities := make([]*model.Facility, 0)
var out *model.Facility
json.Unmarshal([]byte(f.Facilities), &facilities)
for _, fac := range facilities {
if fac.Type == fType {
maxLevel := facility.FConf.MaxLevel(fType)
if fac.CanLV() == false {
//正在升级中了
slog.Warn("UpFacility error because already in up",
"curLevel", int(fac.GetLevel()),
"maxLevel", int(maxLevel),
"cityId", cid,
"type", int(fType))
return nil, constant.UpError
}else if fac.GetLevel() >= maxLevel {
slog.Warn("UpFacility error",
"curLevel", int(fac.GetLevel()),
"maxLevel", int(maxLevel),
"cityId", cid,
"type", int(fType))
return nil, constant.UpError
}else{
need, ok := facility.FConf.Need(fType, fac.GetLevel()+1)
if ok == false {
slog.Warn("UpFacility Need config error",
"curLevel", int(fac.GetLevel()),
"cityId", cid,
"type", int(fType))
return nil, constant.UpError
}
code := RResMgr.TryUseNeed(rid, *need)
if code == constant.OK {
fac.UpTime = time.Now().Unix()
out = fac
if t, err := json.Marshal(facilities); err == nil{
f.Facilities = string(t)
f.SyncExecute()
return out, constant.OK
}else{
return nil, constant.UpError
}
}else{
slog.Warn("UpFacility Need Res Not Enough",
"curLevel", int(fac.GetLevel()),
"cityId", cid,
"type", int(fType))
return nil, code
}
}
}
}
slog.Warn("UpFacility error not found type",
"cityId", cid,
"type", int(fType))
return nil, constant.UpError
}
}
func (this*facilityMgr) GetYield(rid int)model.Yield{
cfs, ok := this.GetByRId(rid)
var y model.Yield
if ok {
for _, cf := range cfs {
for _, f := range cf.Facility() {
if f.GetLevel() > 0{
values := facility.FConf.GetValues(f.Type, f.GetLevel())
additions := facility.FConf.GetAdditions(f.Type)
for i, aType := range additions {
if aType == facility.TypeWood {
y.Wood += values[i]
}else if aType == facility.TypeGrain {
y.Grain += values[i]
}else if aType == facility.TypeIron {
y.Iron += values[i]
}else if aType == facility.TypeStone {
y.Stone += values[i]
}else if aType == facility.TypeTax {
y.Gold += values[i]
}
}
}
}
}
}
return y
}
func (this*facilityMgr) GetDepotCapacity(rid int)int{
cfs, ok := this.GetByRId(rid)
limit := 0
if ok {
for _, cf := range cfs {
for _, f := range cf.Facility() {
if f.GetLevel() > 0{
values := facility.FConf.GetValues(f.Type, f.GetLevel())
additions := facility.FConf.GetAdditions(f.Type)
for i, aType := range additions {
if aType == facility.TypeWarehouseLimit {
limit += values[i]
}
}
}
}
}
}
return limit
}
func (this*facilityMgr) GetCost(cid int) int8{
cf, ok := this.Get(cid)
limit := 0
if ok {
for _, f := range cf.Facility() {
if f.GetLevel() > 0{
values := facility.FConf.GetValues(f.Type, f.GetLevel())
additions := facility.FConf.GetAdditions(f.Type)
for i, aType := range additions {
if aType == facility.TypeCost {
limit += values[i]
}
}
}
}
}
return int8(limit)
}
func (this*facilityMgr) GetMaxDurable(cid int) int{
cf, ok := this.Get(cid)
limit := 0
if ok {
for _, f := range cf.Facility() {
if f.GetLevel() > 0{
values := facility.FConf.GetValues(f.Type, f.GetLevel())
additions := facility.FConf.GetAdditions(f.Type)
for i, aType := range additions {
if aType == facility.TypeDurable {
limit += values[i]
}
}
}
}
}
return limit
}
func (this*facilityMgr) GetCityLV(cid int) int8{
return this.GetFacilityLv(cid, facility.Main)
}

View File

@@ -0,0 +1,98 @@
package mgr
import (
"log/slog"
"slgserver/db"
"slgserver/server/slgserver/model"
"sync"
"time"
)
type coalitionMgr struct {
mutex sync.RWMutex
unions map[int]*model.Coalition
}
var UnionMgr = &coalitionMgr{
unions: make(map[int]*model.Coalition),
}
func (this*coalitionMgr) Load() {
rr := make([]*model.Coalition, 0)
err := db.MasterDB.Where("state=?", model.UnionRunning).Find(&rr)
if err != nil {
slog.Error("coalitionMgr load union table error")
}
for _, v := range rr {
this.unions[v.Id] = v
}
}
func (this*coalitionMgr) Get(unionId int) (*model.Coalition, bool){
this.mutex.RLock()
r, ok := this.unions[unionId]
this.mutex.RUnlock()
if ok {
return r, true
}
m := &model.Coalition{}
ok, err := db.MasterDB.Table(new(model.Coalition)).Where(
"unionId=? and state=?", unionId, model.UnionRunning).Get(m)
if ok {
this.mutex.Lock()
this.unions[unionId] = m
this.mutex.Unlock()
return m, true
}else{
if err == nil{
slog.Warn("coalitionMgr not found", "unionId", unionId)
return nil, false
}else{
slog.Warn("db error", "error", err)
return nil, false
}
}
}
func (this*coalitionMgr) Create(name string, rid int) (*model.Coalition, bool){
m := &model.Coalition{Name: name, Ctime: time.Now(),
CreateId: rid, Chairman: rid, State: model.UnionRunning, MemberArray: []int{rid}}
_, err := db.MasterDB.Table(new(model.Coalition)).InsertOne(m)
if err == nil {
this.mutex.Lock()
this.unions[m.Id] = m
this.mutex.Unlock()
return m, true
}else{
slog.Error("db error", "error", err)
return nil, false
}
}
func (this*coalitionMgr) List() []*model.Coalition {
r := make([]*model.Coalition, 0)
this.mutex.RLock()
for _, coalition := range this.unions {
r = append(r, coalition)
}
this.mutex.RUnlock()
return r
}
func (this*coalitionMgr) Remove(unionId int) {
this.mutex.Lock()
delete(this.unions, unionId)
this.mutex.Unlock()
}

View File

@@ -0,0 +1,353 @@
package mgr
import (
"log/slog"
"math/rand"
"slgserver/db"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/static_conf"
"slgserver/server/slgserver/static_conf/general"
"slgserver/util"
"sync"
"time"
)
type generalMgr struct {
mutex sync.RWMutex
genByRole map[int][]*model.General
genByGId map[int]*model.General
}
var GMgr = &generalMgr{
genByRole: make(map[int][]*model.General),
genByGId: make(map[int]*model.General),
}
func (this*generalMgr) updatePhysicalPower() {
limit := static_conf.Basic.General.PhysicalPowerLimit
recoverCnt := static_conf.Basic.General.RecoveryPhysicalPower
for true {
time.Sleep(1*time.Hour)
this.mutex.RLock()
for _, g := range this.genByGId {
if g.PhysicalPower < limit{
g.PhysicalPower = util.MinInt(limit, g.PhysicalPower+recoverCnt)
g.SyncExecute()
}
}
this.mutex.RUnlock()
}
}
//创建npc
func (this*generalMgr) createNPC() ([]*model.General, bool){
gs := make([]*model.General, 0)
sess := db.MasterDB.NewSession()
sess.Begin()
for _, v := range general.General.GMap {
if v.Star >= 3{
arr := []int8{1,5,10,20}
for _, level := range arr{
r, ok := this.NewGeneral(v.CfgId, 0, level)
if ok == false {
sess.Rollback()
return nil, false
}
gs = append(gs, r)
}
}
}
if err := sess.Commit(); err != nil{
slog.Warn("db error", "error", err)
return nil, false
}else{
return gs, true
}
}
func (this*generalMgr) add(g *model.General) {
this.mutex.Lock()
if _,ok := this.genByRole[g.RId]; ok == false{
this.genByRole[g.RId] = make([]*model.General, 0)
}
this.genByRole[g.RId] = append(this.genByRole[g.RId], g)
this.genByGId[g.Id] = g
this.mutex.Unlock()
}
func (this*generalMgr) Load(){
err := db.MasterDB.Table(model.General{}).Where("state=?",
model.GeneralNormal).Find(this.genByGId)
if err != nil {
slog.Warn("db error", "error", err)
return
}
for _, v := range this.genByGId {
if _, ok := this.genByRole[v.RId]; ok==false {
this.genByRole[v.RId] = make([]*model.General, 0)
}
this.genByRole[v.RId] = append(this.genByRole[v.RId], v)
}
if len(this.genByGId) == 0{
this.createNPC()
}
go this.updatePhysicalPower()
}
func (this*generalMgr) GetByRId(rid int) ([]*model.General, bool){
this.mutex.Lock()
r, ok := this.genByRole[rid]
this.mutex.Unlock()
if ok {
out := make([]*model.General, 0)
for _, g := range r {
if g.IsActive(){
out = append(out, g)
}
}
return out, true
}
gs := make([]*model.General, 0)
err := db.MasterDB.Table(new(model.General)).Where(
"rid=? and state=?", rid, model.GeneralNormal).Find(&gs)
if err == nil {
if len(gs) > 0 {
for _, g := range gs {
this.add(g)
}
return gs, true
}else{
slog.Warn("general not fount", "rid", rid)
return nil, false
}
}else{
slog.Warn("db error", "error", err)
return nil, false
}
}
//查找将领
func (this*generalMgr) GetByGId(gid int) (*model.General, bool){
this.mutex.RLock()
g, ok := this.genByGId[gid]
this.mutex.RUnlock()
if ok {
if g.IsActive(){
return g, true
}else{
return nil, false
}
}else{
g := &model.General{}
r, err := db.MasterDB.Table(new(model.General)).Where(
"id=? and state=?", gid, model.GeneralNormal).Get(g)
if err == nil{
if r {
this.add(g)
return g, true
}else{
slog.Warn("general gid not found", "gid", gid)
return nil, false
}
}else{
slog.Warn("general gid not found", "gid", gid)
return nil, false
}
}
}
//这个角色是否有这个武将
func (this*generalMgr) HasGeneral(rid int ,gid int) (*model.General,bool){
r, ok := this.GetByRId(rid)
if ok {
for _, v := range r {
t := v
if t.Id == gid {
return t,true
}
}
}
return nil,false
}
func (this*generalMgr) HasGenerals(rid int, gIds []int) ([]*model.General,bool){
gs := make([]*model.General, 0)
for i := 0; i < len(gIds); i++ {
g,ok := this.HasGeneral(rid, gIds[i])
if ok{
gs = append(gs,g)
}else{
return gs,false
}
}
return gs,true
}
func (this*generalMgr) Count(rid int) int{
gs, ok := this.GetByRId(rid)
if ok {
return len(gs)
}else{
return 0
}
}
func (this*generalMgr) NewGeneral(cfgId int, rid int, level int8) (*model.General, bool) {
g, ok := model.NewGeneral(cfgId, rid, level)
if ok {
this.add(g)
}
return g, ok
}
/*
如果不存在则去创建
*/
func (this*generalMgr) GetOrCreateByRId(rid int) ([]*model.General, bool){
r, ok := this.GetByRId(rid)
if ok {
return r, true
}else{
//创建
gs := make([]*model.General, 0)
sess := db.MasterDB.NewSession()
sess.Begin()
g, ok := this.RandCreateGeneral(rid,3)
if ok == false{
sess.Rollback()
return nil, false
}
gs = g
if err := sess.Commit(); err != nil{
slog.Warn("db error", "error", err)
return nil, false
}else{
return gs, true
}
}
}
/*
随机创建一个
*/
func (this*generalMgr) RandCreateGeneral(rid int, nums int) ([]*model.General, bool){
gs := make([]*model.General, 0)
sess := db.MasterDB.NewSession()
sess.Begin()
for i := 0; i < nums; i++ {
cfgId := general.General.Draw()
g, ok := this.NewGeneral(cfgId, rid, 1)
if ok == false{
sess.Rollback()
return nil, false
}
gs = append(gs, g)
}
if err := sess.Commit(); err != nil{
slog.Warn("db error", "error", err)
return nil, false
}else{
return gs, true
}
}
//获取npc武将
func (this*generalMgr) GetNPCGenerals(cnt int, star int8, level int8) ([]model.General, bool) {
gs, ok := this.GetByRId(0)
if ok == false {
return make([]model.General, 0), false
}else{
target := make([]model.General, 0)
for _, g := range gs {
if g.Level == level && g.Star == star{
target = append(target, *g)
}
}
if len(target) < cnt{
return make([]model.General, 0), false
}else{
m := make(map[int]int)
for true {
r := rand.Intn(len(target))
m[r] = r
if len(m) == cnt{
break
}
}
rgs := make([]model.General, 0)
for _, v := range m {
t := target[v]
rgs = append(rgs, t)
}
return rgs, true
}
}
}
func (this *generalMgr) GetDestroy(army *model.Army) int{
destroy := 0
for _, g := range army.Gens {
if g != nil {
destroy += g.GetDestroy()
}
}
return destroy
}
//体力是否足够
func (this*generalMgr) PhysicalPowerIsEnough(army *model.Army, cost int) bool{
for _, g := range army.Gens {
if g == nil{
continue
}
if g.PhysicalPower < cost{
return false
}
}
return true
}
//尝试使用体力
func (this *generalMgr) TryUsePhysicalPower(army *model.Army, cost int) bool{
if this.PhysicalPowerIsEnough(army, cost) == false{
return false
}
for _, g := range army.Gens {
if g == nil{
continue
}
g.PhysicalPower -= cost
g.SyncExecute()
}
return true
}

View File

@@ -0,0 +1,176 @@
package mgr
import (
"encoding/json"
"log/slog"
"math"
"os"
"slgserver/config"
"slgserver/server/slgserver/global"
"slgserver/server/slgserver/model"
"slgserver/util"
"sync"
)
const ScanWith = 3
const ScanHeight = 3
type NMArray struct {
arr []model.NationalMap
}
type mapData struct {
Width int `json:"w"`
Height int `json:"h"`
List [][]int `json:"list"`
}
func Distance(begX, begY, endX, endY int) float64 {
w := math.Abs(float64(endX - begX))
h := math.Abs(float64(endY - begY))
return math.Sqrt(w*w + h*h)
}
func TravelTime(speed, begX, begY, endX, endY int) int {
dis := Distance(begX, begY, endX, endY)
t := dis / float64(speed) * 100000000
return int(t)
}
type NationalMapMgr struct {
mutex sync.RWMutex
conf map[int]model.NationalMap
sysBuild map[int]model.NationalMap
}
var NMMgr = &NationalMapMgr{
conf: make(map[int]model.NationalMap),
sysBuild: make(map[int]model.NationalMap),
}
func (this *NationalMapMgr) Load() {
fileName := config.GetPath("logic.map_data",
"data/conf/mapRes_0.json")
jdata, err := os.ReadFile(fileName)
if err != nil {
slog.Error("NationalMapMgr load file error", "error", err)
os.Exit(0)
}
m := &mapData{}
err = json.Unmarshal(jdata, m)
if err != nil {
slog.Error("NationalMapMgr Unmarshal json error", "error", err)
os.Exit(0)
}
//转成服务用的结构
global.MapWith = m.Width
global.MapHeight = m.Height
for i, v := range m.List {
t := int8(v[0])
l := int8(v[1])
d := model.NationalMap{Y: i / global.MapHeight, X: i % global.MapWith, MId: i, Type: t, Level: l}
this.conf[i] = d
if d.Type == model.MapBuildSysCity ||
d.Type == model.MapBuildSysFortress {
this.sysBuild[i] = d
}
}
slog.Info("sysBuild len", "len", len(this.sysBuild))
}
func (this *NationalMapMgr) IsCanBuild(x, y int) bool {
posIndex := global.ToPosition(x, y)
this.mutex.RLock()
defer this.mutex.RUnlock()
c, ok := this.conf[posIndex]
if ok {
if c.Type == 0 {
return false
} else {
return true
}
} else {
return false
}
}
func (this *NationalMapMgr) IsCanBuildCity(x, y int) bool {
//系统城池附近5格不能有玩家城池
for _, nationalMap := range this.sysBuild {
if nationalMap.Type == model.MapBuildSysCity {
if x >= nationalMap.X-5 && x <= nationalMap.X+5 &&
y >= nationalMap.Y-5 && y <= nationalMap.Y+5 {
return false
}
}
}
for i := x - 2; i <= x+2; i++ {
if i < 0 || i > global.MapWith {
return false
}
for j := y - 2; j <= y+2; j++ {
if j < 0 || j > global.MapHeight {
return false
}
}
if this.IsCanBuild(x, y) == false ||
RBMgr.IsEmpty(x, y) == false ||
RCMgr.IsEmpty(x, y) == false {
return false
}
}
return true
}
func (this *NationalMapMgr) MapResTypeLevel(x, y int) (bool, int8, int8) {
n, ok := this.PositionBuild(x, y)
if ok {
return true, n.Type, n.Level
}
return false, 0, 0
}
func (this *NationalMapMgr) PositionBuild(x, y int) (model.NationalMap, bool) {
posIndex := global.ToPosition(x, y)
this.mutex.RLock()
defer this.mutex.RUnlock()
b, ok := this.conf[posIndex]
return b, ok
}
func (this *NationalMapMgr) Scan(x, y int) []model.NationalMap {
this.mutex.RLock()
defer this.mutex.RUnlock()
minX := util.MaxInt(0, x-ScanWith)
maxX := util.MinInt(40, x+ScanWith)
minY := util.MaxInt(0, y-ScanHeight)
maxY := util.MinInt(40, y+ScanHeight)
c := (maxX - minX + 1) * (maxY - minY + 1)
r := make([]model.NationalMap, c)
index := 0
for i := minX; i <= maxX; i++ {
for j := minY; j <= maxY; j++ {
v, ok := this.conf[global.ToPosition(i, j)]
if ok {
r[index] = v
}
index++
}
}
return r
}

View File

@@ -0,0 +1,121 @@
package mgr
import (
"log/slog"
"slgserver/db"
"slgserver/server/slgserver/model"
"sync"
)
type roleAttributeMgr struct {
mutex sync.RWMutex
attribute map[int]*model.RoleAttribute //key:rid
}
var RAttrMgr = &roleAttributeMgr{
attribute: make(map[int]*model.RoleAttribute),
}
func (this*roleAttributeMgr) Load() {
//加载
t := make(map[int]*model.RoleAttribute)
err := db.MasterDB.Find(t)
if err != nil {
slog.Error("roleAttributeMgr load role_attribute table error", "error", err)
}
//获取联盟id
for _, v:= range t {
this.attribute[v.RId] = v
}
l := UnionMgr.List()
for _, c := range l {
for _, rid := range c.MemberArray {
attr, ok := this.attribute[rid]
if ok {
attr.UnionId = c.Id
}else{
attr := this.create(rid)
if attr != nil{
attr.UnionId = c.Id
}
}
}
}
}
func (this*roleAttributeMgr) Get(rid int) (*model.RoleAttribute, bool){
this.mutex.RLock()
r, ok := this.attribute[rid]
this.mutex.RUnlock()
if ok {
return r, true
}else {
return nil, false
}
}
func (this*roleAttributeMgr) TryCreate(rid int) (*model.RoleAttribute, bool){
attr, ok := this.Get(rid)
if ok {
return attr, true
}else{
this.mutex.Lock()
defer this.mutex.Unlock()
attr := this.create(rid)
return attr, attr != nil
}
}
func (this*roleAttributeMgr) create(rid int) *model.RoleAttribute {
roleAttr := &model.RoleAttribute{RId: rid, ParentId: 0, UnionId: 0}
if _ , err := db.MasterDB.Insert(roleAttr); err != nil {
slog.Error("insert RoleAttribute error", "error", err)
return nil
}else{
this.attribute[rid] = roleAttr
return roleAttr
}
}
func (this*roleAttributeMgr) IsHasUnion(rid int) bool{
this.mutex.RLock()
r, ok := this.attribute[rid]
this.mutex.RUnlock()
if ok {
return r.UnionId != 0
}else {
return false
}
}
func (this*roleAttributeMgr) UnionId(rid int) int{
this.mutex.RLock()
r, ok := this.attribute[rid]
this.mutex.RUnlock()
if ok {
return r.UnionId
}else {
return 0
}
}
func (this*roleAttributeMgr) List() []*model.RoleAttribute {
this.mutex.RLock()
defer this.mutex.RUnlock()
ret := make([]*model.RoleAttribute, 0)
for _, attribute := range this.attribute {
ret = append(ret, attribute)
}
return ret
}

View File

@@ -0,0 +1,436 @@
package mgr
import (
"log/slog"
"slgserver/constant"
"slgserver/db"
"slgserver/server/slgserver/global"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/static_conf"
"slgserver/util"
"sync"
"time"
)
type roleBuildMgr struct {
baseMutex sync.RWMutex
giveUpMutex sync.RWMutex
destroyMutex sync.RWMutex
dbRB map[int]*model.MapRoleBuild //key:dbId
posRB map[int]*model.MapRoleBuild //key:posId
roleRB map[int][]*model.MapRoleBuild //key:roleId
giveUpRB map[int64]map[int]*model.MapRoleBuild //key:time
destroyRB map[int64]map[int]*model.MapRoleBuild //key:time
}
var RBMgr = &roleBuildMgr{
dbRB: make(map[int]*model.MapRoleBuild),
posRB: make(map[int]*model.MapRoleBuild),
roleRB: make(map[int][]*model.MapRoleBuild),
giveUpRB: make(map[int64]map[int]*model.MapRoleBuild),
destroyRB: make(map[int64]map[int]*model.MapRoleBuild),
}
func (this *roleBuildMgr) Load() {
if total, err := db.MasterDB.Where("type = ? or type = ?",
model.MapBuildSysCity,
model.MapBuildSysFortress).Count(new(model.MapRoleBuild)); err != nil {
slog.Error("db error when loading role build", "error", err)
panic("db error: " + err.Error())
} else {
//初始化系统建筑到数据库
if int64(len(NMMgr.sysBuild)) != total {
db.MasterDB.Where("type = ? or type = ?",
model.MapBuildSysCity,
model.MapBuildSysFortress).Delete(new(model.MapRoleBuild))
for _, sysBuild := range NMMgr.sysBuild {
build := model.MapRoleBuild{
RId: 0,
Type: sysBuild.Type,
Level: sysBuild.Level,
X: sysBuild.X,
Y: sysBuild.Y,
}
build.Init()
db.MasterDB.InsertOne(&build)
}
}
}
err := db.MasterDB.Find(this.dbRB)
if err != nil {
slog.Error("roleBuildMgr load role_build table error", "error", err)
}
curTime := time.Now().Unix()
//转成posRB 和 roleRB
for _, v := range this.dbRB {
v.Init()
//恢复正在放弃的土地
if v.GiveUpTime != 0 {
_, ok := this.giveUpRB[v.GiveUpTime]
if ok == false {
this.giveUpRB[v.GiveUpTime] = make(map[int]*model.MapRoleBuild)
}
this.giveUpRB[v.GiveUpTime][v.Id] = v
}
//恢复正在拆除的建筑
if v.OPLevel == 0 && v.Level != v.OPLevel {
t := v.EndTime.Unix()
if curTime >= t {
v.ConvertToRes()
} else {
_, ok := this.destroyRB[t]
if ok == false {
this.destroyRB[t] = make(map[int]*model.MapRoleBuild)
}
this.destroyRB[t][v.Id] = v
}
}
posId := global.ToPosition(v.X, v.Y)
this.posRB[posId] = v
_, ok := this.roleRB[v.RId]
if ok == false {
this.roleRB[v.RId] = make([]*model.MapRoleBuild, 0)
}
this.roleRB[v.RId] = append(this.roleRB[v.RId], v)
//过滤掉到了放弃时间的领地
if v.GiveUpTime != 0 && v.GiveUpTime <= curTime {
this.RemoveFromRole(v)
}
}
}
// 检测正在放弃的土地是否到期了
func (this *roleBuildMgr) CheckGiveUp() []int {
var ret []int
var builds []*model.MapRoleBuild
curTime := time.Now().Unix()
this.giveUpMutex.Lock()
for i := curTime - 10; i <= curTime; i++ {
gs, ok := this.giveUpRB[i]
if ok {
for _, g := range gs {
builds = append(builds, g)
ret = append(ret, global.ToPosition(g.X, g.Y))
}
}
}
this.giveUpMutex.Unlock()
for _, build := range builds {
this.RemoveFromRole(build)
}
return ret
}
// 检测正在拆除的建筑是否到期
func (this *roleBuildMgr) CheckDestroy() []int {
var ret []int
var builds []*model.MapRoleBuild
curTime := time.Now().Unix()
this.destroyMutex.Lock()
for i := curTime - 10; i <= curTime; i++ {
gs, ok := this.destroyRB[i]
if ok {
for _, g := range gs {
builds = append(builds, g)
ret = append(ret, global.ToPosition(g.X, g.Y))
}
}
}
this.destroyMutex.Unlock()
for _, build := range builds {
build.ConvertToRes()
build.SyncExecute()
}
return ret
}
/*
该位置是否被角色占领
*/
func (this *roleBuildMgr) IsEmpty(x, y int) bool {
this.baseMutex.RLock()
defer this.baseMutex.RUnlock()
posId := global.ToPosition(x, y)
_, ok := this.posRB[posId]
return !ok
}
func (this *roleBuildMgr) PositionBuild(x, y int) (*model.MapRoleBuild, bool) {
this.baseMutex.RLock()
defer this.baseMutex.RUnlock()
posId := global.ToPosition(x, y)
b, ok := this.posRB[posId]
if ok {
return b, ok
} else {
return nil, false
}
}
func (this *roleBuildMgr) RoleFortressCnt(rid int) int {
bs, ok := this.GetRoleBuild(rid)
cnt := 0
if ok == false {
return 0
} else {
for _, b := range bs {
if b.IsRoleFortress() {
cnt += 1
}
}
}
return cnt
}
func (this *roleBuildMgr) AddBuild(rid, x, y int) (*model.MapRoleBuild, bool) {
posId := global.ToPosition(x, y)
this.baseMutex.Lock()
rb, ok := this.posRB[posId]
this.baseMutex.Unlock()
if ok {
rb.RId = rid
this.baseMutex.Lock()
if _, ok := this.roleRB[rid]; ok == false {
this.roleRB[rid] = make([]*model.MapRoleBuild, 0)
}
this.roleRB[rid] = append(this.roleRB[rid], rb)
this.baseMutex.Unlock()
return rb, true
} else {
if b, ok := NMMgr.PositionBuild(x, y); ok {
if cfg, _ := static_conf.MapBuildConf.BuildConfig(b.Type, b.Level); cfg != nil {
rb := &model.MapRoleBuild{
RId: rid, X: x, Y: y,
Type: b.Type, Level: b.Level, OPLevel: b.Level,
Name: cfg.Name, CurDurable: cfg.Durable,
MaxDurable: cfg.Durable,
}
rb.Init()
if _, err := db.MasterDB.Table(model.MapRoleBuild{}).Insert(rb); err == nil {
this.baseMutex.Lock()
this.posRB[posId] = rb
this.dbRB[rb.Id] = rb
if _, ok := this.roleRB[rid]; ok == false {
this.roleRB[rid] = make([]*model.MapRoleBuild, 0)
}
this.roleRB[rid] = append(this.roleRB[rid], rb)
this.baseMutex.Unlock()
return rb, true
} else {
slog.Warn("db error", "error", err)
}
}
}
}
return nil, false
}
func (this *roleBuildMgr) RemoveFromRole(build *model.MapRoleBuild) {
this.baseMutex.Lock()
rb, ok := this.roleRB[build.RId]
if ok {
for i, v := range rb {
if v.Id == build.Id {
this.roleRB[build.RId] = append(rb[:i], rb[i+1:]...)
break
}
}
}
this.baseMutex.Unlock()
//移除放弃事件
t := build.GiveUpTime
this.giveUpMutex.Lock()
if ms, ok := this.giveUpRB[t]; ok {
delete(ms, build.Id)
}
this.giveUpMutex.Unlock()
//移除拆除事件
t = build.EndTime.Unix()
this.destroyMutex.Lock()
if ms, ok := this.destroyRB[t]; ok {
delete(ms, build.Id)
}
this.destroyMutex.Unlock()
build.Reset()
build.SyncExecute()
}
func (this *roleBuildMgr) GetRoleBuild(rid int) ([]*model.MapRoleBuild, bool) {
this.baseMutex.RLock()
defer this.baseMutex.RUnlock()
ra, ok := this.roleRB[rid]
return ra, ok
}
func (this *roleBuildMgr) BuildCnt(rid int) int {
bs, ok := this.GetRoleBuild(rid)
if ok {
return len(bs)
} else {
return 0
}
}
func (this *roleBuildMgr) Scan(x, y int) []*model.MapRoleBuild {
if x < 0 || x >= global.MapWith || y < 0 || y >= global.MapHeight {
return nil
}
this.baseMutex.RLock()
defer this.baseMutex.RUnlock()
minX := util.MaxInt(0, x-ScanWith)
maxX := util.MinInt(global.MapWith, x+ScanWith)
minY := util.MaxInt(0, y-ScanHeight)
maxY := util.MinInt(global.MapHeight, y+ScanHeight)
rb := make([]*model.MapRoleBuild, 0)
for i := minX; i <= maxX; i++ {
for j := minY; j <= maxY; j++ {
posId := global.ToPosition(i, j)
v, ok := this.posRB[posId]
if ok && v.RId != 0 {
rb = append(rb, v)
}
}
}
return rb
}
func (this *roleBuildMgr) ScanBlock(x, y, length int) []*model.MapRoleBuild {
if x < 0 || x >= global.MapWith || y < 0 || y >= global.MapHeight {
return nil
}
this.baseMutex.RLock()
defer this.baseMutex.RUnlock()
maxX := util.MinInt(global.MapWith, x+length-1)
maxY := util.MinInt(global.MapHeight, y+length-1)
rb := make([]*model.MapRoleBuild, 0)
for i := x; i <= maxX; i++ {
for j := y; j <= maxY; j++ {
posId := global.ToPosition(i, j)
v, ok := this.posRB[posId]
if ok && (v.RId != 0 || v.IsSysCity() || v.IsSysFortress()) {
rb = append(rb, v)
}
}
}
return rb
}
func (this *roleBuildMgr) BuildIsRId(x, y, rid int) bool {
b, ok := this.PositionBuild(x, y)
if ok {
return b.RId == rid
} else {
return false
}
}
func (this *roleBuildMgr) GetYield(rid int) model.Yield {
builds, ok := this.GetRoleBuild(rid)
var y model.Yield
if ok {
for _, b := range builds {
y.Iron += b.Iron
y.Wood += b.Wood
y.Grain += b.Grain
y.Stone += b.Grain
}
}
return y
}
func (this *roleBuildMgr) GiveUp(x, y int) int {
b, ok := this.PositionBuild(x, y)
if ok == false {
return constant.CannotGiveUp
}
if b.IsWarFree() {
return constant.BuildWarFree
}
if b.GiveUpTime > 0 {
return constant.BuildGiveUpAlready
}
b.GiveUpTime = time.Now().Unix() + static_conf.Basic.Build.GiveUpTime
b.SyncExecute()
this.giveUpMutex.Lock()
_, ok = this.giveUpRB[b.GiveUpTime]
if ok == false {
this.giveUpRB[b.GiveUpTime] = make(map[int]*model.MapRoleBuild)
}
this.giveUpRB[b.GiveUpTime][b.Id] = b
this.giveUpMutex.Unlock()
return constant.OK
}
func (this *roleBuildMgr) Destroy(x, y int) int {
b, ok := this.PositionBuild(x, y)
if ok == false {
return constant.BuildNotMe
}
if b.IsHaveModifyLVAuth() == false || b.IsInGiveUp() || b.IsBusy() {
return constant.CanNotDestroy
}
cfg, ok := static_conf.MapBCConf.BuildConfig(b.Type, b.Level)
if ok == false {
return constant.InvalidParam
}
code := RResMgr.TryUseNeed(b.RId, cfg.Need)
if code != constant.OK {
return code
}
b.EndTime = time.Now().Add(time.Duration(cfg.Time) * time.Second)
this.destroyMutex.Lock()
t := b.EndTime.Unix()
_, ok = this.destroyRB[t]
if ok == false {
this.destroyRB[t] = make(map[int]*model.MapRoleBuild)
}
this.destroyRB[t][b.Id] = b
this.destroyMutex.Unlock()
b.DelBuild(*cfg)
b.SyncExecute()
return constant.OK
}

View File

@@ -0,0 +1,204 @@
package mgr
import (
"log/slog"
"slgserver/db"
"slgserver/server/slgserver/global"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/static_conf"
"slgserver/util"
"sync"
"time"
)
type roleCityMgr struct {
mutex sync.RWMutex
dbCity map[int]*model.MapRoleCity //key: cid
posCity map[int]*model.MapRoleCity //key: pos
roleCity map[int][]*model.MapRoleCity //key: rid
}
var RCMgr = &roleCityMgr{
dbCity: make(map[int]*model.MapRoleCity),
posCity: make(map[int]*model.MapRoleCity),
roleCity: make(map[int][]*model.MapRoleCity),
}
func GetCityCost(cid int) int8 {
return RFMgr.GetCost(cid) + static_conf.Basic.City.Cost
}
func GetMaxDurable(cid int) int {
return RFMgr.GetMaxDurable(cid) + static_conf.Basic.City.Durable
}
func GetCityLV(cid int) int8 {
return RFMgr.GetCityLV(cid)
}
func (this*roleCityMgr) Load() {
err := db.MasterDB.Find(this.dbCity)
if err != nil {
slog.Error("roleCityMgr load role_city table error")
}
//转成posCity、roleCity
for _, v := range this.dbCity {
posId := global.ToPosition(v.X, v.Y)
this.posCity[posId] = v
_, ok := this.roleCity[v.RId]
if ok == false{
this.roleCity[v.RId] = make([]*model.MapRoleCity, 0)
}
this.roleCity[v.RId] = append(this.roleCity[v.RId], v)
}
go this.running()
}
func (this*roleCityMgr) running() {
for true {
t := static_conf.Basic.City.RecoveryTime
time.Sleep(time.Duration(t) * time.Second)
this.mutex.RLock()
for _, city := range this.dbCity {
if city.CurDurable < GetMaxDurable(city.CityId){
city.DurableChange(100)
city.SyncExecute()
}
}
this.mutex.RUnlock()
}
}
/*
该位置是否被角色建立城池
*/
func (this*roleCityMgr) IsEmpty(x, y int) bool {
this.mutex.RLock()
defer this.mutex.RUnlock()
posId := global.ToPosition(x, y)
_, ok := this.posCity[posId]
return !ok
}
func (this*roleCityMgr) PositionCity(x, y int) (*model.MapRoleCity, bool) {
this.mutex.RLock()
defer this.mutex.RUnlock()
posId := global.ToPosition(x, y)
c,ok := this.posCity[posId]
return c, ok
}
func (this*roleCityMgr) Add(city *model.MapRoleCity) {
this.mutex.Lock()
defer this.mutex.Unlock()
this.dbCity[city.CityId] = city
this.posCity[global.ToPosition(city.X, city.Y)] = city
_, ok := this.roleCity[city.RId]
if ok == false{
this.roleCity[city.RId] = make([]*model.MapRoleCity, 0)
}
this.roleCity[city.RId] = append(this.roleCity[city.RId], city)
}
func (this*roleCityMgr) Scan(x, y int) []*model.MapRoleCity {
if x < 0 || x >= global.MapWith || y < 0 || y >= global.MapHeight {
return nil
}
this.mutex.RLock()
defer this.mutex.RUnlock()
minX := util.MaxInt(0, x-ScanWith)
maxX := util.MinInt(40, x+ScanWith)
minY := util.MaxInt(0, y-ScanHeight)
maxY := util.MinInt(40, y+ScanHeight)
cb := make([]*model.MapRoleCity, 0)
for i := minX; i <= maxX; i++ {
for j := minY; j <= maxY; j++ {
posId := global.ToPosition(i, j)
v, ok := this.posCity[posId]
if ok {
cb = append(cb, v)
}
}
}
return cb
}
func (this*roleCityMgr) ScanBlock(x, y, length int) []*model.MapRoleCity {
if x < 0 || x >= global.MapWith || y < 0 || y >= global.MapHeight {
return nil
}
this.mutex.RLock()
defer this.mutex.RUnlock()
maxX := util.MinInt(global.MapWith, x+length-1)
maxY := util.MinInt(global.MapHeight, y+length-1)
cb := make([]*model.MapRoleCity, 0)
for i := x; i <= maxX; i++ {
for j := y; j <= maxY; j++ {
posId := global.ToPosition(i, j)
v, ok := this.posCity[posId]
if ok {
cb = append(cb, v)
}
}
}
return cb
}
func (this*roleCityMgr) GetByRId(rid int) ([]*model.MapRoleCity, bool){
this.mutex.RLock()
r, ok := this.roleCity[rid]
this.mutex.RUnlock()
return r, ok
}
func (this*roleCityMgr) GetMainCity(rid int) (*model.MapRoleCity, bool){
citys, ok := this.GetByRId(rid)
if ok == false {
return nil, false
}else{
for _, city := range citys {
if city.IsMain == 1{
return city, true
}
}
}
return nil, false
}
func (this*roleCityMgr) Get(cid int) (*model.MapRoleCity, bool){
this.mutex.RLock()
r, ok := this.dbCity[cid]
this.mutex.RUnlock()
if ok {
return r, true
}
r = &model.MapRoleCity{}
ok, err := db.MasterDB.Table(r).Where("cityId=?", cid).Get(r)
if err != nil{
slog.Warn("db error", "error", err)
}
if ok {
this.mutex.Lock()
this.dbCity[cid] = r
this.mutex.Unlock()
return r, true
}else{
return nil, false
}
}

View File

@@ -0,0 +1,48 @@
package mgr
import (
"log/slog"
"slgserver/db"
"slgserver/server/slgserver/model"
"sync"
)
func RoleNickName(rid int) string {
vRole, ok := RMgr.Get(rid)
if ok {
return vRole.NickName
}
return ""
}
type roleMgr struct {
mutex sync.RWMutex
roles map[int]*model.Role
}
var RMgr = &roleMgr{
roles: make(map[int]*model.Role),
}
func (this*roleMgr) Get(rid int) (*model.Role, bool){
this.mutex.RLock()
r, ok := this.roles[rid]
this.mutex.RUnlock()
if ok {
return r, true
}
m := &model.Role{}
ok, err := db.MasterDB.Table(new(model.Role)).Where("rid=?", rid).Get(m)
if ok {
this.mutex.Lock()
this.roles[rid] = m
this.mutex.Unlock()
return m, true
}else{
slog.Warn("db error", "error", err, "rid", rid)
return nil, false
}
}

View File

@@ -0,0 +1,248 @@
package mgr
import (
"log/slog"
"slgserver/constant"
"slgserver/db"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/static_conf"
"slgserver/server/slgserver/static_conf/facility"
"slgserver/util"
"sync"
"time"
)
type roleResMgr struct {
mutex sync.RWMutex
rolesRes map[int]*model.RoleRes
}
var RResMgr = &roleResMgr{
rolesRes: make(map[int]*model.RoleRes),
}
//获取产量
func GetYield(rid int) model.Yield {
by := RBMgr.GetYield(rid)
cy := RFMgr.GetYield(rid)
var y model.Yield
y.Gold = by.Gold + cy.Gold + static_conf.Basic.Role.GoldYield
y.Stone = by.Stone + cy.Stone + static_conf.Basic.Role.StoneYield
y.Iron = by.Iron + cy.Iron + static_conf.Basic.Role.IronYield
y.Grain = by.Grain + cy.Grain + static_conf.Basic.Role.GrainYield
y.Wood = by.Wood + cy.Wood + static_conf.Basic.Role.WoodYield
return y
}
//获取仓库容量
func GetDepotCapacity(rid int) int {
return RFMgr.GetDepotCapacity(rid) + static_conf.Basic.Role.DepotCapacity
}
func (this*roleResMgr) Load() {
rr := make([]*model.RoleRes, 0)
err := db.MasterDB.Find(&rr)
if err != nil {
slog.Error("roleResMgr load role_res table error")
}
for _, v := range rr {
this.rolesRes[v.RId] = v
}
go this.produce()
}
func (this*roleResMgr) Get(rid int) (*model.RoleRes, bool){
this.mutex.RLock()
r, ok := this.rolesRes[rid]
this.mutex.RUnlock()
if ok {
return r, true
}
m := &model.RoleRes{}
ok, err := db.MasterDB.Table(new(model.RoleRes)).Where("rid=?", rid).Get(m)
if ok {
this.mutex.Lock()
this.rolesRes[rid] = m
this.mutex.Unlock()
return m, true
}else{
if err == nil{
slog.Warn("RoleRes not found", "rid", rid)
return nil, false
}else{
slog.Warn("db error", "error", err)
return nil, false
}
}
}
func (this*roleResMgr) Add(res *model.RoleRes) (){
this.mutex.Lock()
this.rolesRes[res.RId] = res
this.mutex.Unlock()
}
func (this*roleResMgr) TryUseNeed(rid int, need facility.NeedRes) int{
this.mutex.RLock()
rr, ok := this.rolesRes[rid]
this.mutex.RUnlock()
if ok {
if need.Decree <= rr.Decree && need.Grain <= rr.Grain &&
need.Stone <= rr.Stone && need.Wood <= rr.Wood &&
need.Iron <= rr.Iron && need.Gold <= rr.Gold {
rr.Decree -= need.Decree
rr.Iron -= need.Iron
rr.Wood -= need.Wood
rr.Stone -= need.Stone
rr.Grain -= need.Grain
rr.Gold -= need.Gold
rr.SyncExecute()
return constant.OK
}else{
if need.Decree > rr.Decree{
return constant.DecreeNotEnough
}else{
return constant.ResNotEnough
}
}
}else {
return constant.RoleNotExist
}
}
//政令是否足够
func (this*roleResMgr) DecreeIsEnough(rid int, cost int) bool {
this.mutex.RLock()
rr, ok := this.rolesRes[rid]
this.mutex.RUnlock()
if ok {
if rr.Decree >= cost {
return true
}else{
return false
}
}else{
return false
}
}
func (this*roleResMgr) TryUseDecree(rid int, decree int) bool{
this.mutex.RLock()
rr, ok := this.rolesRes[rid]
this.mutex.RUnlock()
if ok {
if rr.Decree >= decree {
rr.Decree -= decree
rr.SyncExecute()
return true
}else{
return false
}
}else{
return false
}
}
//金币是否足够
func (this*roleResMgr) GoldIsEnough(rid int, cost int) bool {
this.mutex.RLock()
rr, ok := this.rolesRes[rid]
this.mutex.RUnlock()
if ok {
if rr.Gold >= cost {
return true
}else{
return false
}
}else{
return false
}
}
func (this*roleResMgr) TryUseGold(rid int, gold int) bool{
this.mutex.RLock()
rr, ok := this.rolesRes[rid]
this.mutex.RUnlock()
if ok {
if rr.Gold >= gold {
rr.Gold -= gold
rr.SyncExecute()
return true
}else{
return false
}
}else{
return false
}
}
func (this*roleResMgr) produce() {
index := 1
for true {
t := static_conf.Basic.Role.RecoveryTime
time.Sleep(time.Duration(t) * time.Second)
this.mutex.RLock()
for _, v := range this.rolesRes {
//加判断是因为爆仓了,资源不无故减少
capacity := GetDepotCapacity(v.RId)
yield := GetYield(v.RId)
if v.Wood < capacity{
v.Wood += util.MinInt(yield.Wood/6, capacity)
}
if v.Iron < capacity{
v.Iron += util.MinInt(yield.Iron/6, capacity)
}
if v.Stone < capacity{
v.Stone += util.MinInt(yield.Stone/6, capacity)
}
if v.Grain < capacity{
v.Grain += util.MinInt(yield.Grain/6, capacity)
}
if v.Gold < capacity{
v.Grain += util.MinInt(yield.Grain/6, capacity)
}
if index%6 == 0{
if v.Decree < static_conf.Basic.Role.DecreeLimit{
v.Decree+=1
}
}
v.SyncExecute()
}
index++
this.mutex.RUnlock()
}
}

View File

@@ -0,0 +1,97 @@
package mgr
import (
"log/slog"
"slgserver/db"
"slgserver/server/slgserver/model"
"sync"
)
type skillMgr struct {
mutex sync.RWMutex
skillMap map[int][]*model.Skill
}
var SkillMgr = &skillMgr{
skillMap: make(map[int][]*model.Skill),
}
func (this*skillMgr) Load() {
rr := make([]*model.Skill, 0)
err := db.MasterDB.Find(&rr)
if err != nil {
slog.Error("skillMgr load role_res table error")
}
for _, v := range rr {
if this.skillMap[v.RId] == nil{
this.skillMap[v.RId] = make([]*model.Skill, 0)
}
this.skillMap[v.RId] = append(this.skillMap[v.RId], v)
}
}
func (this*skillMgr) Get(rid int) ([]*model.Skill, bool){
this.mutex.RLock()
r, ok := this.skillMap[rid]
this.mutex.RUnlock()
if ok {
return r, true
}
m := make([]*model.Skill, 0)
ok, err := db.MasterDB.Table(new(model.Skill)).Where("rid=?", rid).Get(&m)
if ok {
this.mutex.Lock()
this.skillMap[rid] = m
this.mutex.Unlock()
return m, true
}else{
if err == nil{
slog.Warn("skill not found", "rid", rid)
return nil, false
}else{
slog.Warn("db error", "error", err)
return nil, false
}
}
}
func (this*skillMgr) GetSkillOrCreate(rid int, cfg int) (*model.Skill, bool){
success := true
m, ok := this.Get(rid)
var ret *model.Skill = nil
if ok {
for _, v := range m {
if v.CfgId != cfg{
continue
}else{
ret = v
}
}
}
if ret == nil {
ret = model.NewSkill(rid, cfg)
_, err := db.MasterDB.InsertOne(ret)
if err != nil {
slog.Warn("db error", "error", err)
success = false
}else{
if this.skillMap[rid] == nil{
this.skillMap[rid] = make([]*model.Skill, 0)
}
this.skillMap[rid] = append(this.skillMap[rid], ret)
}
}
return ret, success
}

View File

@@ -0,0 +1,95 @@
package logic
import (
"slgserver/server/slgserver/global"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/static_conf"
"sync"
)
func NewSysArmy() *sysArmyLogic {
return &sysArmyLogic{
sysArmys: make(map[int][]*model.Army),
}
}
type sysArmyLogic struct {
mutex sync.Mutex
sysArmys map[int][]*model.Army //key:posId 系统建筑军队
}
func (this* sysArmyLogic) getArmyCfg(x, y int) (star int8, lv int8, soilders int) {
defender := 1
star = 3
lv = 5
soilders = 100
if mapBuild, ok := mgr.NMMgr.PositionBuild(x, y); ok{
cfg, ok := static_conf.MapBuildConf.BuildConfig(mapBuild.Type, mapBuild.Level)
if ok {
defender = cfg.Defender
if npc, ok := static_conf.Basic.GetNPC(cfg.Level); ok {
soilders = npc.Soilders
}
}
}
if defender == 1{
star = 3
lv = 5
}else if defender == 2{
star = 4
lv = 10
}else {
star = 5
lv = 20
}
return star, lv, soilders
}
func (this *sysArmyLogic) GetArmy(x, y int) []*model.Army {
posId := global.ToPosition(x, y)
this.mutex.Lock()
a, ok := this.sysArmys[posId]
this.mutex.Unlock()
if ok {
return a
}else{
armys := make([]*model.Army, 0)
star, lv, soilders := this.getArmyCfg(x, y)
out, ok := mgr.GMgr.GetNPCGenerals(3, star, lv)
if ok {
gsId := make([]int, 0)
gs := make([]*model.General, 3)
for i := 0; i < len(out) ; i++ {
gs[i] = &out[i]
}
scnt := []int{soilders, soilders, soilders}
army := &model.Army{RId: 0, Order: 0, CityId: 0,
GeneralArray: gsId, Gens: gs, SoldierArray: scnt}
army.ToGeneral()
army.ToSoldier()
armys = append(armys, army)
posId := global.ToPosition(x, y)
this.sysArmys[posId] = armys
}
return armys
}
}
func (this *sysArmyLogic) DelArmy(x, y int) {
this.mutex.Lock()
defer this.mutex.Unlock()
posId := global.ToPosition(x, y)
delete(this.sysArmys, posId)
}

View File

@@ -0,0 +1,36 @@
package logic
import (
"slgserver/server/slgserver/global"
"slgserver/server/slgserver/logic/mgr"
"slgserver/util"
)
var ViewWidth = 5
var ViewHeight = 5
//是否在视野范围内
func armyIsInView(rid, x, y int) bool {
unionId := getUnionId(rid)
for i := util.MaxInt(x-ViewWidth, 0); i < util.MinInt(x+ViewWidth, global.MapWith) ; i++ {
for j := util.MaxInt(y-ViewHeight, 0); j < util.MinInt(y+ViewHeight, global.MapHeight) ; j++ {
build, ok := mgr.RBMgr.PositionBuild(i, j)
if ok {
tUnionId := getUnionId(build.RId)
if (tUnionId != 0 && unionId == tUnionId) || build.RId == rid{
return true
}
}
city, ok := mgr.RCMgr.PositionCity(i, j)
if ok {
tUnionId := getUnionId(city.RId)
if (tUnionId != 0 && unionId == tUnionId) || city.RId == rid{
return true
}
}
}
}
return false
}

View File

@@ -0,0 +1,338 @@
package model
import (
"encoding/json"
"fmt"
"log/slog"
"slgserver/db"
"slgserver/net"
"slgserver/server/slgserver/global"
"slgserver/server/slgserver/proto"
"slgserver/util"
"time"
"xorm.io/xorm"
)
const (
ArmyCmdIdle = 0 //空闲
ArmyCmdAttack = 1 //攻击
ArmyCmdDefend = 2 //驻守
ArmyCmdReclamation = 3 //屯垦
ArmyCmdBack = 4 //撤退
ArmyCmdConscript = 5 //征兵
ArmyCmdTransfer = 6 //调动
)
const (
ArmyStop = 0
ArmyRunning = 1
)
/*******db 操作begin********/
var dbArmyMgr *armyDBMgr
func init() {
dbArmyMgr = &armyDBMgr{armys: make(chan *Army, 100)}
go dbArmyMgr.running()
}
type armyDBMgr struct {
armys chan *Army
}
func (this *armyDBMgr) running() {
for true {
select {
case army := <-this.armys:
if army.Id > 0 {
_, err := db.MasterDB.Table(army).ID(army.Id).Cols(
"soldiers", "generals", "conscript_times",
"conscript_cnts", "cmd", "from_x", "from_y", "to_x",
"to_y", "start", "end").Update(army)
if err != nil {
slog.Warn("db error", "error", err)
}
} else {
slog.Warn("update army fail, because id <= 0")
}
}
}
}
func (this *armyDBMgr) push(army *Army) {
this.armys <- army
}
/*******db 操作end********/
// 军队
type Army struct {
Id int `xorm:"id pk autoincr"`
RId int `xorm:"rid"`
CityId int `xorm:"cityId"`
Order int8 `xorm:"order"`
Generals string `xorm:"generals"`
Soldiers string `xorm:"soldiers"`
ConscriptTimes string `xorm:"conscript_times"` //征兵结束时间json数组
ConscriptCnts string `xorm:"conscript_cnts"` //征兵数量json数组
Cmd int8 `xorm:"cmd"`
FromX int `xorm:"from_x"`
FromY int `xorm:"from_y"`
ToX int `xorm:"to_x"`
ToY int `xorm:"to_y"`
Start time.Time `json:"-"xorm:"start"`
End time.Time `json:"-"xorm:"end"`
State int8 `xorm:"-"` //状态:0:running,1:stop
GeneralArray []int `json:"-" xorm:"-"`
SoldierArray []int `json:"-" xorm:"-"`
ConscriptTimeArray []int64 `json:"-" xorm:"-"`
ConscriptCntArray []int `json:"-" xorm:"-"`
Gens []*General `json:"-" xorm:"-"`
CellX int `json:"-" xorm:"-"`
CellY int `json:"-" xorm:"-"`
}
func (this *Army) TableName() string {
return "tb_army" + fmt.Sprintf("_%d", ServerId)
}
// 是否能出战
func (this *Army) IsCanOutWar() bool {
return this.Gens[0] != nil && this.Cmd == ArmyCmdIdle
}
func (this *Army) AfterSet(name string, cell xorm.Cell) {
if name == "generals" {
this.GeneralArray = []int{0, 0, 0}
if cell != nil {
gs, ok := (*cell).([]uint8)
if ok {
json.Unmarshal(gs, &this.GeneralArray)
slog.Debug("army generals loaded", "array", this.GeneralArray)
}
}
} else if name == "soldiers" {
this.SoldierArray = []int{0, 0, 0}
if cell != nil {
ss, ok := (*cell).([]uint8)
if ok {
json.Unmarshal(ss, &this.SoldierArray)
slog.Debug("army soldiers loaded", "array", this.SoldierArray)
}
}
} else if name == "conscript_times" {
this.ConscriptTimeArray = []int64{0, 0, 0}
if cell != nil {
ss, ok := (*cell).([]uint8)
if ok {
json.Unmarshal(ss, &this.ConscriptTimeArray)
slog.Debug("army conscript times loaded", "array", this.ConscriptTimeArray)
}
}
} else if name == "conscript_cnts" {
this.ConscriptCntArray = []int{0, 0, 0}
if cell != nil {
ss, ok := (*cell).([]uint8)
if ok {
json.Unmarshal(ss, &this.ConscriptCntArray)
slog.Debug("army conscript counts loaded", "array", this.ConscriptCntArray)
}
}
}
}
func (this *Army) beforeModify() {
data, _ := json.Marshal(this.GeneralArray)
this.Generals = string(data)
data, _ = json.Marshal(this.SoldierArray)
this.Soldiers = string(data)
data, _ = json.Marshal(this.ConscriptTimeArray)
this.ConscriptTimes = string(data)
data, _ = json.Marshal(this.ConscriptCntArray)
this.ConscriptCnts = string(data)
}
func (this *Army) BeforeInsert() {
this.beforeModify()
}
func (this *Army) BeforeUpdate() {
this.beforeModify()
}
func (this *Army) ToSoldier() {
if this.SoldierArray != nil {
data, _ := json.Marshal(this.SoldierArray)
this.Soldiers = string(data)
}
}
func (this *Army) ToGeneral() {
if this.GeneralArray != nil {
data, _ := json.Marshal(this.GeneralArray)
this.Generals = string(data)
}
}
// 获取军队阵营
func (this *Army) GetCamp() int8 {
var camp int8 = 0
for _, g := range this.Gens {
if g == nil {
return 0
}
if camp == 0 {
camp = g.GetCamp()
} else {
if camp != g.GetCamp() {
return 0
}
}
}
return camp
}
// 检测征兵是否完成,服务器不做定时任务,用到的时候再检测
func (this *Army) CheckConscript() {
if this.Cmd == ArmyCmdConscript {
curTime := time.Now().Unix()
finish := true
for i, endTime := range this.ConscriptTimeArray {
if endTime > 0 {
if endTime <= curTime {
this.SoldierArray[i] += this.ConscriptCntArray[i]
this.ConscriptCntArray[i] = 0
this.ConscriptTimeArray[i] = 0
} else {
finish = false
}
}
}
if finish {
this.Cmd = ArmyCmdIdle
}
}
}
// 队伍指定的位置是否能变化(上下阵)
func (this *Army) PositionCanModify(position int) bool {
if position >= 3 || position < 0 {
return false
}
if this.Cmd == ArmyCmdIdle {
return true
} else if this.Cmd == ArmyCmdConscript {
endTime := this.ConscriptTimeArray[position]
return endTime == 0
} else {
return false
}
}
func (this *Army) ClearConscript() {
if this.Cmd == ArmyCmdConscript {
for i, _ := range this.ConscriptTimeArray {
this.ConscriptCntArray[i] = 0
this.ConscriptTimeArray[i] = 0
}
this.Cmd = ArmyCmdIdle
}
}
func (this *Army) IsIdle() bool {
return this.Cmd == ArmyCmdIdle
}
/* 推送同步 begin */
func (this *Army) IsCellView() bool {
return true
}
func (this *Army) IsCanView(rid, x, y int) bool {
if ArmyIsInView != nil {
return ArmyIsInView(rid, x, y)
}
return false
}
func (this *Army) BelongToRId() []int {
return []int{this.RId}
}
func (this *Army) PushMsgName() string {
return "army.push"
}
func (this *Army) Position() (int, int) {
diffTime := this.End.Unix() - this.Start.Unix()
passTime := time.Now().Unix() - this.Start.Unix()
rate := float32(passTime) / float32(diffTime)
x := 0
y := 0
if this.Cmd == ArmyCmdBack {
diffX := this.FromX - this.ToX
diffY := this.FromY - this.ToY
x = int(rate*float32(diffX)) + this.ToX
y = int(rate*float32(diffY)) + this.ToY
} else {
diffX := this.ToX - this.FromX
diffY := this.ToY - this.FromY
x = int(rate*float32(diffX)) + this.FromX
y = int(rate*float32(diffY)) + this.FromY
}
x = util.MinInt(util.MaxInt(x, 0), global.MapWith)
y = util.MinInt(util.MaxInt(y, 0), global.MapHeight)
slog.Info("army Position:", "x", x, "y", y)
return x, y
}
func (this *Army) TPosition() (int, int) {
return this.ToX, this.ToY
}
func (this *Army) ToProto() interface{} {
p := proto.Army{}
p.CityId = this.CityId
p.Id = this.Id
p.UnionId = GetUnionId(this.RId)
p.Order = this.Order
p.Generals = this.GeneralArray
p.Soldiers = this.SoldierArray
p.ConTimes = this.ConscriptTimeArray
p.ConCnts = this.ConscriptCntArray
p.Cmd = this.Cmd
p.State = this.State
p.FromX = this.FromX
p.FromY = this.FromY
p.ToX = this.ToX
p.ToY = this.ToY
p.Start = this.Start.Unix()
p.End = this.End.Unix()
return p
}
func (this *Army) Push() {
net.ConnMgr.Push(this)
}
/* 推送同步 end */
func (this *Army) SyncExecute() {
dbArmyMgr.push(this)
this.Push()
this.CellX, this.CellY = this.Position()
}
func (this *Army) CheckSyncCell() {
x, y := this.Position()
if x != this.CellX || y != this.CellY {
this.SyncExecute()
}
}

View File

@@ -0,0 +1,90 @@
package model
import (
"encoding/json"
"fmt"
"log/slog"
"slgserver/db"
"slgserver/server/slgserver/static_conf/facility"
"time"
)
/*******db 操作begin********/
var dbCFMgr *cfDBMgr
func init() {
dbCFMgr = &cfDBMgr{cs: make(chan *CityFacility, 100)}
go dbCFMgr.running()
}
type cfDBMgr struct {
cs chan *CityFacility
}
func (this*cfDBMgr) running() {
for true {
select {
case c := <- this.cs:
if c.Id >0 {
_, err := db.MasterDB.Table(c).ID(c.Id).Cols("facilities").Update(c)
if err != nil{
slog.Warn("db error", "error", err)
}
}else{
slog.Warn("update CityFacility fail, because id <= 0")
}
}
}
}
func (this*cfDBMgr) push(c *CityFacility) {
this.cs <- c
}
/*******db 操作end********/
type Facility struct {
Name string `json:"name"`
PrivateLevel int8 `json:"level"` //等级外部读的时候不能直接读要用GetLevel
Type int8 `json:"type"`
UpTime int64 `json:"up_time"` //升级的时间戳0表示该等级已经升级完成了
}
//升级这里做成被动触发产生,不做定时
func (this* Facility) GetLevel() int8 {
if this.UpTime > 0{
cur := time.Now().Unix()
cost := facility.FConf.CostTime(this.Type, this.PrivateLevel+1)
if cur >= this.UpTime + int64(cost){
this.PrivateLevel +=1
this.UpTime = 0
}
}
return this.PrivateLevel
}
func (this* Facility) CanLV() bool {
this.GetLevel()
return this.UpTime == 0
}
type CityFacility struct {
Id int `xorm:"id pk autoincr"`
RId int `xorm:"rid"`
CityId int `xorm:"cityId"`
Facilities string `xorm:"facilities"`
}
func (this *CityFacility) TableName() string {
return "tb_city_facility" + fmt.Sprintf("_%d", ServerId)
}
func (this *CityFacility) SyncExecute() {
dbCFMgr.push(this)
}
func (this*CityFacility) Facility()[]Facility {
facilities := make([]Facility, 0)
json.Unmarshal([]byte(this.Facilities), &facilities)
return facilities
}

View File

@@ -0,0 +1,323 @@
package model
import (
"encoding/json"
"fmt"
"log/slog"
"slgserver/db"
"slgserver/net"
"slgserver/server/slgserver/proto"
"time"
"xorm.io/xorm"
)
const (
UnionDismiss = 0 //解散
UnionRunning = 1 //运行中
)
/*******db 操作begin********/
var dbCoalitionMgr *coalitionDBMgr
func init() {
dbCoalitionMgr = &coalitionDBMgr{coalitions: make(chan *Coalition, 100)}
go dbCoalitionMgr.running()
}
type coalitionDBMgr struct {
coalitions chan *Coalition
}
func (this *coalitionDBMgr) running() {
for true {
select {
case coalition := <-this.coalitions:
if coalition.Id > 0 {
_, err := db.MasterDB.Table(coalition).ID(coalition.Id).Cols("name",
"members", "chairman", "vice_chairman", "notice", "state").Update(coalition)
if err != nil {
slog.Warn("db error", "error", err)
}
} else {
slog.Warn("update coalition fail, because id <= 0")
}
}
}
}
func (this *coalitionDBMgr) push(coalition *Coalition) {
this.coalitions <- coalition
}
/*******db 操作end********/
type Coalition struct {
Id int `xorm:"id pk autoincr"`
Name string `xorm:"name"`
Members string `xorm:"members"`
MemberArray []int `xorm:"-"`
CreateId int `xorm:"create_id"`
Chairman int `xorm:"chairman"`
ViceChairman int `xorm:"vice_chairman"`
Notice string `xorm:"notice"`
State int8 `xorm:"state"`
Ctime time.Time `xorm:"ctime"`
}
func (this *Coalition) ToProto() interface{} {
p := proto.Union{}
p.Id = this.Id
p.Name = this.Name
p.Notice = this.Notice
p.Cnt = this.Cnt()
return p
}
func (this *Coalition) TableName() string {
return "tb_coalition" + fmt.Sprintf("_%d", ServerId)
}
func (this *Coalition) AfterSet(name string, cell xorm.Cell) {
if name == "members" {
if cell != nil {
ss, ok := (*cell).([]uint8)
if ok {
json.Unmarshal(ss, &this.MemberArray)
}
if this.MemberArray == nil {
this.MemberArray = []int{}
slog.Debug("coalition members loaded", "members", this.MemberArray)
}
}
}
}
func (this *Coalition) BeforeInsert() {
data, _ := json.Marshal(this.MemberArray)
this.Members = string(data)
}
func (this *Coalition) BeforeUpdate() {
data, _ := json.Marshal(this.MemberArray)
this.Members = string(data)
}
func (this *Coalition) Cnt() int {
return len(this.MemberArray)
}
func (this *Coalition) SyncExecute() {
dbCoalitionMgr.push(this)
}
type CoalitionApply struct {
Id int `xorm:"id pk autoincr"`
UnionId int `xorm:"union_id"`
RId int `xorm:"rid"`
State int8 `xorm:"state"`
Ctime time.Time `xorm:"ctime"`
}
func (this *CoalitionApply) TableName() string {
return "tb_coalition_apply" + fmt.Sprintf("_%d", ServerId)
}
/* 推送同步 begin */
func (this *CoalitionApply) IsCellView() bool {
return false
}
func (this *CoalitionApply) IsCanView(rid, x, y int) bool {
return false
}
func (this *CoalitionApply) BelongToRId() []int {
r := GetMainMembers(this.UnionId)
return append(r, this.RId)
}
func (this *CoalitionApply) PushMsgName() string {
return "unionApply.push"
}
func (this *CoalitionApply) Position() (int, int) {
return -1, -1
}
func (this *CoalitionApply) TPosition() (int, int) {
return -1, -1
}
func (this *CoalitionApply) ToProto() interface{} {
p := proto.ApplyItem{}
p.RId = this.RId
p.Id = this.Id
p.NickName = GetRoleNickName(this.RId)
return p
}
func (this *CoalitionApply) Push() {
net.ConnMgr.Push(this)
}
/* 推送同步 end */
func (this *CoalitionApply) SyncExecute() {
this.Push()
}
const (
UnionOpCreate = 0 //创建
UnionOpDismiss = 1 //解散
UnionOpJoin = 2 //加入
UnionOpExit = 3 //退出
UnionOpKick = 4 //踢出
UnionOpAppoint = 5 //任命
UnionOpAbdicate = 6 //禅让
UnionOpModNotice = 7 //修改公告
)
type CoalitionLog struct {
Id int `xorm:"id pk autoincr"`
UnionId int `xorm:"union_id"`
OPRId int `xorm:"op_rid"`
TargetId int `xorm:"target_id"`
State int8 `xorm:"state"`
Des string `xorm:"des"`
Ctime time.Time `xorm:"ctime"`
}
func (this *CoalitionLog) TableName() string {
return "tb_coalition_log" + fmt.Sprintf("_%d", ServerId)
}
func (this *CoalitionLog) ToProto() interface{} {
p := proto.UnionLog{}
p.OPRId = this.OPRId
p.TargetId = this.TargetId
p.Des = this.Des
p.State = this.State
p.Ctime = this.Ctime.UnixNano() / 1e6
return p
}
func NewCreate(opNickName string, unionId int, opRId int) {
ulog := &CoalitionLog{
UnionId: unionId,
OPRId: opRId,
TargetId: 0,
State: UnionOpCreate,
Des: opNickName + " 创建了联盟",
Ctime: time.Now(),
}
db.MasterDB.InsertOne(ulog)
}
func NewDismiss(opNickName string, unionId int, opRId int) {
ulog := &CoalitionLog{
UnionId: unionId,
OPRId: opRId,
TargetId: 0,
State: UnionOpDismiss,
Des: opNickName + " 解散了联盟",
Ctime: time.Now(),
}
db.MasterDB.InsertOne(ulog)
}
func NewJoin(targetNickName string, unionId int, opRId int, targetId int) {
ulog := &CoalitionLog{
UnionId: unionId,
OPRId: opRId,
TargetId: targetId,
State: UnionOpJoin,
Des: targetNickName + " 加入了联盟",
Ctime: time.Now(),
}
db.MasterDB.InsertOne(ulog)
}
func NewExit(opNickName string, unionId int, opRId int) {
ulog := &CoalitionLog{
UnionId: unionId,
OPRId: opRId,
TargetId: opRId,
State: UnionOpExit,
Des: opNickName + " 退出了联盟",
Ctime: time.Now(),
}
db.MasterDB.InsertOne(ulog)
}
func NewKick(opNickName string, targetNickName string, unionId int, opRId int, targetId int) {
ulog := &CoalitionLog{
UnionId: unionId,
OPRId: opRId,
TargetId: targetId,
State: UnionOpKick,
Des: opNickName + " 将 " + targetNickName + " 踢出了联盟",
Ctime: time.Now(),
}
db.MasterDB.InsertOne(ulog)
}
func NewAppoint(opNickName string, targetNickName string,
unionId int, opRId int, targetId int, memberType int) {
title := ""
if memberType == proto.UnionChairman {
title = "盟主"
} else if memberType == proto.UnionViceChairman {
title = "副盟主"
} else {
title = "普通成员"
}
ulog := &CoalitionLog{
UnionId: unionId,
OPRId: opRId,
TargetId: targetId,
State: UnionOpAppoint,
Des: opNickName + " 将 " + targetNickName + " 任命为 " + title,
Ctime: time.Now(),
}
db.MasterDB.InsertOne(ulog)
}
func NewAbdicate(opNickName string, targetNickName string,
unionId int, opRId int, targetId int, memberType int) {
title := ""
if memberType == proto.UnionChairman {
title = "盟主"
} else if memberType == proto.UnionViceChairman {
title = "副盟主"
} else {
title = "普通成员"
}
ulog := &CoalitionLog{
UnionId: unionId,
OPRId: opRId,
TargetId: targetId,
State: UnionOpAbdicate,
Des: opNickName + " 将 " + title + " 禅让给 " + targetNickName,
Ctime: time.Now(),
}
db.MasterDB.InsertOne(ulog)
}
func NewModNotice(opNickName string, unionId int, opRId int) {
ulog := &CoalitionLog{
UnionId: unionId,
OPRId: opRId,
TargetId: 0,
State: UnionOpModNotice,
Des: opNickName + " 修改了公告",
Ctime: time.Now(),
}
db.MasterDB.InsertOne(ulog)
}

View File

@@ -0,0 +1,326 @@
package model
import (
"encoding/json"
"errors"
"fmt"
"log/slog"
"slgserver/db"
"slgserver/net"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf"
"slgserver/server/slgserver/static_conf/general"
"time"
"xorm.io/xorm"
)
const (
GeneralNormal = 0 //正常
GeneralComposeStar = 1 //星级合成
GeneralConvert = 2 //转换
)
/*******db 操作begin********/
var dbGeneralMgr *generalDBMgr
func init() {
dbGeneralMgr = &generalDBMgr{gs: make(chan *General, 100)}
go dbGeneralMgr.running()
}
type generalDBMgr struct {
gs chan *General
}
func (this *generalDBMgr) running() {
for true {
select {
case g := <-this.gs:
if g.Id > 0 && g.RId > 0 {
_, err := db.MasterDB.Table(g).ID(g.Id).Cols(
"level", "exp", "order", "cityId",
"physical_power", "star_lv", "has_pr_point",
"use_pr_point", "force_added", "strategy_added",
"defense_added", "speed_added", "destroy_added",
"parentId", "compose_type", "skills", "state").Update(g)
if err != nil {
slog.Warn("db error", "error", err)
}
} else {
slog.Warn("update general fail, because id <= 0")
}
}
}
}
func (this *generalDBMgr) push(g *General) {
this.gs <- g
}
/*******db 操作end********/
const SkillLimit = 3
func NewGeneral(cfgId int, rid int, level int8) (*General, bool) {
cfg, ok := general.General.GMap[cfgId]
if ok {
sa := make([]*proto.GSkill, SkillLimit)
ss, _ := json.Marshal(sa)
g := &General{
PhysicalPower: static_conf.Basic.General.PhysicalPowerLimit,
RId: rid,
CfgId: cfg.CfgId,
Order: 0,
CityId: 0,
Level: level,
CreatedAt: time.Now(),
CurArms: cfg.Arms[0],
HasPrPoint: 0,
UsePrPoint: 0,
AttackDis: 0,
ForceAdded: 0,
StrategyAdded: 0,
DefenseAdded: 0,
SpeedAdded: 0,
DestroyAdded: 0,
Star: cfg.Star,
StarLv: 0,
ParentId: 0,
SkillsArray: sa,
Skills: string(ss),
State: GeneralNormal,
}
if _, err := db.MasterDB.Table(General{}).Insert(g); err != nil {
slog.Warn("db error", "error", err)
return nil, false
} else {
return g, true
}
} else {
return nil, false
}
}
type General struct {
Id int `xorm:"id pk autoincr"`
RId int `xorm:"rid"`
CfgId int `xorm:"cfgId"`
PhysicalPower int `xorm:"physical_power"`
Level int8 `xorm:"level"`
Exp int `xorm:"exp"`
Order int8 `xorm:"order"`
CityId int `xorm:"cityId"`
CreatedAt time.Time `xorm:"created_at"`
CurArms int `xorm:"arms"`
HasPrPoint int `xorm:"has_pr_point"`
UsePrPoint int `xorm:"use_pr_point"`
AttackDis int `xorm:"attack_distance"`
ForceAdded int `xorm:"force_added"`
StrategyAdded int `xorm:"strategy_added"`
DefenseAdded int `xorm:"defense_added"`
SpeedAdded int `xorm:"speed_added"`
DestroyAdded int `xorm:"destroy_added"`
StarLv int8 `xorm:"star_lv"`
Star int8 `xorm:"star"`
ParentId int `xorm:"parentId"`
Skills string `xorm:"skills"`
SkillsArray []*proto.GSkill `xorm:"-"`
State int8 `xorm:"state"`
}
func (this *General) TableName() string {
return "tb_general" + fmt.Sprintf("_%d", ServerId)
}
func (this *General) AfterSet(name string, cell xorm.Cell) {
if name == "skills" {
this.SkillsArray = make([]*proto.GSkill, 3)
if cell != nil {
gs, ok := (*cell).([]uint8)
if ok {
json.Unmarshal(gs, &this.Skills)
slog.Debug("general skills loaded", "skills", this.SkillsArray)
}
}
}
}
func (this *General) beforeModify() {
data, _ := json.Marshal(this.SkillsArray)
this.Skills = string(data)
}
func (this *General) BeforeInsert() {
this.beforeModify()
}
func (this *General) BeforeUpdate() {
this.beforeModify()
}
func (this *General) GetDestroy() int {
cfg, ok := general.General.GMap[this.CfgId]
if ok {
return cfg.Destroy + cfg.DestroyGrow*int(this.Level) + this.DestroyAdded
}
return 0
}
func (this *General) IsActive() bool {
return this.State == GeneralNormal
}
func (this *General) GetSpeed() int {
cfg, ok := general.General.GMap[this.CfgId]
if ok {
return cfg.Speed + cfg.SpeedGrow*int(this.Level) + this.SpeedAdded
}
return 0
}
func (this *General) GetForce() int {
cfg, ok := general.General.GMap[this.CfgId]
if ok {
return cfg.Force + cfg.ForceGrow*int(this.Level) + this.ForceAdded
}
return 0
}
func (this *General) GetDefense() int {
cfg, ok := general.General.GMap[this.CfgId]
if ok {
return cfg.Defense + cfg.DefenseGrow*int(this.Level) + this.DefenseAdded
}
return 0
}
func (this *General) GetStrategy() int {
cfg, ok := general.General.GMap[this.CfgId]
if ok {
return cfg.Strategy + cfg.StrategyGrow*int(this.Level) + this.StrategyAdded
}
return 0
}
// 获取阵营
func (this *General) GetCamp() int8 {
cfg, ok := general.General.GMap[this.CfgId]
if ok {
return cfg.Camp
}
return 0
}
func (this *General) UpSkill(skillId int, cfgId int, pos int) bool {
if pos < 0 || pos >= SkillLimit {
return false
}
for _, skill := range this.SkillsArray {
if skill != nil && skill.Id == skillId {
//已经上过同类型的技能了
return false
}
}
s := this.SkillsArray[pos]
if s == nil {
this.SkillsArray[pos] = &proto.GSkill{Id: skillId, Lv: 1, CfgId: cfgId}
return true
} else {
if s.Id == 0 {
s.Id = skillId
s.CfgId = cfgId
s.Lv = 1
return true
} else {
return false
}
}
}
func (this *General) DownSkill(skillId int, pos int) bool {
if pos < 0 || pos >= SkillLimit {
return false
}
s := this.SkillsArray[pos]
if s != nil && s.Id == skillId {
s.Id = 0
s.Lv = 0
s.CfgId = 0
return true
} else {
return false
}
}
func (this *General) PosSkill(pos int) (*proto.GSkill, error) {
if pos >= len(this.SkillsArray) {
return nil, errors.New("skill index out of range")
}
return this.SkillsArray[pos], nil
}
/* 推送同步 begin */
func (this *General) IsCellView() bool {
return false
}
func (this *General) IsCanView(rid, x, y int) bool {
return false
}
func (this *General) BelongToRId() []int {
return []int{this.RId}
}
func (this *General) PushMsgName() string {
return "general.push"
}
func (this *General) Position() (int, int) {
return -1, -1
}
func (this *General) TPosition() (int, int) {
return -1, -1
}
func (this *General) ToProto() interface{} {
p := proto.General{}
p.CityId = this.CityId
p.Order = this.Order
p.PhysicalPower = this.PhysicalPower
p.Id = this.Id
p.CfgId = this.CfgId
p.Level = this.Level
p.Exp = this.Exp
p.CurArms = this.CurArms
p.HasPrPoint = this.HasPrPoint
p.UsePrPoint = this.UsePrPoint
p.AttackDis = this.AttackDis
p.ForceAdded = this.ForceAdded
p.StrategyAdded = this.StrategyAdded
p.DefenseAdded = this.DefenseAdded
p.SpeedAdded = this.SpeedAdded
p.DestroyAdded = this.DestroyAdded
p.StarLv = this.StarLv
p.Star = this.Star
p.State = this.State
p.ParentId = this.ParentId
p.Skills = this.SkillsArray
return p
}
func (this *General) Push() {
net.ConnMgr.Push(this)
}
/* 推送同步 end */
func (this *General) SyncExecute() {
dbGeneralMgr.push(this)
this.Push()
}

View File

@@ -0,0 +1,285 @@
package model
import (
"fmt"
"log/slog"
"slgserver/db"
"slgserver/net"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf"
"slgserver/util"
"time"
)
const (
MapBuildSysFortress = 50 //系统要塞
MapBuildSysCity = 51 //系统城市
MapBuildFortress = 56 //玩家要塞
)
/*******db 操作begin********/
var dbRBMgr *rbDBMgr
func init() {
dbRBMgr = &rbDBMgr{builds: make(chan *MapRoleBuild, 100)}
go dbRBMgr.running()
}
type rbDBMgr struct {
builds chan *MapRoleBuild
}
func (this *rbDBMgr) running() {
for true {
select {
case b := <- this.builds:
if b.Id >0 {
_, err := db.MasterDB.Table(b).ID(b.Id).Cols(
"rid", "name", "type", "level", "op_level",
"cur_durable", "max_durable", "occupy_time",
"giveUp_time", "end_time").Update(b)
if err != nil{
slog.Warn("db error", "error", err)
}
}else{
slog.Warn("update role build fail, because id <= 0")
}
}
}
}
func (this *rbDBMgr) push(b *MapRoleBuild) {
this.builds <- b
}
/*******db 操作end********/
type MapRoleBuild struct {
Id int `xorm:"id pk autoincr"`
RId int `xorm:"rid"`
Type int8 `xorm:"type"`
Level int8 `xorm:"level"`
OPLevel int8 `xorm:"op_level"` //操作level
X int `xorm:"x"`
Y int `xorm:"y"`
Name string `xorm:"name"`
Wood int `xorm:"-"`
Iron int `xorm:"-"`
Stone int `xorm:"-"`
Grain int `xorm:"-"`
Defender int `xorm:"-"`
CurDurable int `xorm:"cur_durable"`
MaxDurable int `xorm:"max_durable"`
OccupyTime time.Time `xorm:"occupy_time"`
EndTime time.Time `xorm:"end_time"` //建造或升级完的时间
GiveUpTime int64 `xorm:"giveUp_time"`
}
func (this *MapRoleBuild) TableName() string {
return "tb_map_role_build" + fmt.Sprintf("_%d", ServerId)
}
func (this* MapRoleBuild) Init() {
if cfg, _ := static_conf.MapBuildConf.BuildConfig(this.Type, this.Level); cfg != nil {
this.Name = cfg.Name
this.Level = cfg.Level
this.Type = cfg.Type
this.Wood = cfg.Wood
this.Iron = cfg.Iron
this.Stone = cfg.Stone
this.Grain = cfg.Grain
this.MaxDurable = cfg.Durable
this.CurDurable = cfg.Durable
this.Defender = cfg.Defender
}
}
func (this* MapRoleBuild) Reset() {
ok, t, level := MapResTypeLevel(this.X, this.Y)
if ok {
if cfg, _ := static_conf.MapBuildConf.BuildConfig(t, level); cfg != nil {
this.Name = cfg.Name
this.Level = cfg.Level
this.Type = cfg.Type
this.Wood = cfg.Wood
this.Iron = cfg.Iron
this.Stone = cfg.Stone
this.Grain = cfg.Grain
this.MaxDurable = cfg.Durable
this.Defender = cfg.Defender
}
}
this.GiveUpTime = 0
this.RId = 0
this.EndTime = time.Time{}
this.OPLevel = this.Level
this.CurDurable = util.MinInt(this.MaxDurable, this.CurDurable)
}
func (this* MapRoleBuild) ConvertToRes() {
rid := this.RId
giveUp := this.GiveUpTime
this.Reset()
this.RId = rid
this.GiveUpTime = giveUp
}
func (this* MapRoleBuild) IsInGiveUp() bool {
return this.GiveUpTime != 0
}
func (this* MapRoleBuild) IsWarFree() bool {
curTime := time.Now().Unix()
if curTime - this.OccupyTime.Unix() < static_conf.Basic.Build.WarFree{
return true
}else{
return false
}
}
func (this* MapRoleBuild) IsResBuild() bool {
return this.Grain > 0 || this.Stone > 0 || this.Iron > 0 || this.Wood > 0
}
//是否有修改等级权限
func (this* MapRoleBuild) IsHaveModifyLVAuth() bool {
return this.Type == MapBuildFortress
}
func (this* MapRoleBuild) IsBusy() bool{
if this.Level != this.OPLevel{
return true
}else {
return false
}
}
func (this* MapRoleBuild) IsRoleFortress() bool {
return this.Type == MapBuildFortress
}
func (this* MapRoleBuild) IsSysFortress() bool {
return this.Type == MapBuildSysFortress
}
func (this* MapRoleBuild) IsSysCity() bool {
return this.Type == MapBuildSysCity
}
func (this* MapRoleBuild) CellRadius() int {
if this.IsSysCity(){
if this.Level >= 8{
return 3
}else if this.Level >= 5{
return 2
}else {
return 1
}
}else{
return 0
}
}
//是否有调兵权限
func (this* MapRoleBuild) IsHasTransferAuth() bool {
return this.Type == MapBuildFortress || this.Type == MapBuildSysFortress
}
func (this* MapRoleBuild) BuildOrUp(cfg static_conf.BCLevelCfg) {
this.Type = cfg.Type
this.Level = cfg.Level -1
this.Name = cfg.Name
this.OPLevel = cfg.Level
this.GiveUpTime = 0
this.Wood = 0
this.Iron = 0
this.Stone = 0
this.Grain = 0
this.EndTime = time.Now().Add(time.Duration(cfg.Time) * time.Second)
}
func (this* MapRoleBuild) DelBuild(cfg static_conf.BCLevelCfg) {
this.OPLevel = 0
this.EndTime = time.Now().Add(time.Duration(cfg.Time) * time.Second)
}
/* 推送同步 begin */
func (this *MapRoleBuild) IsCellView() bool{
return true
}
func (this *MapRoleBuild) IsCanView(rid, x, y int) bool{
return true
}
func (this *MapRoleBuild) BelongToRId() []int{
return []int{this.RId}
}
func (this *MapRoleBuild) PushMsgName() string{
return "roleBuild.push"
}
func (this *MapRoleBuild) Position() (int, int){
return this.X, this.Y
}
func (this *MapRoleBuild) TPosition() (int, int){
return -1, -1
}
func (this *MapRoleBuild) ToProto() interface{}{
p := proto.MapRoleBuild{}
p.RNick = GetRoleNickName(this.RId)
p.UnionId = GetUnionId(this.RId)
p.UnionName = GetUnionName(p.UnionId)
p.ParentId = GetParentId(this.RId)
p.X = this.X
p.Y = this.Y
p.Type = this.Type
p.RId = this.RId
p.Name = this.Name
p.OccupyTime = this.OccupyTime.UnixNano()/1e6
p.GiveUpTime = this.GiveUpTime*1000
p.EndTime = this.EndTime.UnixNano()/1e6
if this.EndTime.IsZero() == false{
if this.IsHasTransferAuth(){
if time.Now().Before(this.EndTime) == false{
if this.OPLevel == 0{
this.ConvertToRes()
}else{
this.Level = this.OPLevel
this.EndTime = time.Time{}
cfg, ok := static_conf.MapBCConf.BuildConfig(this.Type, this.Level)
if ok {
this.MaxDurable = cfg.Durable
this.CurDurable = util.MinInt(this.MaxDurable, this.CurDurable)
this.Defender = cfg.Defender
}
}
}
}
}
p.CurDurable = this.CurDurable
p.MaxDurable = this.MaxDurable
p.Defender = this.Defender
p.Level = this.Level
p.OPLevel = this.OPLevel
return p
}
func (this *MapRoleBuild) Push(){
net.ConnMgr.Push(this)
}
/* 推送同步 end */
func (this *MapRoleBuild) SyncExecute() {
dbRBMgr.push(this)
this.Push()
}

View File

@@ -0,0 +1,144 @@
package model
import (
"fmt"
"log/slog"
"slgserver/db"
"slgserver/net"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf"
"slgserver/util"
"sync"
"time"
)
/*******db 操作begin********/
var dbRCMgr *rcDBMgr
func init() {
dbRCMgr = &rcDBMgr{builds: make(chan *MapRoleCity, 100)}
go dbRCMgr.running()
}
type rcDBMgr struct {
builds chan *MapRoleCity
}
func (this*rcDBMgr) running() {
for true {
select {
case b := <- this.builds:
if b.CityId >0 {
_, err := db.MasterDB.Table(b).ID(b.CityId).Cols("cur_durable", "occupy_time").Update(b)
if err != nil{
slog.Warn("db error", "error", err)
}
}else{
slog.Warn("update role city build fail, because CityId <= 0")
}
}
}
}
func (this*rcDBMgr) push(b *MapRoleCity) {
this.builds <- b
}
/*******db 操作end********/
type MapRoleCity struct {
mutex sync.Mutex `xorm:"-"`
CityId int `xorm:"cityId pk autoincr"`
RId int `xorm:"rid"`
Name string `xorm:"name" validate:"min=4,max=20,regexp=^[a-zA-Z0-9_]*$"`
X int `xorm:"x"`
Y int `xorm:"y"`
IsMain int8 `xorm:"is_main"`
CurDurable int `xorm:"cur_durable"`
CreatedAt time.Time `xorm:"created_at"`
OccupyTime time.Time `xorm:"occupy_time"`
}
func (this* MapRoleCity) IsWarFree() bool {
curTime := time.Now().Unix()
if curTime - this.OccupyTime.Unix() < static_conf.Basic.Build.WarFree{
return true
}else{
return false
}
}
func (this*MapRoleCity) DurableChange(change int) {
this.mutex.Lock()
defer this.mutex.Unlock()
t := this.CurDurable + change
if t < 0{
this.CurDurable = 0
}else{
this.CurDurable = util.MinInt(GetMaxDurable(this.CityId), t)
}
}
func (this *MapRoleCity) Level() int8 {
return GetCityLv(this.CityId)
}
func (this* MapRoleCity) CellRadius() int {
return 1
}
func (this *MapRoleCity) TableName() string {
return "tb_map_role_city" + fmt.Sprintf("_%d", ServerId)
}
/* 推送同步 begin */
func (this *MapRoleCity) IsCellView() bool{
return true
}
func (this *MapRoleCity) IsCanView(rid, x, y int) bool{
return true
}
func (this *MapRoleCity) BelongToRId() []int{
return []int{this.RId}
}
func (this *MapRoleCity) PushMsgName() string{
return "roleCity.push"
}
func (this *MapRoleCity) Position() (int, int){
return this.X, this.Y
}
func (this *MapRoleCity) TPosition() (int, int){
return -1, -1
}
func (this *MapRoleCity) ToProto() interface{}{
p := proto.MapRoleCity{}
p.X = this.X
p.Y = this.Y
p.CityId = this.CityId
p.UnionId = GetUnionId(this.RId)
p.UnionName = GetUnionName(p.UnionId)
p.ParentId = GetParentId(this.RId)
p.MaxDurable = GetMaxDurable(this.RId)
p.CurDurable = this.CurDurable
p.Level = this.Level()
p.RId = this.RId
p.Name = this.Name
p.IsMain = this.IsMain == 1
p.OccupyTime = this.OccupyTime.UnixNano()/1e6
return p
}
func (this *MapRoleCity) Push(){
net.ConnMgr.Push(this)
}
/* 推送同步 end */
func (this *MapRoleCity) SyncExecute() {
dbRCMgr.push(this)
this.Push()
}

View File

@@ -0,0 +1,11 @@
package model
type NationalMap struct {
MId int `xorm:"mid"`
X int `xorm:"x"`
Y int `xorm:"y"`
Type int8 `xorm:"type"`
Level int8 `xorm:"level"`
}

View File

@@ -0,0 +1,36 @@
package model
import (
"fmt"
"slgserver/server/slgserver/proto"
"time"
)
type Role struct {
RId int `xorm:"rid pk autoincr"`
UId int `xorm:"uid"`
NickName string `xorm:"nick_name" validate:"min=4,max=20,regexp=^[a-zA-Z0-9_]*$"`
Balance int `xorm:"balance"`
HeadId int16 `xorm:"headId"`
Sex int8 `xorm:"sex"`
Profile string `xorm:"profile"`
LoginTime time.Time `xorm:"login_time"`
LogoutTime time.Time `xorm:"logout_time"`
CreatedAt time.Time `xorm:"created_at"`
}
func (this *Role) TableName() string {
return "tb_role" + fmt.Sprintf("_%d", ServerId)
}
func (this *Role) ToProto() interface{}{
p := proto.Role{}
p.UId = this.UId
p.RId = this.RId
p.Sex = this.Sex
p.NickName = this.NickName
p.HeadId = this.HeadId
p.Balance = this.Balance
p.Profile = this.Profile
return p
}

View File

@@ -0,0 +1,153 @@
package model
import (
"encoding/json"
"fmt"
"log/slog"
"slgserver/db"
"slgserver/net"
"slgserver/server/slgserver/proto"
"time"
"xorm.io/xorm"
)
/*******db 操作begin********/
var dbRAttrMgr *roleAttrDBMgr
func init() {
dbRAttrMgr = &roleAttrDBMgr{rattr: make(chan *RoleAttribute, 100)}
go dbRAttrMgr.running()
}
type roleAttrDBMgr struct {
rattr chan *RoleAttribute
}
func (this *roleAttrDBMgr) running() {
for true {
select {
case attr := <-this.rattr:
if attr.Id > 0 {
_, err := db.MasterDB.Table(attr).ID(attr.Id).Cols(
"parent_id", "collect_times", "last_collect_time", "pos_tags").Update(attr)
if err != nil {
slog.Warn("db error", "error", err)
}
} else {
slog.Warn("update role attr fail, because id <= 0")
}
}
}
}
func (this *roleAttrDBMgr) push(attr *RoleAttribute) {
this.rattr <- attr
}
/*******db 操作end********/
type RoleAttribute struct {
Id int `xorm:"id pk autoincr"`
RId int `xorm:"rid"`
UnionId int `xorm:"-"` //联盟id
ParentId int `xorm:"parent_id"` //上级id被沦陷
CollectTimes int8 `xorm:"collect_times"` //征收次数
LastCollectTime time.Time `xorm:"last_collect_time"` //最后征收的时间
PosTags string `xorm:"pos_tags"` //位置标记
PosTagArray []proto.PosTag `xorm:"-"`
}
func (this *RoleAttribute) TableName() string {
return "tb_role_attribute" + fmt.Sprintf("_%d", ServerId)
}
func (this *RoleAttribute) AfterSet(name string, cell xorm.Cell) {
if name == "pos_tags" {
this.PosTagArray = make([]proto.PosTag, 0)
if cell != nil {
data, ok := (*cell).([]uint8)
if ok {
json.Unmarshal(data, &this.PosTagArray)
slog.Debug("role pos tags loaded", "tags", this.PosTagArray)
}
}
}
}
func (this *RoleAttribute) beforeModify() {
if this.PosTagArray == nil {
this.PosTagArray = make([]proto.PosTag, 0)
}
data, _ := json.Marshal(this.PosTagArray)
this.PosTags = string(data)
}
func (this *RoleAttribute) BeforeInsert() {
this.beforeModify()
}
func (this *RoleAttribute) BeforeUpdate() {
this.beforeModify()
}
func (this *RoleAttribute) RemovePosTag(x, y int) {
tags := make([]proto.PosTag, 0)
for _, tag := range this.PosTagArray {
if tag.X != x || tag.Y != y {
tags = append(tags, tag)
}
}
this.PosTagArray = tags
}
func (this *RoleAttribute) AddPosTag(x, y int, name string) {
ok := true
for _, tag := range this.PosTagArray {
if tag.X == x && tag.Y == y {
ok = false
break
}
}
if ok {
this.PosTagArray = append(this.PosTagArray, proto.PosTag{X: x, Y: y, Name: name})
}
}
/* 推送同步 begin */
func (this *RoleAttribute) IsCellView() bool {
return false
}
func (this *RoleAttribute) IsCanView(rid, x, y int) bool {
return false
}
func (this *RoleAttribute) BelongToRId() []int {
return []int{this.RId}
}
func (this *RoleAttribute) PushMsgName() string {
return "roleAttr.push"
}
func (this *RoleAttribute) ToProto() interface{} {
return nil
}
func (this *RoleAttribute) Position() (int, int) {
return -1, -1
}
func (this *RoleAttribute) TPosition() (int, int) {
return -1, -1
}
func (this *RoleAttribute) Push() {
net.ConnMgr.Push(this)
}
/* 推送同步 end */
func (this *RoleAttribute) SyncExecute() {
dbRAttrMgr.push(this)
}

View File

@@ -0,0 +1,122 @@
package model
import (
"fmt"
"log/slog"
"slgserver/db"
"slgserver/net"
"slgserver/server/slgserver/proto"
)
type Yield struct {
Wood int
Iron int
Stone int
Grain int
Gold int
}
/*******db 操作begin********/
var dbRResMgr *roleResDBMgr
func init() {
dbRResMgr = &roleResDBMgr{ress: make(chan *RoleRes, 100)}
go dbRResMgr.running()
}
type roleResDBMgr struct {
ress chan *RoleRes
}
func (this *roleResDBMgr) running() {
for true {
select {
case res := <- this.ress:
if res.Id >0 {
_, err := db.MasterDB.Table(res).ID(res.Id).Cols(
"wood", "iron", "stone",
"grain", "gold", "decree").Update(res)
if err != nil{
slog.Warn("db error", "error", err)
}
}else{
slog.Warn("update role build fail, because id <= 0")
}
}
}
}
func (this *roleResDBMgr) push(res *RoleRes) {
this.ress <- res
}
/*******db 操作end********/
type RoleRes struct {
Id int `xorm:"id pk autoincr"`
RId int `xorm:"rid"`
Wood int `xorm:"wood"`
Iron int `xorm:"iron"`
Stone int `xorm:"stone"`
Grain int `xorm:"grain"`
Gold int `xorm:"gold"`
Decree int `xorm:"decree"` //令牌
}
func (this *RoleRes) TableName() string {
return "tb_role_res" + fmt.Sprintf("_%d", ServerId)
}
/* 推送同步 begin */
func (this *RoleRes) IsCellView() bool{
return false
}
func (this *RoleRes) IsCanView(rid, x, y int) bool{
return false
}
func (this *RoleRes) BelongToRId() []int{
return []int{this.RId}
}
func (this *RoleRes) PushMsgName() string{
return "roleRes.push"
}
func (this *RoleRes) ToProto() interface{}{
p := proto.RoleRes{}
p.Gold = this.Gold
p.Grain = this.Grain
p.Stone = this.Stone
p.Iron = this.Iron
p.Wood = this.Wood
p.Decree = this.Decree
y := GetYield(this.RId)
p.GoldYield = y.Gold
p.GrainYield = y.Grain
p.StoneYield = y.Stone
p.IronYield = y.Iron
p.WoodYield = y.Wood
p.DepotCapacity = GetDepotCapacity(this.RId)
return p
}
func (this *RoleRes) Position() (int, int){
return -1, -1
}
func (this *RoleRes) TPosition() (int, int){
return -1, -1
}
func (this *RoleRes) Push(){
net.ConnMgr.Push(this)
}
/* 推送同步 end */
func (this *RoleRes) SyncExecute() {
dbRResMgr.push(this)
this.Push()
}

View File

@@ -0,0 +1,178 @@
package model
import (
"encoding/json"
"fmt"
"log/slog"
"slgserver/db"
"slgserver/net"
"slgserver/server/slgserver/proto"
"slgserver/server/slgserver/static_conf/skill"
"xorm.io/xorm"
)
/*******db 操作begin********/
var dbSkillMgr *skillDBMgr
func init() {
dbSkillMgr = &skillDBMgr{skills: make(chan *Skill, 100)}
go dbSkillMgr.running()
}
type skillDBMgr struct {
skills chan *Skill
}
func (this*skillDBMgr) running() {
for true {
select {
case skill := <- this.skills:
if skill.Id >0 {
_, err := db.MasterDB.Table(skill).ID(skill.Id).Cols(
"cfgId", "belong_generals", "rid").Update(skill)
if err != nil{
slog.Warn("db error", "error", err)
}
}else{
db.MasterDB.Table(skill).InsertOne(skill)
}
}
}
}
func (this*skillDBMgr) push(skill *Skill) {
this.skills <- skill
}
/*******db 操作end********/
//军队
type Skill struct {
Id int `xorm:"id pk autoincr"`
RId int `xorm:"rid"`
CfgId int `xorm:"cfgId"`
BelongGenerals string `xorm:"belong_generals"`
Generals []int `xorm:"-"`
}
func NewSkill(rid int, cfgId int) *Skill{
return &Skill{
CfgId: cfgId,
RId: rid,
Generals: []int{},
BelongGenerals: "[]",
}
}
func (this *Skill) TableName() string {
return "tb_skill" + fmt.Sprintf("_%d", ServerId)
}
func (this *Skill) AfterSet(name string, cell xorm.Cell){
if name == "belong_generals"{
this.Generals = []int{}
if cell != nil{
gs, ok := (*cell).([]uint8)
if ok {
json.Unmarshal(gs, &this.BelongGenerals)
}
}
}
}
func (this *Skill) beforeModify() {
data, _ := json.Marshal(this.Generals)
this.BelongGenerals = string(data)
}
func (this *Skill) BeforeInsert() {
this.beforeModify()
}
func (this *Skill) BeforeUpdate() {
this.beforeModify()
}
/* 推送同步 begin */
func (this *Skill) IsCellView() bool{
return false
}
func (this *Skill) IsCanView(rid, x, y int) bool{
return false
}
func (this *Skill) BelongToRId() []int{
return []int{this.RId}
}
func (this *Skill) PushMsgName() string{
return "skill.push"
}
func (this *Skill) Position() (int, int){
return -1, -1
}
func (this *Skill) TPosition() (int, int){
return -1, -1
}
func (this *Skill) ToProto() interface{}{
p := proto.Skill{}
p.Id = this.Id
p.CfgId = this.CfgId
p.Generals = this.Generals
return p
}
func (this *Skill) Push(){
net.ConnMgr.Push(this)
}
/* 推送同步 end */
func (this *Skill) SyncExecute() {
dbSkillMgr.push(this)
this.Push()
}
func (this *Skill) Limit() int {
cfg, _ := skill.Skill.GetCfg(this.CfgId)
return cfg.Limit
}
func (this *Skill) IsInLimit() bool{
//fmt.Println("this.BelongGenerals", this.BelongGenerals)
return len(this.Generals) < this.Limit()
}
func (this *Skill) ArmyIsIn(armId int) bool {
cfg, _ := skill.Skill.GetCfg(this.CfgId)
for _, arm := range cfg.Arms {
if arm == armId{
return true
}
}
return false
}
func (this *Skill) UpSkill(gId int) {
this.Generals = append(this.Generals, gId)
data, _ := json.Marshal(this.Generals)
this.BelongGenerals = string(data)
}
func (this *Skill) DownSkill(gId int) {
gs := make([]int, 0)
for _, general := range this.Generals {
if gId != general {
gs = append(gs, general)
}
}
this.Generals = gs
data, _ := json.Marshal(this.Generals)
this.BelongGenerals = string(data)
}

View File

@@ -0,0 +1,16 @@
package model
var ArmyIsInView func(rid, x, y int) bool
var GetUnionId func(rid int) int
var GetUnionName func(unionId int) string
var GetRoleNickName func(rid int) string
var GetParentId func(rid int) int
var GetMainMembers func(unionId int) []int
var GetYield func(rid int) Yield
var GetDepotCapacity func(rid int) int
var GetCityCost func(cid int) int8
var GetMaxDurable func(cid int) int
var GetCityLv func(cid int) int8
var MapResTypeLevel func(x, y int) (bool, int8, int8)
var ServerId = 0

View File

@@ -0,0 +1,101 @@
package model
import (
"fmt"
"log/slog"
"slgserver/db"
"slgserver/net"
"slgserver/server/slgserver/proto"
"time"
)
type WarReport struct {
Id int `xorm:"id pk autoincr"`
AttackRid int `xorm:"a_rid"`
DefenseRid int `xorm:"d_rid"`
BegAttackArmy string `xorm:"b_a_army"`
BegDefenseArmy string `xorm:"b_d_army"`
EndAttackArmy string `xorm:"e_a_army"`
EndDefenseArmy string `xorm:"e_d_army"`
BegAttackGeneral string `xorm:"b_a_general"`
BegDefenseGeneral string `xorm:"b_d_general"`
EndAttackGeneral string `xorm:"e_a_general"`
EndDefenseGeneral string `xorm:"e_d_general"`
Result int `xorm:"result"` //0失败1打平2胜利
Rounds string `xorm:"rounds"` //回合
AttackIsRead bool `xorm:"a_is_read"`
DefenseIsRead bool `xorm:"d_is_read"`
DestroyDurable int `xorm:"destroy"`
Occupy int `xorm:"occupy"`
X int `xorm:"x"`
Y int `xorm:"y"`
CTime time.Time `xorm:"ctime"`
}
func (this *WarReport) TableName() string {
return "tb_war_report" + fmt.Sprintf("_%d", ServerId)
}
/* 推送同步 begin */
func (this *WarReport) IsCellView() bool{
return false
}
func (this *WarReport) IsCanView(rid, x, y int) bool{
return false
}
func (this *WarReport) BelongToRId() []int{
return []int{this.AttackRid, this.DefenseRid}
}
func (this *WarReport) PushMsgName() string{
return "warReport.push"
}
func (this *WarReport) Position() (int, int){
return this.X, this.Y
}
func (this *WarReport) TPosition() (int, int){
return -1, -1
}
func (this *WarReport) ToProto() interface{}{
p := proto.WarReport{}
p.CTime = int(this.CTime.UnixNano() / 1e6)
p.Id = this.Id
p.AttackRid = this.AttackRid
p.DefenseRid = this.DefenseRid
p.BegAttackArmy = this.BegAttackArmy
p.BegDefenseArmy = this.BegDefenseArmy
p.EndAttackArmy = this.EndAttackArmy
p.EndDefenseArmy = this.EndDefenseArmy
p.BegAttackGeneral = this.BegAttackGeneral
p.BegDefenseGeneral = this.BegDefenseGeneral
p.EndAttackGeneral = this.EndAttackGeneral
p.EndDefenseGeneral = this.EndDefenseGeneral
p.Result = this.Result
p.Rounds = this.Rounds
p.AttackIsRead = this.AttackIsRead
p.DefenseIsRead = this.DefenseIsRead
p.DestroyDurable = this.DestroyDurable
p.Occupy = this.Occupy
p.X = this.X
p.X = this.X
return p
}
func (this *WarReport) Push(){
net.ConnMgr.Push(this)
}
/* 推送同步 end */
func (this *WarReport) SyncExecute() {
_, err := db.MasterDB.InsertOne(this)
if err != nil{
slog.Warn("db error", "error", err)
}
this.Push()
}

View File

@@ -0,0 +1,63 @@
package pos
import "sync"
var RPMgr = RolePosMgr{
posCaches: make(map[position]map[int]int),
ridCaches: make(map[int]position),
}
type position struct {
X int
Y int
}
type RolePosMgr struct {
mutex sync.RWMutex
posCaches map[position]map[int]int
ridCaches map[int]position
}
func (this *RolePosMgr) Push(x, y, rid int) {
this.mutex.Lock()
defer this.mutex.Unlock()
//旧的要删除
if r, ok := this.ridCaches[rid]; ok {
if r.X == x && r.Y == y{
return
}
if c, ok1 := this.posCaches[r]; ok1 {
delete(c, rid)
}
}
//新的写入
p := position{x, y}
_, ok := this.posCaches[p]
if ok == false {
this.posCaches[p] = make(map[int]int)
}
this.posCaches[p][rid] = rid
this.ridCaches[rid] = p
}
func (this *RolePosMgr) GetCellRoleIds(x, y, width, height int) []int{
this.mutex.RLock()
defer this.mutex.RUnlock()
l := make([]int, 0)
for i := x-width; i <= x+width; i++ {
for j := y-height; j <= y+height; j++ {
pos := position{i, j}
r, ok := this.posCaches[pos]
if ok {
for _, v := range r {
l = append(l, v)
}
}
}
}
return l
}

View File

@@ -0,0 +1,36 @@
package proto
type Facility struct {
Name string `json:"name"`
Level int8 `json:"level"`
Type int8 `json:"type"`
UpTime int64 `json:"up_time"` //升级的时间戳0表示该等级已经升级完成了
}
type FacilitiesReq struct {
CityId int `json:"cityId"`
}
type FacilitiesRsp struct {
CityId int `json:"cityId"`
Facilities []Facility `json:"facilities"`
}
type UpFacilityReq struct {
CityId int `json:"cityId"`
FType int8 `json:"fType"`
}
type UpFacilityRsp struct {
CityId int `json:"cityId"`
Facility Facility `json:"facility"`
RoleRes RoleRes `json:"role_res"`
}
type UpCityReq struct {
CityId int `json:"cityId"`
}
type UpCityRsp struct {
City MapRoleCity `json:"city"`
}

View File

@@ -0,0 +1,195 @@
package proto
const (
UnionChairman = 0 //盟主
UnionViceChairman = 1 //副盟主
UnionCommon = 2 //普通成员
)
const (
UnionUntreated = 0 //未处理
UnionRefuse = 1 //拒绝
UnionAdopt = 2 //通过
)
type Member struct {
RId int `json:"rid"`
Name string `json:"name"`
Title int8 `json:"title"`
X int `json:"x"`
Y int `json:"y"`
}
type Major struct {
RId int `json:"rid"`
Name string `json:"name"`
Title int8 `json:"title"`
}
type Union struct {
Id int `json:"id"` //联盟id
Name string `json:"name"` //联盟名字
Cnt int `json:"cnt"` //联盟人数
Notice string `json:"notice"` //公告
Major []Major `json:"major"` //联盟主要人物,盟主副盟主
}
type ApplyItem struct {
Id int `json:"id"`
RId int `json:"rid"`
NickName string `json:"nick_name"`
}
//创建联盟
type CreateReq struct {
Name string `json:"name"`
}
type CreateRsp struct {
Id int `json:"id"` //联盟id
Name string `json:"name"`
}
//联盟列表
type ListReq struct {
}
type ListRsp struct {
List []Union `json:"list"`
}
//申请加入联盟
type JoinReq struct {
Id int `json:"id"` //联盟id
}
type JoinRsp struct {
}
//联盟成员
type MemberReq struct {
Id int `json:"id"` //联盟id
}
type MemberRsp struct {
Id int `json:"id"` //联盟id
Members []Member `json:"Members"`
}
//获取申请列表
type ApplyReq struct {
Id int `json:"id"`
}
type ApplyRsp struct {
Id int `json:"id"`
Applys []ApplyItem `json:"applys"`
}
//审核
type VerifyReq struct {
Id int `json:"id"` //申请操作的id
Decide int8 `json:"decide"` //1是拒绝2是通过
}
type VerifyRsp struct {
Id int `json:"id"` //申请操作的id
Decide int8 `json:"decide"` //1是拒绝2是通过
}
//退出
type ExitReq struct {
}
type ExitRsp struct {
}
//解散
type DismissReq struct {
}
type DismissRsp struct {
}
type NoticeReq struct {
Id int `json:"id"` //联盟id
}
type NoticeRsp struct {
Text string `json:"text"`
}
//修改公告
type ModNoticeReq struct {
Text string `json:"text"`
}
type ModNoticeRsp struct {
Id int `json:"id"` //联盟id
Text string `json:"text"`
}
//踢人
type KickReq struct {
RId int `json:"rid"`
}
type KickRsp struct {
RId int `json:"rid"`
}
//任命
type AppointReq struct {
RId int `json:"rid"`
Title int `json:"title"` //职位0盟主、1副盟主、2普通成员
}
type AppointRsp struct {
RId int `json:"rid"`
Title int `json:"title"` //职位0盟主、1副盟主、2普通成员
}
//禅让(盟主副盟主)
type AbdicateReq struct {
RId int `json:"rid"` //禅让给的rid
}
type AbdicateRsp struct {
}
//联盟信息
type InfoReq struct {
Id int `json:"id"` //联盟id
}
type InfoRsp struct {
Id int `json:"id"` //联盟id
Info Union `json:"info"`
}
type UnionLog struct {
OPRId int `json:"op_rid"`
TargetId int `json:"target_id"`
State int8 `json:"state"`
Des string `json:"des"`
Ctime int64 `json:"ctime"`
}
type LogReq struct {
}
type LogRsp struct {
Logs []UnionLog `json:"logs"`
}

View File

@@ -0,0 +1,207 @@
package proto
type GSkill struct {
Id int `json:"id"`
Lv int `json:"lv"`
CfgId int `json:"cfgId"`
}
type General struct {
Id int `json:"id"`
CfgId int `json:"cfgId"`
PhysicalPower int `json:"physical_power"`
Order int8 `json:"order"`
Level int8 `json:"level"`
Exp int `json:"exp"`
CityId int `json:"cityId"`
CurArms int `json:"curArms"`
HasPrPoint int `json:"hasPrPoint"`
UsePrPoint int `json:"usePrPoint"`
AttackDis int `json:"attack_distance"`
ForceAdded int `json:"force_added"`
StrategyAdded int `json:"strategy_added"`
DefenseAdded int `json:"defense_added"`
SpeedAdded int `json:"speed_added"`
DestroyAdded int `json:"destroy_added"`
StarLv int8 `json:"star_lv"`
Star int8 `json:"star"`
ParentId int `json:"parentId"`
Skills []*GSkill `json:"skills"`
State int8 `json:"state"`
}
func (this*General) ToArray()[]int {
r := make([]int, 0)
r = append(r, this.Id)
r = append(r, this.CfgId)
r = append(r, this.PhysicalPower)
r = append(r, int(this.Order))
r = append(r, int(this.Level))
r = append(r, this.Exp)
r = append(r, this.CityId)
r = append(r, this.CurArms)
r = append(r, this.HasPrPoint)
r = append(r, this.UsePrPoint)
r = append(r, this.AttackDis)
r = append(r, this.ForceAdded)
r = append(r, this.StrategyAdded)
r = append(r, this.SpeedAdded)
r = append(r, this.DefenseAdded)
r = append(r, this.DestroyAdded)
r = append(r, int(this.StarLv))
r = append(r, int(this.Star))
return r
}
type MyGeneralReq struct {
}
type MyGeneralRsp struct {
Generals []General `json:"generals"`
}
type ArmyListReq struct {
CityId int `json:"cityId"`
}
type ArmyListRsp struct {
CityId int `json:"cityId"`
Armys []Army `json:"armys"`
}
type ArmyOneReq struct {
CityId int `json:"cityId"`
Order int8 `json:"order"`
}
type ArmyOneRsp struct {
Army Army `json:"army"`
}
type Army struct {
Id int `json:"id"`
CityId int `json:"cityId"`
UnionId int `json:"union_id"` //联盟id
Order int8 `json:"order"` //第几队1-5队
Generals []int `json:"generals"`
Soldiers []int `json:"soldiers"`
ConTimes []int64 `json:"con_times"`
ConCnts []int `json:"con_cnts"`
Cmd int8 `json:"cmd"`
State int8 `json:"state"` //状态:0:running,1:stop
FromX int `json:"from_x"`
FromY int `json:"from_y"`
ToX int `json:"to_x"`
ToY int `json:"to_y"`
Start int64 `json:"start"`//出征开始时间
End int64 `json:"end"`//出征结束时间
}
//配置武将
type DisposeReq struct {
CityId int `json:"cityId"` //城市id
GeneralId int `json:"generalId"` //将领id
Order int8 `json:"order"` //第几队1-5队
Position int `json:"position"` //位置,-1到2,-1是解除该武将上阵状态
}
type DisposeRsp struct {
Army Army `json:"army"`
}
//征兵
type ConscriptReq struct {
ArmyId int `json:"armyId"` //队伍id
Cnts []int `json:"cnts"` //征兵人数
}
type ConscriptRsp struct {
Army Army `json:"army"`
RoleRes RoleRes `json:"role_res"`
}
//派遣队伍
type AssignArmyReq struct {
ArmyId int `json:"armyId"` //队伍id
Cmd int8 `json:"cmd"` //命令0:空闲 1:攻击 2驻军 3:返回
X int `json:"x"`
Y int `json:"y"`
}
type AssignArmyRsp struct {
Army Army `json:"army"`
}
//抽卡
type DrawGeneralReq struct {
DrawTimes int `json:"drawTimes"` //抽卡次数
}
type DrawGeneralRsp struct {
Generals []General `json:"generals"`
}
//合成
type ComposeGeneralReq struct {
CompId int `json:"compId"`
GIds []int `json:"gIds"` //合成材料
}
type ComposeGeneralRsp struct {
Generals []General `json:"generals"`
}
//加点
type AddPrGeneralReq struct {
CompId int `json:"compId"`
ForceAdd int `json:"forceAdd"`
StrategyAdd int `json:"strategyAdd"`
DefenseAdd int `json:"defenseAdd"`
SpeedAdd int `json:"speedAdd"`
DestroyAdd int `json:"destroyAdd"`
}
type AddPrGeneralRsp struct {
Generals General `json:"general"`
}
type ConvertReq struct {
GIds []int `json:"gIds"`
}
type ConvertRsp struct {
GIds []int `json:"gIds"`
Gold int `json:"gold"`
AddGold int `json:"add_gold"`
}
type UpDownSkillReq struct {
GId int `json:"gId"` //武将id
CfgId int `json:"cfgId"` //技能配置id
Pos int `json:"pos"` //位置0-2
}
type UpDownSkillRsp struct {
GId int `json:"gId"` //武将id
CfgId int `json:"cfgId"` //技能配置id
Pos int `json:"pos"` //位置0-2
}
type LvSkillReq struct {
GId int `json:"gId"` //武将id
Pos int `json:"pos"` //位置0-2
}
type LvSkillRsp struct {
GId int `json:"gId"` //武将id
Pos int `json:"pos"` //位置0-2
}

View File

@@ -0,0 +1,29 @@
package proto
type CollectionReq struct {
}
type CollectionRsp struct {
Gold int `json:"gold"`
Limit int8 `json:"limit"`
CurTimes int8 `json:"cur_times"`
NextTime int64 `json:"next_time"`
}
type OpenCollectionReq struct {
}
type OpenCollectionRsp struct {
Limit int8 `json:"limit"`
CurTimes int8 `json:"cur_times"`
NextTime int64 `json:"next_time"`
}
type TransformReq struct {
From []int `json:"from"` //0 Wood 1 Iron 2 Stone 3 Grain
To []int `json:"to"` //0 Wood 1 Iron 2 Stone 3 Grain
}
type TransformRsp struct {
}

View File

@@ -0,0 +1,104 @@
package proto
type Conf struct {
Type int8 `json:"type"`
Level int8 `json:"level"`
Name string `json:"name"`
Wood int `json:"Wood"`
Iron int `json:"iron"`
Stone int `json:"stone"`
Grain int `json:"grain"`
Durable int `json:"durable"` //耐久
Defender int `json:"defender"` //防御等级
}
type ConfigReq struct {
}
type ConfigRsp struct {
Confs []Conf
}
type MapRoleBuild struct {
RId int `json:"rid"`
RNick string `json:"RNick"` //角色昵称
Name string `json:"name"`
UnionId int `json:"union_id"` //联盟id
UnionName string `json:"union_name"` //联盟名字
ParentId int `json:"parent_id"` //上级id
X int `json:"x"`
Y int `json:"y"`
Type int8 `json:"type"`
Level int8 `json:"level"`
OPLevel int8 `json:"op_level"`
CurDurable int `json:"cur_durable"`
MaxDurable int `json:"max_durable"`
Defender int `json:"defender"`
OccupyTime int64 `json:"occupy_time"`
EndTime int64 `json:"end_time"` //建造完的时间
GiveUpTime int64 `json:"giveUp_time"` //领地到了这个时间会被放弃
}
type ScanReq struct {
X int `json:"x"`
Y int `json:"y"`
}
type ScanRsp struct {
MRBuilds []MapRoleBuild `json:"mr_builds"` //角色建筑,包含被占领的基础建筑
MCBuilds []MapRoleCity `json:"mc_builds"` //角色城市
Armys []Army `json:"armys"` //军队
}
type ScanBlockReq struct {
X int `json:"x"`
Y int `json:"y"`
Length int `json:"length"`
}
type GiveUpReq struct {
X int `json:"x"`
Y int `json:"y"`
}
type GiveUpRsp struct {
X int `json:"x"`
Y int `json:"y"`
}
type BuildReq struct {
X int `json:"x"`
Y int `json:"y"`
Type int8 `json:"type"`
}
type BuildRsp struct {
X int `json:"x"`
Y int `json:"y"`
Type int8 `json:"type"`
}
type UpBuildReq struct {
X int `json:"x"`
Y int `json:"y"`
}
type UpBuildRsp struct {
X int `json:"x"`
Y int `json:"y"`
Build MapRoleBuild `json:"build"`
}
type DelBuildReq struct {
X int `json:"x"`
Y int `json:"y"`
}
type DelBuildRsp struct {
X int `json:"x"`
Y int `json:"y"`
Build MapRoleBuild `json:"build"`
}

View File

@@ -0,0 +1,154 @@
package proto
type Role struct {
RId int `json:"rid"`
UId int `json:"uid"`
NickName string `json:"nickName"`
Sex int8 `json:"sex"`
Balance int `json:"balance"`
HeadId int16 `json:"headId"`
Profile string `json:"profile"`
}
type RoleRes struct {
Wood int `json:"wood"`
Iron int `json:"iron"`
Stone int `json:"stone"`
Grain int `json:"grain"`
Gold int `json:"gold"`
Decree int `json:"decree"` //令牌
WoodYield int `json:"wood_yield"`
IronYield int `json:"iron_yield"`
StoneYield int `json:"stone_yield"`
GrainYield int `json:"grain_yield"`
GoldYield int `json:"gold_yield"`
DepotCapacity int `json:"depot_capacity"` //仓库容量
}
type CreateRoleReq struct {
UId int `json:"uid"`
NickName string `json:"nickName"`
Sex int8 `json:"sex"`
SId int `json:"sid"`
HeadId int16 `json:"headId"`
}
type CreateRoleRsp struct {
Role Role `json:"role"`
}
type RoleListReq struct {
UId int `json:"uid"`
}
type RoleListRsp struct {
Roles []Role
}
type EnterServerReq struct {
Session string `json:"session"`
}
type EnterServerRsp struct {
Role Role `json:"role"`
RoleRes RoleRes `json:"role_res"`
Time int64 `json:"time"`
Token string `json:"token"`
}
type MapRoleCity struct {
CityId int `json:"cityId"`
RId int `json:"rid"`
Name string `json:"name"`
UnionId int `json:"union_id"` //联盟id
UnionName string `json:"union_name"` //联盟名字
ParentId int `json:"parent_id"` //上级id
X int `json:"x"`
Y int `json:"y"`
IsMain bool `json:"is_main"`
Level int8 `json:"level"`
CurDurable int `json:"cur_durable"`
MaxDurable int `json:"max_durable"`
OccupyTime int64 `json:"occupy_time"`
}
type MyCityReq struct {
}
type MyCityRsp struct {
Citys []MapRoleCity `json:"citys"`
}
type MyRoleResReq struct {
}
type MyRoleResRsp struct {
RoleRes RoleRes `json:"role_res"`
}
type MyRoleBuildReq struct {
}
type MyRoleBuildRsp struct {
MRBuilds []MapRoleBuild `json:"mr_builds"` //角色建筑,包含被占领的基础建筑
}
/*
建筑发生变化
*/
type RoleBuildStatePush struct {
MRBuild MapRoleBuild `json:"mr_build"` //角色建筑,包含被占领的基础建筑
}
type MyRolePropertyReq struct {
}
type MyRolePropertyRsp struct {
RoleRes RoleRes `json:"role_res"`
MRBuilds []MapRoleBuild `json:"mr_builds"` //角色建筑,包含被占领的基础建筑
Generals []General `json:"generals"`
Citys []MapRoleCity `json:"citys"`
Armys []Army `json:"armys"`
}
type UpPositionReq struct {
X int `json:"x"`
Y int `json:"y"`
}
type UpPositionRsp struct {
X int `json:"x"`
Y int `json:"y"`
}
type PosTag struct {
X int `json:"x"`
Y int `json:"y"`
Name string `json:"name"`
}
type PosTagListReq struct {
}
type PosTagListRsp struct {
PosTags []PosTag `json:"pos_tags"`
}
type PosTagReq struct {
Type int `json:"type"` //1是标记0是取消标记
X int `json:"x"`
Y int `json:"y"`
Name string `json:"name"`
}
type PosTagRsp struct {
Type int `json:"type"` //1是标记0是取消标记
X int `json:"x"`
Y int `json:"y"`
Name string `json:"name"`
}

View File

@@ -0,0 +1,16 @@
package proto
type Skill struct {
Id int `json:"id"`
CfgId int `json:"cfgId"`
Generals []int `json:"generals"`
}
type SkillListReq struct {
}
type SkillListRsp struct {
List []Skill `json:"list"`
}

View File

@@ -0,0 +1,45 @@
package proto
type WarReport struct {
Id int `json:"id"`
AttackRid int `json:"a_rid"`
DefenseRid int `json:"d_rid"`
BegAttackArmy string `json:"b_a_army"`
BegDefenseArmy string `json:"b_d_army"`
EndAttackArmy string `json:"e_a_army"`
EndDefenseArmy string `json:"e_d_army"`
BegAttackGeneral string `json:"b_a_general"`
BegDefenseGeneral string `json:"b_d_general"`
EndAttackGeneral string `json:"e_a_general"`
EndDefenseGeneral string `json:"e_d_general"`
Result int `json:"result"` //0失败1打平2胜利
Rounds string `json:"rounds"` //回合
AttackIsRead bool `json:"a_is_read"`
DefenseIsRead bool `json:"d_is_read"`
DestroyDurable int `json:"destroy"`
Occupy int `json:"occupy"`
X int `json:"x"`
Y int `json:"y"`
CTime int `json:"ctime"`
}
type WarReportPush struct {
List []WarReport `json:"list"`
}
type WarReportReq struct {
}
type WarReportRsp struct {
List []WarReport `json:"list"`
}
type WarReadReq struct {
Id uint `json:"id"` //0全部已读
}
type WarReadRsp struct {
Id uint `json:"id"`
}

View File

@@ -0,0 +1,65 @@
package run
import (
"slgserver/config"
"slgserver/db"
"slgserver/net"
"slgserver/server/slgserver/controller"
"slgserver/server/slgserver/logic"
"slgserver/server/slgserver/logic/mgr"
"slgserver/server/slgserver/model"
"slgserver/server/slgserver/static_conf"
"slgserver/server/slgserver/static_conf/facility"
"slgserver/server/slgserver/static_conf/general"
"slgserver/server/slgserver/static_conf/skill"
)
var MyRouter = &net.Router{}
func Init() {
db.TestDB()
facility.FConf.Load()
general.GenBasic.Load()
skill.Skill.Load()
general.General.Load()
static_conf.Basic.Load()
static_conf.MapBuildConf.Load()
static_conf.MapBCConf.Load()
serverId := config.GetInt("logic.server_id", 1)
model.ServerId = serverId
logic.BeforeInit()
mgr.NMMgr.Load()
//需要先加载联盟相关的信息
mgr.UnionMgr.Load()
mgr.RAttrMgr.Load()
mgr.RCMgr.Load()
mgr.RBMgr.Load()
mgr.RFMgr.Load()
mgr.RResMgr.Load()
mgr.SkillMgr.Load()
mgr.GMgr.Load()
mgr.AMgr.Load()
logic.Init()
logic.AfterInit()
//全部初始化完才注册路由,防止服务器还没启动就绪收到请求
initRouter()
}
func initRouter() {
controller.DefaultRole.InitRouter(MyRouter)
controller.DefaultMap.InitRouter(MyRouter)
controller.DefaultCity.InitRouter(MyRouter)
controller.DefaultGeneral.InitRouter(MyRouter)
controller.DefaultArmy.InitRouter(MyRouter)
controller.DefaultWar.InitRouter(MyRouter)
controller.DefaultCoalition.InitRouter(MyRouter)
controller.DefaultInterior.InitRouter(MyRouter)
controller.DefaultSkill.InitRouter(MyRouter)
}

View File

@@ -0,0 +1,119 @@
package static_conf
import (
"encoding/json"
"log/slog"
"os"
"path"
"slgserver/config"
)
var Basic basic
type conscript struct {
Des string `json:"des"`
CostWood int `json:"cost_wood"`
CostIron int `json:"cost_iron"`
CostStone int `json:"cost_stone"`
CostGrain int `json:"cost_grain"`
CostGold int `json:"cost_gold"`
CostTime int `json:"cost_time"` //每征一个兵需要花费时间
}
type general struct {
Des string `json:"des"`
PhysicalPowerLimit int `json:"physical_power_limit"` //体力上限
CostPhysicalPower int `json:"cost_physical_power"` //消耗体力
RecoveryPhysicalPower int `json:"recovery_physical_power"` //恢复体力
ReclamationTime int `json:"reclamation_time"` //屯田消耗时间,单位秒
ReclamationCost int `json:"reclamation_cost"` //屯田消耗政令
DrawGeneralCost int `json:"draw_general_cost"` //抽卡消耗金币
PrPoint int `json:"pr_point"` //合成一个武将或者的技能点
Limit int `json:"limit"` //武将数量上限
}
type role struct {
Des string `json:"des"`
Wood int `json:"wood"`
Iron int `json:"iron"`
Stone int `json:"stone"`
Grain int `json:"grain"`
Gold int `json:"gold"`
Decree int `json:"decree"`
WoodYield int `json:"wood_yield"`
IronYield int `json:"iron_yield"`
StoneYield int `json:"stone_yield"`
GrainYield int `json:"grain_yield"`
GoldYield int `json:"gold_yield"`
DepotCapacity int `json:"depot_capacity"` //仓库初始容量
BuildLimit int `json:"build_limit"` //野外建筑上限
RecoveryTime int `json:"recovery_time"`
DecreeLimit int `json:"decree_limit"` //令牌上限
CollectTimesLimit int8 `json:"collect_times_limit"` //每日征收次数上限
CollectInterval int `json:"collect_interval"` //征收间隔
PosTagLimit int8 `json:"pos_tag_limit"` //位置标签上限
}
type city struct {
Des string `json:"des"`
Cost int8 `json:"cost"`
Durable int `json:"durable"`
RecoveryTime int `json:"recovery_time"`
TransformRate int `json:"transform_rate"`
}
type build struct {
Des string `json:"des"`
WarFree int64 `json:"war_free"` //免战时间,单位秒
GiveUpTime int64 `json:"giveUp_time"` //建筑放弃时间
FortressLimit int `json:"fortress_limit"` //要塞上限
}
type npcLevel struct {
Soilders int `json:"soilders"`
}
type npc struct {
Des string `json:"des"`
Levels []npcLevel `json:"levels"`
}
type union struct {
Des string `json:"des"`
MemberLimit int `json:"member_limit"`
}
type basic struct {
ConScript conscript `json:"conscript"`
General general `json:"general"`
Role role `json:"role"`
City city `json:"city"`
Npc npc `json:"npc"`
Union union `json:"union"`
Build build `json:"build"`
}
func (this *basic) Load() {
jsonDir := config.GetPath("logic.json_data", "data/conf/json/")
fileName := path.Join(jsonDir, "basic.json")
jdata, err := os.ReadFile(fileName)
if err != nil {
slog.Error("basic load file error", "error", err, "file", fileName)
os.Exit(0)
}
json.Unmarshal(jdata, this)
slog.Debug("basic config loaded")
}
func (this *basic) GetNPC(level int8) (*npcLevel, bool) {
if level <= 0 {
return nil, false
}
if len(this.Npc.Levels) >= int(level) {
return &this.Npc.Levels[level-1], true
}
return nil, false
}

View File

@@ -0,0 +1,58 @@
package facility
import (
"encoding/json"
"log/slog"
"os"
)
type conditions struct {
Type int `json:"type"`
Level int `json:"level"`
}
type facility struct {
Title string `json:"title"`
Des string `json:"des"`
Name string `json:"name"`
Type int8 `json:"type"`
Additions []int8 `json:"additions"`
Conditions []conditions `json:"conditions"`
Levels []fLevel `json:"levels"`
}
type NeedRes struct {
Decree int `json:"decree"`
Grain int `json:"grain"`
Wood int `json:"wood"`
Iron int `json:"iron"`
Stone int `json:"stone"`
Gold int `json:"gold"`
}
type fLevel struct {
Level int `json:"level"`
Values []int `json:"values"`
Need NeedRes `json:"need"`
Time int `json:"time"` //升级需要的时间
}
func NewFacility(jsonName string) *facility {
f := &facility{}
f.load(jsonName)
return f
}
func (this *facility) load(jsonName string) {
jdata, err := os.ReadFile(jsonName)
if err != nil {
slog.Error("facility load file error",
"error", err, "file", jsonName)
os.Exit(0)
}
json.Unmarshal(jdata, this)
slog.Debug("facility file loaded", "name", this.Name)
}

View File

@@ -0,0 +1,31 @@
package facility
const (
TypeDurable = 1 //耐久
TypeCost = 2
TypeArmyTeams = 3 //队伍数量
TypeSpeed = 4 //速度
TypeDefense = 5 //防御
TypeStrategy = 6 //谋略
TypeForce = 7 //攻击武力
TypeConscriptTime = 8 //征兵时间
TypeReserveLimit = 9 //预备役上限
TypeUnkonw = 10
TypeHanAddition = 11
TypeQunAddition = 12
TypeWeiAddition = 13
TypeShuAddition = 14
TypeWuAddition = 15
TypeDealTaxRate = 16//交易税率
TypeWood = 17
TypeIron = 18
TypeGrain = 19
TypeStone = 20
TypeTax = 21//税收
TypeExtendTimes = 22//扩建次数
TypeWarehouseLimit = 23//仓库容量
TypeSoldierLimit = 24//带兵数量
TypeVanguardLimit = 25//前锋数量
)

View File

@@ -0,0 +1,134 @@
package facility
import (
"encoding/json"
"log/slog"
"os"
"path"
"slgserver/config"
)
const (
Main = 0 //主城
JiaoChang = 13 //校场
TongShuaiTing = 14 //统帅厅
JiShi = 15 //集市
MBS = 16 //募兵所
)
var FConf facilityConf
type conf struct {
Name string
Type int8
}
type facilityConf struct {
Title string `json:"title"`
List []conf `json:"list"`
facilitys map[int8]*facility
}
func (this *facilityConf) Load() {
this.facilitys = make(map[int8]*facility, 0)
jsonDir := config.GetPath("logic.json_data", "data/conf/json/")
fileName := path.Join(jsonDir, "facility", "facility.json")
jdata, err := os.ReadFile(fileName)
if err != nil {
slog.Error("facilityConf load file error",
"error", err,
"file", fileName)
os.Exit(0)
}
json.Unmarshal(jdata, this)
fdir := path.Join(jsonDir, "facility")
files, err := os.ReadDir(fdir)
if err != nil {
return
}
for _, file := range files {
if file.IsDir() {
continue
} else {
if file.Name() == "facility.json" || file.Name() == "facility_addition.json" {
continue
}
fileName := path.Join(fdir, file.Name())
f := NewFacility(fileName)
this.facilitys[f.Type] = f
}
}
slog.Debug("facility config loaded", "count", len(this.facilitys))
}
func (this *facilityConf) MaxLevel(fType int8) int8 {
f, ok := this.facilitys[fType]
if ok {
return int8(len(f.Levels))
} else {
return 0
}
}
func (this *facilityConf) Need(fType int8, level int8) (*NeedRes, bool) {
if level <= 0 {
return nil, false
}
f, ok := this.facilitys[fType]
if ok {
if int8(len(f.Levels)) >= level {
return &f.Levels[level-1].Need, true
} else {
return nil, false
}
} else {
return nil, false
}
}
// 升级需要的时间
func (this *facilityConf) CostTime(fType int8, level int8) int {
if level <= 0 {
return 0
}
f, ok := this.facilitys[fType]
if ok {
if int8(len(f.Levels)) >= level {
return f.Levels[level-1].Time - 2 //比客户端快2s保证客户端倒计时完一定是升级成功了
} else {
return 0
}
} else {
return 0
}
}
func (this *facilityConf) GetValues(fType int8, level int8) []int {
if level <= 0 {
return []int{}
}
f, ok := this.facilitys[fType]
if ok {
if int8(len(f.Levels)) >= level {
return f.Levels[level-1].Values
} else {
return []int{}
}
} else {
return []int{}
}
}
func (this *facilityConf) GetAdditions(fType int8) []int8 {
f, ok := this.facilitys[fType]
if ok {
return f.Additions
} else {
return []int8{}
}
}

View File

@@ -0,0 +1,85 @@
package general
import (
"encoding/json"
"log/slog"
"math/rand"
"os"
"path"
"slgserver/config"
"time"
)
var General general
type g struct {
Name string `json:"name"`
CfgId int `json:"cfgId"`
Force int `json:"force"`
Strategy int `json:"strategy"`
Defense int `json:"defense"`
Speed int `json:"speed"`
Destroy int `json:"destroy"`
ForceGrow int `json:"force_grow"`
StrategyGrow int `json:"strategy_grow"`
DefenseGrow int `json:"defense_grow"`
SpeedGrow int `json:"speed_grow"`
DestroyGrow int `json:"destroy_grow"`
Cost int8 `json:"cost"`
Probability int `json:"probability"`
Star int8 `json:"star"`
Arms []int `json:"arms"`
Camp int8 `json:"camp"`
}
type general struct {
Title string `json:"title"`
GArr []g `json:"list"`
GMap map[int]g
totalProbability int
}
func (this *general) Load() {
jsonDir := config.GetPath("logic.json_data", "data/conf/json/")
fileName := path.Join(jsonDir, "general", "general.json")
jdata, err := os.ReadFile(fileName)
if err != nil {
slog.Error("general load file error",
"error", err,
"file", fileName)
os.Exit(0)
}
this.totalProbability = 0
json.Unmarshal(jdata, this)
this.GMap = make(map[int]g)
for _, v := range this.GArr {
this.GMap[v.CfgId] = v
this.totalProbability += v.Probability
}
slog.Debug("general config loaded", "count", len(this.GArr))
}
func (this *general) Cost(cfgId int) int8 {
c, ok := this.GMap[cfgId]
if ok {
return c.Cost
} else {
return 0
}
}
func (this *general) Draw() int {
rand.Seed(time.Now().UnixNano())
rate := rand.Intn(this.totalProbability)
cur := 0
for _, g := range this.GArr {
if rate >= cur && rate < cur+g.Probability {
return g.CfgId
}
cur += g.Probability
}
return 0
}

View File

@@ -0,0 +1,67 @@
package general
import (
"encoding/json"
"log/slog"
"os"
"path"
"slgserver/config"
)
var GenArms Arms
type gArmsCondition struct {
Level int `json:"level"`
StarLevel int `json:"star_lv"`
}
type gArmsCost struct {
Gold int `json:"gold"`
}
type gArms struct {
Id int `json:"id"`
Name string `json:"name"`
Condition gArmsCondition `json:"condition"`
ChangeCost gArmsCost `json:"change_cost"`
HarmRatio []int `json:"harm_ratio"`
}
type Arms struct {
Title string `json:"title"`
Arms []gArms `json:"arms"`
AMap map[int]gArms
}
func (this *Arms) Load() {
jsonDir := config.GetPath("logic.json_data", "data/conf/json/")
fileName := path.Join(jsonDir, "general", "general_arms.json")
jdata, err := os.ReadFile(fileName)
if err != nil {
slog.Error("general load file error", "error", err, "file", fileName)
os.Exit(0)
}
json.Unmarshal(jdata, this)
this.AMap = make(map[int]gArms)
for _, v := range this.Arms {
this.AMap[v.Id] = v
}
slog.Debug("general arms loaded", "count", len(this.Arms))
}
func (this *Arms) GetArm(id int) (gArms, error) {
return this.AMap[id], nil
}
func (this *Arms) GetHarmRatio(attId, defId int) float64 {
attArm, ok1 := this.AMap[attId]
_, ok2 := this.AMap[defId]
if ok1 && ok2 {
return float64(attArm.HarmRatio[defId-1]) / 100.0
} else {
return 1.0
}
}

View File

@@ -0,0 +1,67 @@
package general
import (
"encoding/json"
"errors"
"log/slog"
"os"
"path"
"slgserver/config"
)
var GenBasic Basic
type gLevel struct {
Level int8 `json:"level"`
Exp int `json:"exp"`
Soldiers int `json:"soldiers"`
}
type Basic struct {
Title string `json:"title"`
Levels []gLevel `json:"levels"`
}
func (this *Basic) Load() {
jsonDir := config.GetPath("logic.json_data", "data/conf/json/")
fileName := path.Join(jsonDir, "general", "general_basic.json")
jdata, err := os.ReadFile(fileName)
if err != nil {
slog.Error("general load file error", "error", err, "file", fileName)
os.Exit(0)
}
json.Unmarshal(jdata, this)
slog.Debug("general basic config loaded", "levels", len(this.Levels))
General.Load()
GenArms.Load()
}
func (this *Basic) GetLevel(l int8) (*gLevel, error) {
if l <= 0 {
return nil, errors.New("level error")
}
if int(l) <= len(this.Levels) {
return &this.Levels[l-1], nil
} else {
return nil, errors.New("level error")
}
}
func (this *Basic) ExpToLevel(exp int) (int8, int) {
var level int8 = 0
limitExp := this.Levels[len(this.Levels)-1].Exp
for _, v := range this.Levels {
if exp >= v.Exp && v.Level > level {
level = v.Level
}
}
if limitExp < exp {
return level, limitExp
} else {
return level, exp
}
}

View File

@@ -0,0 +1,64 @@
package static_conf
import (
"encoding/json"
"log/slog"
"os"
"path"
"slgserver/config"
)
// 地图资源配置
var MapBuildConf mapBuildConf
type cfg struct {
Type int8 `json:"type"`
Name string `json:"name"`
Level int8 `json:"level"`
Grain int `json:"grain"`
Wood int `json:"wood"`
Iron int `json:"iron"`
Stone int `json:"stone"`
Durable int `json:"durable"`
Defender int `json:"defender"`
}
type mapBuildConf struct {
Title string `json:"title"`
Cfg []cfg `json:"cfg"`
cfgMap map[int8][]cfg
}
func (this *mapBuildConf) Load() {
jsonDir := config.GetPath("logic.json_data", "data/conf/json/")
fileName := path.Join(jsonDir, "map_build.json")
jdata, err := os.ReadFile(fileName)
if err != nil {
slog.Error("mapBuildConf load file error", "error", err, "file", fileName)
os.Exit(0)
}
json.Unmarshal(jdata, this)
this.cfgMap = make(map[int8][]cfg)
for _, v := range this.Cfg {
if _, ok := this.cfgMap[v.Type]; ok == false {
this.cfgMap[v.Type] = make([]cfg, 0)
}
this.cfgMap[v.Type] = append(this.cfgMap[v.Type], v)
}
slog.Debug("map build config loaded", "types", len(this.cfgMap))
}
func (this *mapBuildConf) BuildConfig(cfgType int8, level int8) (*cfg, bool) {
if c, ok := this.cfgMap[cfgType]; ok {
for _, v := range c {
if v.Level == level {
return &v, true
}
}
}
return nil, false
}

View File

@@ -0,0 +1,94 @@
package static_conf
import (
"encoding/json"
"log/slog"
"os"
"path"
"slgserver/config"
"slgserver/server/slgserver/static_conf/facility"
)
// 地图资源配置
var MapBCConf mapBuildCustomConf
type level struct {
Level int8 `json:"level"`
Time int `json:"time"` //升级需要的时间
Durable int `json:"durable"`
Defender int `json:"defender"`
Need facility.NeedRes `json:"need"`
Result result `json:"result"`
}
type customConf struct {
Type int8 `json:"type"`
Name string `json:"name"`
Levels []level `json:"levels"`
}
type result struct {
ArmyCnt int `json:"army_cnt"`
}
type BCLevelCfg struct {
level
Type int8 `json:"type"`
Name string `json:"name"`
}
type mapBuildCustomConf struct {
Title string `json:"title"`
Cfg []customConf `json:"cfg"`
cfgMap map[int8]customConf
}
func (this *mapBuildCustomConf) Load() {
jsonDir := config.GetPath("logic.json_data", "data/conf/json/")
fileName := path.Join(jsonDir, "map_build_custom.json")
jdata, err := os.ReadFile(fileName)
if err != nil {
slog.Error("mapBuildCustomConf load file error",
"error", err,
"file", fileName)
os.Exit(0)
}
json.Unmarshal(jdata, this)
this.cfgMap = make(map[int8]customConf)
for _, v := range this.Cfg {
this.cfgMap[v.Type] = v
}
slog.Debug("map build custom config loaded", "types", len(this.cfgMap))
}
func (this *mapBuildCustomConf) BuildConfig(cfgType int8, level int8) (*BCLevelCfg, bool) {
if c, ok := this.cfgMap[cfgType]; ok {
if len(c.Levels) < int(level) {
return nil, false
}
lc := c.Levels[level-1]
cfg := BCLevelCfg{Type: cfgType, Name: c.Name}
cfg.Level = level
cfg.Need = lc.Need
cfg.Result = lc.Result
cfg.Durable = lc.Durable
cfg.Time = lc.Time
cfg.Result = lc.Result
return &cfg, true
}
return nil, false
}
// 可容纳队伍数量
func (this *mapBuildCustomConf) GetHoldArmyCnt(cfgType int8, level int8) int {
cfg, ok := this.BuildConfig(cfgType, level)
if ok == false {
return 0
}
return cfg.Result.ArmyCnt
}

View File

@@ -0,0 +1,73 @@
package skill
import (
"encoding/json"
"log/slog"
"os"
"path"
"slgserver/config"
)
var Skill skill
type skill struct {
skills []Conf
skillConfMap map[int]Conf
outline outline
}
func (this *skill) Load() {
this.skills = make([]Conf, 0)
this.skillConfMap = make(map[int]Conf)
jsonDir := config.GetPath("logic.json_data", "data/conf/json/")
fileName := path.Join(jsonDir, "skill", "skill_outline.json")
jdata, err := os.ReadFile(fileName)
if err != nil {
slog.Error("skill load file error", "error", err, "file", fileName)
os.Exit(0)
}
json.Unmarshal(jdata, &this.outline)
rd, err := os.ReadDir(path.Join(jsonDir, "skill"))
if err != nil {
slog.Error("skill readdir error", "error", err)
os.Exit(0)
}
for _, r := range rd {
if r.IsDir() {
this.readSkill(path.Join(jsonDir, "skill", r.Name()))
}
}
slog.Debug("skill configs loaded", "count", len(this.skills))
}
func (this *skill) readSkill(dir string) {
rd, err := os.ReadDir(dir)
if err == nil {
for _, r := range rd {
if r.IsDir() == false {
jdata, err := os.ReadFile(path.Join(dir, r.Name()))
if err == nil {
conf := Conf{}
if err := json.Unmarshal(jdata, &conf); err == nil {
this.skills = append(this.skills, conf)
this.skillConfMap[conf.CfgId] = conf
} else {
slog.Warn("Unmarshal skill error", "error", err,
"file", path.Join(dir, r.Name()))
}
}
}
}
}
}
func (this *skill) GetCfg(cfgId int) (Conf, bool) {
cfg, ok := this.skillConfMap[cfgId]
return cfg, ok
}

View File

@@ -0,0 +1,19 @@
package skill
type level struct {
Probability int `json:"probability"` //发动概率
EffectValue []int `json:"effect_value"` //效果值
EffectRound []int `json:"effect_round"` //效果持续回合数
}
type Conf struct {
CfgId int `json:"cfgId"`
Name string `json:"name"`
Trigger int `json:"trigger"` //发起类型
Target int `json:"target"` //目标类型
Des string `json:"des"`
Limit int `json:"limit"` //可以被武将装备上限
Arms []int `json:"arms"` //可以装备的兵种
IncludeEffect []int `json:"include_effect"` //技能包括的效果
Levels []level `json:"levels"`
}

View File

@@ -0,0 +1,39 @@
package skill
type trigger struct {
Type int `json:"type"`
Des string `json:"des"`
}
type triggerType struct {
Des string `json:"des"`
List [] trigger `json:"list"`
}
type effect struct {
Type int `json:"type"`
Des string `json:"des"`
IsRate bool `json:"isRate"`
}
type effectType struct {
Des string `json:"des"`
List [] effect `json:"list"`
}
type target struct {
Type int `json:"type"`
Des string `json:"des"`
}
type targetType struct {
Des string `json:"des"`
List [] target `json:"list"`
}
type outline struct {
TriggerType triggerType `json:"trigger_type"` //触发类型
EffectType effectType `json:"effect_type"` //效果类型
TargetType targetType `json:"target_type"` //目标类型
}