Browse Source

Merge pull request #644 from Timothy-Liuxf/feat/experimental/capi/go

feat(go):  experimantal capi framework for go
dev
Timothy Liu GitHub 2 years ago
parent
commit
c42a532a4c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1113 additions and 0 deletions
  1. +5
    -0
      experimental/CAPI/README.md
  2. +28
    -0
      experimental/CAPI/go/.gitignore
  3. +15
    -0
      experimental/CAPI/go/API/ai.go
  4. +80
    -0
      experimental/CAPI/go/API/core/api.go
  5. +97
    -0
      experimental/CAPI/go/API/core/communication.go
  6. +202
    -0
      experimental/CAPI/go/API/core/logic.go
  7. +13
    -0
      experimental/CAPI/go/API/go.mod
  8. +19
    -0
      experimental/CAPI/go/API/go.sum
  9. +18
    -0
      experimental/CAPI/go/API/main.go
  10. +3
    -0
      experimental/CAPI/go/API/shell/init.sh
  11. +14
    -0
      experimental/CAPI/go/API/thuai6/iai.go
  12. +15
    -0
      experimental/CAPI/go/API/thuai6/iapi.go
  13. +7
    -0
      experimental/CAPI/go/API/thuai6/state.go
  14. +55
    -0
      experimental/CAPI/go/API/thuai6/structures.go
  15. +38
    -0
      experimental/CAPI/go/API/thuai6/utils.go
  16. +15
    -0
      experimental/CAPI/go/README.md
  17. +9
    -0
      experimental/README.md
  18. +3
    -0
      experimental/dependency/README.md
  19. +204
    -0
      experimental/dependency/proto/Message2Clients.proto
  20. +74
    -0
      experimental/dependency/proto/Message2Server.proto
  21. +132
    -0
      experimental/dependency/proto/MessageType.proto
  22. +33
    -0
      experimental/dependency/proto/Services.proto
  23. +10
    -0
      experimental/dependency/proto/buf.gen.tag.yaml
  24. +14
    -0
      experimental/dependency/proto/buf.gen.yaml
  25. +10
    -0
      experimental/dependency/proto/go_output.sh

+ 5
- 0
experimental/CAPI/README.md View File

@@ -0,0 +1,5 @@
# experimental/CAPI

## 简介

实验性选手接口

+ 28
- 0
experimental/CAPI/go/.gitignore View File

@@ -0,0 +1,28 @@
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work

# Protocol Buffers generated code directory
/API/proto/

# Executables
/API/API
/API/API.exe

+ 15
- 0
experimental/CAPI/go/API/ai.go View File

@@ -0,0 +1,15 @@
package main

import (
thuai6 "API/thuai6"
)

const Asynchronous = false

func GetStudentType() []thuai6.StudentType {
return []thuai6.StudentType{thuai6.Athlete, thuai6.Teacher, thuai6.StraightAStudent, thuai6.Sunshine}
}

func GetTrickerType() thuai6.TrickerType {
return thuai6.Assassin
}

+ 80
- 0
experimental/CAPI/go/API/core/api.go View File

@@ -0,0 +1,80 @@
package core

import (
thuai6 "API/thuai6"
)

type ILogic interface {
Move(time int64, angle float64) bool
TryConnection() bool
GetStudentSelfInfo() *thuai6.Student
GetTrickerSelfInfo() *thuai6.Tricker
}

type StudentAPI struct {
logic ILogic
}

type TrickerAPI struct {
logic ILogic
}

func NewStudentAPI(logic ILogic) *StudentAPI {
return &StudentAPI{
logic: logic,
}
}

func NewTrickerAPI(logic ILogic) *TrickerAPI {
return &TrickerAPI{
logic: logic,
}
}

func (api *StudentAPI) Move(timeInMilliseconds int64, angleInRadian float64) <-chan bool {
res := make(chan bool, 1)
go func() {
res <- api.logic.Move(timeInMilliseconds, angleInRadian)
}()
return res
}

func (api *StudentAPI) GetSelfInfo() *thuai6.Student {
return api.logic.GetStudentSelfInfo()
}

func (api *StudentAPI) StartTimer() {
// Nothing
}

func (api *StudentAPI) EndTimer() {
// Nothing
}

func (api *StudentAPI) Play(ai thuai6.IAI) {
ai.StudentPlay(api)
}

func (api *TrickerAPI) Move(timeInMilliseconds int64, angleInRadian float64) <-chan bool {
res := make(chan bool, 1)
go func() {
res <- api.logic.Move(timeInMilliseconds, angleInRadian)
}()
return res
}

func (api *TrickerAPI) GetSelfInfo() *thuai6.Tricker {
return api.logic.GetTrickerSelfInfo()
}

func (api *TrickerAPI) StartTimer() {
// Nothing
}

func (api *TrickerAPI) EndTimer() {
// Nothing
}

func (api *TrickerAPI) Play(ai thuai6.IAI) {
ai.TrickerPlay(api)
}

+ 97
- 0
experimental/CAPI/go/API/core/communication.go View File

@@ -0,0 +1,97 @@
package core

import (
pb "API/proto"
thuai6 "API/thuai6"
"context"
"sync"

"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)

type Communication struct {
stub pb.AvailableServiceClient
messageToClient *pb.MessageToClient
haveNewMessage bool
mtxMessage sync.Mutex
cvMessage *sync.Cond
}

func NewCommunication(ip string, port string) (*Communication, error) {
addr := ip + ":" + port
conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, err
}
stub := pb.NewAvailableServiceClient(conn)
comm := &Communication{stub: stub, messageToClient: nil, haveNewMessage: false, mtxMessage: sync.Mutex{}}
comm.cvMessage = sync.NewCond(&comm.mtxMessage)
return comm, nil
}

func (self *Communication) TryConnection(playerID int64) bool {
res, err := self.stub.TryConnection(context.Background(), &pb.IDMsg{PlayerId: playerID})
if err != nil {
// TODO: do loggings
return false
}
return res.GetActSuccess()
}

func (self *Communication) AddPlayer(playerID int64, playerType thuai6.PlayerType, studentType thuai6.StudentType, trickerType thuai6.TrickerType) {
var playerMsg pb.PlayerMsg
playerMsg.PlayerId = playerID
playerMsg.PlayerType = thuai6.PlayerTypeToProto[playerType]
if playerType == thuai6.StudentPlayer {
playerMsg.JobType = &pb.PlayerMsg_StudentType{StudentType: thuai6.StudentTypeToProto[studentType]}
} else if playerType == thuai6.TrickerPlayer {
playerMsg.JobType = &pb.PlayerMsg_TrickerType{TrickerType: thuai6.TrickerTypeToProto[trickerType]}
} else {
// TODO: Report ERROR
}

go func() {
msgReader, err := self.stub.AddPlayer(context.Background(), &playerMsg)
if err != nil {
// TODO: Report ERROR
}
for {
msg, err := msgReader.Recv()
if err != nil {
break
}

func() {
self.mtxMessage.Lock()
defer self.mtxMessage.Unlock()
self.messageToClient = msg
self.haveNewMessage = true
self.cvMessage.Signal()
}()
}
}()
}

func (self *Communication) Move(time int64, angle float64, playerID int64) bool {
res, err := self.stub.Move(context.Background(), &pb.MoveMsg{
TimeInMilliseconds: time,
Angle: angle,
PlayerId: playerID,
})
if err != nil {
// TODO: do loggings
return false
}
return res.GetActSuccess()
}

func (self *Communication) GetMessageToClient() pb.MessageToClient {
self.mtxMessage.Lock()
defer self.mtxMessage.Unlock()
for !self.haveNewMessage {
self.cvMessage.Wait()
}
self.haveNewMessage = false
return *self.messageToClient
}

+ 202
- 0
experimental/CAPI/go/API/core/logic.go View File

@@ -0,0 +1,202 @@
package core

import (
"errors"
"sync"
"sync/atomic"

main "API"
pb "API/proto"
thuai6 "API/thuai6"
)

type Logic struct {
communication *Communication
playerType thuai6.PlayerType
playerID int64
studentType thuai6.StudentType
trickerType thuai6.TrickerType
timer thuai6.IGameTimer
mtxAI sync.Mutex
mtxState sync.Mutex
mtxBuffer sync.Mutex
cvBuffer *sync.Cond
cvAI *sync.Cond
state [2]thuai6.State
currentState *thuai6.State
bufferState *thuai6.State
counterState int32
counterBuffer int32
gameState thuai6.GameState
aiStart bool
bufferUpdated bool
aiLoop int32
freshed int32
}

func NewLogic(playerType thuai6.PlayerType, id int64, tricker thuai6.TrickerType, student thuai6.StudentType) *Logic {
logic := &Logic{
communication: nil,
playerType: playerType,
playerID: id,
studentType: student,
trickerType: tricker,
timer: nil,
mtxAI: sync.Mutex{},
mtxState: sync.Mutex{},
mtxBuffer: sync.Mutex{},
cvBuffer: nil,
cvAI: nil,
state: [2]thuai6.State{},
counterState: 0,
counterBuffer: 0,
gameState: thuai6.NullGameState,
aiStart: false,
bufferUpdated: true,
aiLoop: 1,
freshed: 0,
}
logic.currentState = &logic.state[0]
logic.bufferState = &logic.state[1]
logic.cvBuffer = sync.NewCond(&logic.mtxBuffer)
logic.cvAI = sync.NewCond(&logic.mtxAI)
return logic
}

func (logic *Logic) GetStudentSelfInfo() *thuai6.Student {
logic.mtxState.Lock()
defer logic.mtxState.Unlock()
return logic.currentState.StudentSelf
}

func (logic *Logic) GetTrickerSelfInfo() *thuai6.Tricker {
logic.mtxState.Lock()
defer logic.mtxState.Unlock()
return logic.currentState.TrickerSelf
}

func (logic *Logic) Move(time int64, angle float64) bool {
return logic.communication.Move(time, angle, logic.playerID)
}

func (logic *Logic) TryConnection() bool {
return logic.communication.TryConnection(logic.playerID)
}

func (logic *Logic) Wait() {
atomic.StoreInt32(&logic.freshed, 0)
logic.mtxBuffer.Lock()
defer logic.mtxBuffer.Unlock()
for atomic.LoadInt32(&logic.freshed) == 0 {
logic.cvBuffer.Wait()
}
}

func (logic *Logic) Update() {
if main.Asynchronous == false {
logic.mtxBuffer.Lock()
defer logic.mtxBuffer.Unlock()
for logic.bufferUpdated == false {
logic.cvBuffer.Wait()
}
// Go 的 defer 是函数推出时执行而非 block 退出时执行,故包装一层 func
func() {
logic.mtxState.Lock()
defer logic.mtxState.Unlock()
var tmpState = logic.currentState
logic.currentState = logic.bufferState
logic.bufferState = tmpState
logic.counterState = logic.counterBuffer
}()
logic.bufferUpdated = false
}
}

func (logic *Logic) ProcessMessage() <-chan int {
endChan := make(chan int, 1)
go func() {
logic.communication.AddPlayer(logic.playerID, logic.playerType, logic.studentType, logic.trickerType)
for logic.gameState != thuai6.GameEnd {
clientMsg := logic.communication.GetMessageToClient()
logic.gameState = thuai6.GameStateToTHUAI6[clientMsg.GameState]
switch logic.gameState {
case thuai6.GameStart:
playerGUIDs := make([]int64, 0)
for _, obj := range clientMsg.ObjMessage {
switch obj.MessageOfObj.(type) {
case *(pb.MessageOfObj_StudentMessage):
playerGUIDs = append(playerGUIDs, obj.GetStudentMessage().GetGuid())
}
}
for _, obj := range clientMsg.ObjMessage {
switch obj.MessageOfObj.(type) {
case *(pb.MessageOfObj_TrickerMessage):
playerGUIDs = append(playerGUIDs, obj.GetTrickerMessage().GetGuid())
}
}
logic.currentState.Guids = playerGUIDs
logic.bufferState.Guids = playerGUIDs
// TODO: LoadBuffer
break
case thuai6.GameEnd:

}
}
// TODO: ProcessMessage
endChan <- 0
}()
return endChan
}

func (logic *Logic) Main(createAI thuai6.CreateAIFunc, ip string, port string) error {
comm, err := NewCommunication(ip, port)
if err != nil {
return err
}
logic.communication = comm

if logic.playerType == thuai6.StudentPlayer {
logic.timer = NewStudentAPI(logic)
} else if logic.playerType == thuai6.TrickerPlayer {
logic.timer = NewTrickerAPI(logic)
} else {
return errors.New("Invalid player type")
}

aiThread := func() {
// Go 的 defer 是函数推出时执行而非 block 退出时执行,故包装一层 func
func() {
logic.mtxAI.Lock()
defer logic.mtxAI.Unlock()
for logic.aiStart == false {
logic.cvAI.Wait()
}
}()
ai := createAI(logic.playerID)

for atomic.LoadInt32(&logic.aiLoop) != 0 {
if main.Asynchronous {
logic.Wait()
} else {
logic.Update()
}
logic.timer.StartTimer()
logic.timer.Play(ai)
logic.timer.EndTimer()
}
}

if logic.TryConnection() == false {
atomic.StoreInt32(&logic.aiLoop, 0)
return errors.New("Connection failed.")
}

aiEnd := make(chan int, 1)
go func() {
aiThread()
aiEnd <- 1
}()
<-logic.ProcessMessage()
<-aiEnd
return nil
}

+ 13
- 0
experimental/CAPI/go/API/go.mod View File

@@ -0,0 +1,13 @@
module API

go 1.18

require (
github.com/golang/protobuf v1.5.2 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/grpc v1.54.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
)

+ 19
- 0
experimental/CAPI/go/API/go.sum View File

@@ -0,0 +1,19 @@
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=

+ 18
- 0
experimental/CAPI/go/API/main.go View File

@@ -0,0 +1,18 @@
package main

import (
"fmt"
"log"
)

var ch = make(chan int, 1)

func Func() {
log.Println(0)
ch <- 1
log.Fatalln(1)
}

func main() {
fmt.Println("THUAI6")
}

+ 3
- 0
experimental/CAPI/go/API/shell/init.sh View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash

../../../dependency/proto/go_output.sh && go get

+ 14
- 0
experimental/CAPI/go/API/thuai6/iai.go View File

@@ -0,0 +1,14 @@
package thuai6

type IGameTimer interface {
StartTimer()
EndTimer()
Play(ai IAI)
}

type IAI interface {
StudentPlay(api IStudentAPI)
TrickerPlay(api ITrickerAPI)
}

type CreateAIFunc = func(playerID int64) IAI

+ 15
- 0
experimental/CAPI/go/API/thuai6/iapi.go View File

@@ -0,0 +1,15 @@
package thuai6

type IAPI interface {
Move(timeInMilliseconds int64, angleInRadian float64) <-chan bool
}

type IStudentAPI interface {
IAPI
GetSelfInfo() *Student
}

type ITrickerAPI interface {
IAPI
GetSelfInfo() *Tricker
}

+ 7
- 0
experimental/CAPI/go/API/thuai6/state.go View File

@@ -0,0 +1,7 @@
package thuai6

type State struct {
StudentSelf *Student
TrickerSelf *Tricker
Guids []int64
}

+ 55
- 0
experimental/CAPI/go/API/thuai6/structures.go View File

@@ -0,0 +1,55 @@
package thuai6

type GameState int8

const (
NullGameState GameState = 0
GameStart GameState = 1
GameRunning GameState = 2
GameEnd GameState = 3
)

type PlayerType int8

const (
NullPlayerType PlayerType = 0
StudentPlayer PlayerType = 1
TrickerPlayer PlayerType = 2
)

type StudentType int8

const (
NullStudentType StudentType = 0
Athlete StudentType = 1
Teacher StudentType = 2
StraightAStudent StudentType = 3
Robot StudentType = 4
TechOtaku StudentType = 5
Sunshine StudentType = 6
)

type TrickerType int8

const (
NullTrickerType TrickerType = 0
Assassin TrickerType = 1
Klee TrickerType = 2
ANoisyPerson TrickerType = 3
Idol TrickerType = 4
)

type Player struct {
x int32
y int32
}

type Student struct {
Player
determination int32
}

type Tricker struct {
Player
trickDesire float64
}

+ 38
- 0
experimental/CAPI/go/API/thuai6/utils.go View File

@@ -0,0 +1,38 @@
package thuai6

import (
pb "API/proto"
)

var (
PlayerTypeToProto map[PlayerType]pb.PlayerType = map[PlayerType]pb.PlayerType{
NullPlayerType: pb.PlayerType_NULL_PLAYER_TYPE,
StudentPlayer: pb.PlayerType_STUDENT_PLAYER,
TrickerPlayer: pb.PlayerType_TRICKER_PLAYER,
}

StudentTypeToProto map[StudentType]pb.StudentType = map[StudentType]pb.StudentType{
NullStudentType: pb.StudentType_NULL_STUDENT_TYPE,
Athlete: pb.StudentType_ATHLETE,
Teacher: pb.StudentType_TEACHER,
StraightAStudent: pb.StudentType_STRAIGHT_A_STUDENT,
Robot: pb.StudentType_ROBOT,
TechOtaku: pb.StudentType_TECH_OTAKU,
Sunshine: pb.StudentType_SUNSHINE,
}

TrickerTypeToProto map[TrickerType]pb.TrickerType = map[TrickerType]pb.TrickerType{
NullTrickerType: pb.TrickerType_NULL_TRICKER_TYPE,
Assassin: pb.TrickerType_ASSASSIN,
Klee: pb.TrickerType_KLEE,
ANoisyPerson: pb.TrickerType_A_NOISY_PERSON,
Idol: pb.TrickerType_IDOL,
}

GameStateToTHUAI6 map[pb.GameState]GameState = map[pb.GameState]GameState{
pb.GameState_NULL_GAME_STATE: NullGameState,
pb.GameState_GAME_START: GameStart,
pb.GameState_GAME_RUNNING: GameRunning,
pb.GameState_GAME_END: GameEnd,
}
)

+ 15
- 0
experimental/CAPI/go/README.md View File

@@ -0,0 +1,15 @@
# experimental/CAPI/go

## 简介

实验性选手 Go 接口

## 运行方法

**注意事项**:Visual Studio Code 的 Go 语言提示**必须**以 `main` package 所在的目录为根目录,否则可能无法进行正确的代码提示。因此以下操作的根目录均为 `/CPI/go/API/`

```bash
$ ./shell/init.sh
$ go build
$ ./API
```

+ 9
- 0
experimental/README.md View File

@@ -0,0 +1,9 @@
# experimental

## 简介

进行实验性功能的探索

## 注意事项

本文件夹内的文件采用某历史版本,与新近版本未必一致。

+ 3
- 0
experimental/dependency/README.md View File

@@ -0,0 +1,3 @@
# experimental/dependency

实验性依赖文件

+ 204
- 0
experimental/dependency/proto/Message2Clients.proto View File

@@ -0,0 +1,204 @@
// Message2Client
syntax = "proto3";
package protobuf;

import "MessageType.proto";

message MessageOfStudent
{
int32 x = 1;
int32 y = 2;
int32 speed = 3;
int32 determination = 4; // 剩余的学习毅力,相当于血量
int32 addiction = 5; // 沉迷程度,相当于淘汰进度
repeated double time_until_skill_available = 6;
PlaceType place = 7;
repeated PropType prop = 8;
PlayerState player_state = 9;
int64 guid = 10;
BulletType bullet_type = 12;
int32 learning_speed = 13; // 修理电机的速度
int32 treat_speed = 14; // 治疗的速度
int64 player_id = 15;
int32 view_range = 16; // 视野距离
int32 radius = 17; // 半径
double danger_alert = 19; // 危险警报,在捣蛋鬼靠近时会有预警
int32 score = 20;
int32 treat_progress = 21; // 治疗进度
int32 rescue_progress = 22; // 救援进度
StudentType student_type = 23;
double facing_direction = 24;
repeated StudentBuffType buff = 25;
}

message MessageOfTricker
{
int32 x = 1;
int32 y = 2;
int32 speed = 3;
repeated double time_until_skill_available = 5;
PlaceType place = 6;
repeated PropType prop = 7;
TrickerType tricker_type = 8;
int64 guid = 9;
int32 score = 10;
int64 player_id = 11;
int32 view_range = 12; // 视野距离
int32 radius = 13; // 半径
PlayerState player_state = 14;
double trick_desire = 15;//bgm
double class_volume = 16;//bgm
double facing_direction = 17;
BulletType bullet_type = 18;
repeated TrickerBuffType buff = 19;
}

message MessageOfBullet
{
BulletType type = 1;
int32 x = 2;
int32 y = 3;
double facing_direction = 4;
int64 guid = 5;
PlayerType team = 6;
PlaceType place = 7;
double bomb_range = 8;
int32 speed = 9;
}

message MessageOfBombedBullet //for Unity,直接继承自THUAI5
{
BulletType type = 1;
int32 x = 2;
int32 y = 3;
double facing_direction = 4;
int64 mapping_id = 5;
double bomb_range = 6;
}

message MessageOfProp // 可拾取道具的信息
{
PropType type = 1;
int32 x = 2;
int32 y = 3;
double facing_direction = 4;
int64 guid = 5;
PlaceType place = 6;
}


message MessageOfPickedProp //for Unity,直接继承自THUAI5
{
PropType type = 1;
int32 x = 2;
int32 y = 3;
double facing_direction = 4;
int64 mapping_id = 5;
}

message MessageOfClassroom
{
int32 x = 1;
int32 y = 2;
int32 progress = 3;
}

message MessageOfGate
{
int32 x = 1;
int32 y = 2;
int32 progress = 3;
}

message MessageOfHiddenGate
{
int32 x = 1;
int32 y = 2;
bool opened = 3;
}

message MessageOfDoor
{
int32 x = 1;
int32 y = 2;
bool is_open = 3;
int32 progress = 4;
}

message MessageOfChest
{
int32 x = 1;
int32 y = 2;
int32 progress = 3;
}

message MessageOfMap
{
message Row
{
repeated PlaceType col = 1;
}
repeated Row row = 2;
}

message MessageOfNews
{
string news = 1;
int64 from_id = 2;
int64 to_id = 3;
}

message MessageOfObj
{
oneof message_of_obj
{
MessageOfStudent student_message = 1;
MessageOfTricker tricker_message = 2;
MessageOfProp prop_message = 3;
MessageOfBullet bullet_message = 4;
MessageOfBombedBullet bombed_bullet_message = 5;
MessageOfClassroom classroom_message = 6;
MessageOfDoor door_message = 7;
MessageOfGate gate_message = 8;
MessageOfChest chest_message = 9;
MessageOfHiddenGate hidden_gate_message = 10;
MessageOfNews news_message = 11;
MessageOfMap map_message = 12;
}
}

message MessageOfAll
{
int32 game_time = 1;
int32 subject_finished = 2; // 完成的科目数
int32 student_graduated = 3; // 已经毕业的学生数
int32 student_quited = 4; // 已经退学的学生数
int32 student_score = 5;
int32 tricker_score = 6;
}

message MessageToClient
{
repeated MessageOfObj obj_message = 1;
GameState game_state = 2;
MessageOfAll all_message = 3;
}

message MoveRes // 如果打算设计撞墙保留平行速度分量,且需要返回值则可用这个(大概没啥用)
{
int64 actual_speed = 1;
double actual_angle = 2;
bool act_success = 3;
}

message BoolRes // 用于只需要判断执行操作是否成功的行为,如捡起道具、使用道具
{
bool act_success = 1;
}

// message MsgRes // 用于获取队友发来的消息
// {
// bool have_message = 1; // 是否有待接收的消息
// int64 from_player_id = 2;
// string message_received = 3;
// }

+ 74
- 0
experimental/dependency/proto/Message2Server.proto View File

@@ -0,0 +1,74 @@
// Message2Server
syntax = "proto3";
package protobuf;

import "MessageType.proto";

message PlayerMsg
{
int64 player_id = 1;
oneof job_type
{
StudentType student_type = 2;
TrickerType tricker_type = 3;
}
PlayerType player_type = 4;
}

message MoveMsg
{
int64 player_id = 1;
double angle = 2;
int64 time_in_milliseconds = 3;
}

message PropMsg
{
int64 player_id = 1;
PropType prop_type = 2;
}

message SendMsg
{
int64 player_id = 1;
int64 to_player_id = 2;
string message = 3;
}

message AttackMsg // 相当于攻击
{
int64 player_id = 1;
double angle = 2;
}

message IDMsg
{
int64 player_id = 1;
}

message TreatAndRescueMsg
{
int64 player_id = 1;
int64 to_player_id = 2;
}

message SkillMsg
{
int64 player_id = 1;
int32 skill_id = 2;
}

// 基本继承于THUAI5,为了使发送的信息尽可能不被浪费,暂定不发这类大包。
// message MessageToServer
// {
// MessageType messageType = 1;
// int64 playerID = 2; // 消息发送者的playerID
// PlayerType playerType = 3;
// HumanType humanType= 4;
// TrickerType trickerType = 5;
// double angle = 6; // messageType为Move, Attack时的角度
// PropType propType = 7; // messageType为PickProp时要捡起的道具类型,防止多个道具堆叠时出现问题
// int64 timeInMilliseconds = 8;//时间参数
// int64 ToPlayerID = 9; // messageType为Send时要发送的对象的ID
// string message = 10; // messageType为Send时发送的消息内容
// }

+ 132
- 0
experimental/dependency/proto/MessageType.proto View File

@@ -0,0 +1,132 @@
// MessageType
syntax = "proto3";
package protobuf;

enum BulletType
{
NULL_BULLET_TYPE = 0;
FLYING_KNIFE = 1;
COMMON_ATTACK_OF_TRICKER = 2;
BOMB_BOMB = 3;
JUMPY_DUMPTY = 4;
ATOM_BOMB = 5;
}

enum PlaceType // 地图中的所有物件类型
{
NULL_PLACE_TYPE = 0;
// 地图情况,其中Gate是总体的大门,HiddenGate是地窖
LAND = 1;
WALL = 2;
GRASS = 3;
CLASSROOM = 4;
GATE = 5;
HIDDEN_GATE = 6;
WINDOW = 7;
DOOR3 = 8;
DOOR5 = 9;
DOOR6 = 10;
CHEST = 11;
// 待补充有特殊效果的地形
}

enum ShapeType // 形状类型
{
NULL_SHAPE_TYPE = 0;
CIRCLE = 1; // 人类、屠夫、可拾取道具等为圆形
SQUARE = 2; // 地形均为方形
}

enum PropType // 地图中的可拾取道具类型
{
NULL_PROP_TYPE = 0;
ADD_SPEED = 1;
ADD_LIFE_OR_CLAIRAUDIENCE = 2;
ADD_HP_OR_AP = 3;
SHIELD_OR_SPEAR = 4;
KEY3 = 5;
KEY5 = 6;
KEY6 = 7;
RECOVERY_FROM_DIZZINESS = 8;
}

enum StudentBuffType // 人类可用的增益效果类型
{
NULL_SBUFF_TYPE = 0;
STUDENT_ADD_SPEED = 1;
ADD_LIFE = 2;
SHIELD = 3;
STUDENT_INVISIBLE = 4;
}

enum PlayerState
{
NULL_STATUS = 0;
IDLE = 1; // 正常状态
LEARNING = 2; // 学习状态,相当于在修机器
ADDICTED = 3; // 血条归零后原地沉迷游戏
QUIT = 4; // 退学状态,相当于寄了
GRADUATED = 5; // 毕业状态,相当于逃脱了
TREATED = 6;
RESCUED = 7;
STUNNED = 8;
TREATING = 9;
RESCUING = 10;
SWINGING = 11; // 后摇
ATTACKING = 12; // 前摇
LOCKING = 13;
RUMMAGING = 14;
CLIMBING = 15; // 翻窗
OPENING_A_CHEST =16;
USING_SPECIAL_SKILL = 17;
OPENING_A_GATE =18;
}

enum TrickerBuffType // 屠夫可用的增益效果类型
{
NULL_TBUFF_TYPE = 0;
TRICKER_ADD_SPEED = 1;
SPEAR = 2;
ADD_AP = 3;
CLAIRAUDIENCE = 4;
TRICKER_INVISIBLE = 5;
}

// 特别说明:由于Student阵营和Tricker阵营有显著的隔离,且暂定职业、主动技能和被动效果相互绑定,故不按照THUAI5的方式区分ActiveSkillType和CharacterType,而是选择了按照阵营来给不同阵营赋予不同的职业(及技能)。

enum PlayerType
{
NULL_PLAYER_TYPE = 0;
STUDENT_PLAYER = 1;
TRICKER_PLAYER = 2;
}

enum StudentType
{
NULL_STUDENT_TYPE = 0;
ATHLETE = 1;
TEACHER = 2;
STRAIGHT_A_STUDENT = 3;
ROBOT = 4;
TECH_OTAKU =5;
SUNSHINE = 6;
}

enum TrickerType
{
NULL_TRICKER_TYPE = 0;
ASSASSIN = 1;
KLEE = 2;
A_NOISY_PERSON = 3;
IDOL = 4;
}

// 游戏进行状态
enum GameState
{
NULL_GAME_STATE = 0;
GAME_START = 1;
GAME_RUNNING = 2;
GAME_END = 3;
}

+ 33
- 0
experimental/dependency/proto/Services.proto View File

@@ -0,0 +1,33 @@
syntax = "proto3";
package protobuf;

import "Message2Clients.proto";
import "Message2Server.proto";

service AvailableService
{
rpc TryConnection (IDMsg) returns(BoolRes);

// 游戏开局调用一次的服务
rpc AddPlayer (PlayerMsg) returns(stream MessageToClient); // 连接上后等待游戏开始,server会定时通过该服务向所有client发送消息。

// 游戏过程中玩家执行操作的服务
rpc Move (MoveMsg) returns (MoveRes);
rpc PickProp (PropMsg) returns (BoolRes);
rpc UseProp (PropMsg) returns (BoolRes);
rpc ThrowProp (PropMsg) returns (BoolRes);
rpc UseSkill (SkillMsg) returns (BoolRes);
rpc SendMessage (SendMsg) returns (BoolRes);
// rpc GetMessage (IDMsg) returns (stream MsgRes);
rpc StartLearning (IDMsg) returns (BoolRes); // 开始修理机器
rpc StartRescueMate (TreatAndRescueMsg) returns (BoolRes); // 开始救人
rpc StartTreatMate (TreatAndRescueMsg) returns (BoolRes); // 开始治疗
rpc Attack (AttackMsg) returns (BoolRes); // 攻击
rpc Graduate (IDMsg) returns (BoolRes); // 相当于逃跑
rpc OpenDoor (IDMsg) returns (BoolRes); // 开门
rpc CloseDoor (IDMsg) returns (BoolRes); // 关门
rpc SkipWindow (IDMsg) returns (BoolRes); // 窗户
rpc StartOpenGate (IDMsg) returns (BoolRes); // 开闸门
rpc StartOpenChest (IDMsg) returns (BoolRes);
rpc EndAllAction (IDMsg) returns (BoolRes); // 结束所有动作
}

+ 10
- 0
experimental/dependency/proto/buf.gen.tag.yaml View File

@@ -0,0 +1,10 @@
version: v1
managed:
enabled: true
go_package_prefix:
default: proto
plugins:
- name: gotag
out: .
opt:
- auto=bson

+ 14
- 0
experimental/dependency/proto/buf.gen.yaml View File

@@ -0,0 +1,14 @@
version: v1
managed:
enabled: true
go_package_prefix:
default: job-API/proto
plugins:
- name: go
out: proto
opt: paths=source_relative
- name: go-grpc
out: proto
opt:
- paths=source_relative
- require_unimplemented_servers=false

+ 10
- 0
experimental/dependency/proto/go_output.sh View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash

set -e

PROTO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
pushd "${PROTO_DIR}"
buf generate
rm -rf ../../CAPI/go/API/proto
mv -f proto ../../CAPI/go/API
popd

Loading…
Cancel
Save