mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-13 23:44:52 +01:00
346 lines
7.9 KiB
Go
346 lines
7.9 KiB
Go
package channelserver
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/bwmarrin/discordgo"
|
|
)
|
|
|
|
type Character struct {
|
|
ID uint32 `db:"id"`
|
|
IsFemale bool `db:"is_female"`
|
|
IsNewCharacter bool `db:"is_new_character"`
|
|
Name string `db:"name"`
|
|
UnkDescString string `db:"unk_desc_string"`
|
|
HRP uint16 `db:"hrp"`
|
|
GR uint16 `db:"gr"`
|
|
WeaponType uint16 `db:"weapon_type"`
|
|
LastLogin uint32 `db:"last_login"`
|
|
}
|
|
|
|
var weapons = []string{
|
|
"<:gs:970861408227049477>",
|
|
"<:hbg:970861408281563206>",
|
|
"<:hm:970861408239628308>",
|
|
"<:lc:970861408298352660>",
|
|
"<:sns:970861408319315988>",
|
|
"<:lbg:970861408327725137>",
|
|
"<:ds:970861408277368883>",
|
|
"<:ls:970861408319311872>",
|
|
"<:hh:970861408222863400>",
|
|
"<:gl:970861408327720980>",
|
|
"<:bw:970861408294174780>",
|
|
"<:tf:970861408424177744>",
|
|
"<:sw:970861408340283472>",
|
|
"<:ms:970861408411594842>",
|
|
}
|
|
|
|
func (s *Server) getCharacterForUser(uid int) (*Character, error) {
|
|
character := Character{}
|
|
err := s.db.Get(&character, "SELECT id, is_female, is_new_character, name, unk_desc_string, hrp, gr, weapon_type, last_login FROM characters WHERE id = $1", uid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &character, nil
|
|
}
|
|
|
|
func CountChars(s *Server) string {
|
|
count := 0
|
|
for _, stage := range s.stages {
|
|
count += len(stage.clients)
|
|
}
|
|
|
|
message := fmt.Sprintf("Server [%s]: %d players;", s.name, count)
|
|
|
|
return message
|
|
}
|
|
|
|
type ListPlayer struct {
|
|
CharName string
|
|
InQuest bool
|
|
WeaponEmoji string
|
|
QuestEmoji string
|
|
StageName string
|
|
}
|
|
|
|
func (p *ListPlayer) toString(length int) string {
|
|
status := ""
|
|
if p.InQuest {
|
|
status = "(in quest " + p.QuestEmoji + ")"
|
|
} else {
|
|
status = p.StageName
|
|
}
|
|
|
|
missingSpace := length - len(p.CharName)
|
|
whitespaces := strings.Repeat(" ", missingSpace+5)
|
|
|
|
return fmt.Sprintf("%s %s %s %s", p.WeaponEmoji, p.CharName, whitespaces, status)
|
|
}
|
|
|
|
func getPlayerList(s *Server) ([]ListPlayer, int) {
|
|
list := []ListPlayer{}
|
|
questEmojis := []string{
|
|
":white_circle:",
|
|
":red_circle:",
|
|
":blue_circle:",
|
|
":brown_circle:",
|
|
":green_circle:",
|
|
":purple_circle:",
|
|
":yellow_circle:",
|
|
":orange_circle:",
|
|
}
|
|
|
|
bigNameLen := 0
|
|
|
|
for _, stage := range s.stages {
|
|
if len(stage.clients) == 0 {
|
|
continue
|
|
}
|
|
|
|
questEmoji := ":black_circle:"
|
|
|
|
if len(questEmojis) > 0 {
|
|
questEmoji = questEmojis[len(questEmojis)-1]
|
|
questEmojis = questEmojis[:len(questEmojis)-1]
|
|
}
|
|
|
|
isQuest := stage.isQuest()
|
|
for client := range stage.clients {
|
|
char, err := s.getCharacterForUser(int(client.charID))
|
|
if err == nil {
|
|
if len(char.Name) > bigNameLen {
|
|
bigNameLen = len(char.Name)
|
|
}
|
|
|
|
list = append(list, ListPlayer{
|
|
CharName: char.Name,
|
|
InQuest: isQuest,
|
|
QuestEmoji: questEmoji,
|
|
WeaponEmoji: weapons[char.WeaponType],
|
|
StageName: stage.GetName(),
|
|
})
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return list, bigNameLen
|
|
}
|
|
|
|
func PlayerList(s *Server) string {
|
|
list := ""
|
|
count := 0
|
|
listPlayers, bigNameLen := getPlayerList(s)
|
|
|
|
sort.SliceStable(listPlayers, func(i, j int) bool {
|
|
return listPlayers[i].CharName < listPlayers[j].CharName
|
|
})
|
|
|
|
for _, lp := range listPlayers {
|
|
list += lp.toString(bigNameLen) + "\n"
|
|
count++
|
|
}
|
|
|
|
message := fmt.Sprintf("<:SnS:822963937360347148> Frontier Hunters Online: [%s ] <:switcha:822963906401533992> \n============== Total %d =============\n", s.name, count)
|
|
message += list
|
|
|
|
return message
|
|
}
|
|
|
|
func debug(s *Server) string {
|
|
list := ""
|
|
|
|
for _, stage := range s.stages {
|
|
if !stage.isQuest() && len(stage.objects) == 0 {
|
|
continue
|
|
}
|
|
|
|
list += fmt.Sprintf(" -> Stage: %s StageId: %s\n", stage.GetName(), stage.id)
|
|
isQuest := "false"
|
|
hasDeparted := "false"
|
|
|
|
if stage.isQuest() {
|
|
isQuest = "true"
|
|
}
|
|
|
|
list += fmt.Sprintf(" '-> isQuest: %s\n", isQuest)
|
|
|
|
if stage.isQuest() {
|
|
if len(stage.clients) > 0 {
|
|
hasDeparted = "true"
|
|
}
|
|
|
|
list += fmt.Sprintf(" '-> isDeparted: %s\n", hasDeparted)
|
|
list += fmt.Sprintf(" '-> reserveSlots (%d/%d)\n", len(stage.reservedClientSlots), stage.maxPlayers)
|
|
|
|
for charid, _ := range stage.reservedClientSlots {
|
|
char, err := s.getCharacterForUser(int(charid))
|
|
if err == nil {
|
|
list += fmt.Sprintf(" '-> %s\n", char.Name)
|
|
}
|
|
}
|
|
}
|
|
|
|
list += " '-> objects: \n"
|
|
for _, obj := range stage.objects {
|
|
objInfo := fmt.Sprintf("X,Y,Z: %f %f %f", obj.x, obj.y, obj.z)
|
|
list += fmt.Sprintf(" '-> ObjectId: %d - %s\n", obj.id, objInfo)
|
|
}
|
|
}
|
|
|
|
message := fmt.Sprintf("Objects in Server: [%s ]\n", s.name)
|
|
message += list
|
|
|
|
return message
|
|
}
|
|
|
|
func questlist(s *Server) string {
|
|
list := ""
|
|
|
|
for _, stage := range s.stages {
|
|
if !stage.isQuest() {
|
|
continue
|
|
}
|
|
|
|
hasDeparted := ""
|
|
if len(stage.clients) > 0 {
|
|
hasDeparted = " - departed"
|
|
}
|
|
list += fmt.Sprintf(" '-> StageId: %s (%d/%d) %s - %s\n", stage.id, len(stage.reservedClientSlots), stage.maxPlayers, hasDeparted, stage.createdAt)
|
|
|
|
for charid, _ := range stage.reservedClientSlots {
|
|
char, err := s.getCharacterForUser(int(charid))
|
|
if err == nil {
|
|
list += fmt.Sprintf(" '-> %s\n", char.Name)
|
|
}
|
|
}
|
|
}
|
|
|
|
message := fmt.Sprintf("Quests in Server: [%s ]\n", s.name)
|
|
message += list
|
|
|
|
return message
|
|
}
|
|
|
|
func removeStageById(s *Server, stageId string) string {
|
|
if s.stages[stageId] != nil {
|
|
delete(s.stages, stageId)
|
|
return "Stage deleted!"
|
|
}
|
|
|
|
return "Stage not found!"
|
|
}
|
|
|
|
func cleanStr(str string) string {
|
|
return strings.ToLower(strings.Trim(str, " "))
|
|
}
|
|
|
|
func getCharInfo(server *Server, charName string) string {
|
|
var s *Stage
|
|
var c *Session
|
|
|
|
for _, stage := range server.stages {
|
|
for client := range stage.clients {
|
|
|
|
if client.Name == "" {
|
|
continue
|
|
}
|
|
|
|
if cleanStr(client.Name) == cleanStr(charName) {
|
|
s = stage
|
|
c = client
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if s == nil {
|
|
return "Character not found"
|
|
}
|
|
|
|
objInfo := ""
|
|
|
|
obj := server.FindObjectByChar(c.charID)
|
|
// server.logger.Info("Found object: %+v", zap.Object("obj", obj))
|
|
|
|
if obj != nil {
|
|
objInfo = fmt.Sprintf("X,Y,Z: %f %f %f", obj.x, obj.y, obj.z)
|
|
}
|
|
|
|
return fmt.Sprintf("Character: %s\nStage: %s\nStageId: %s\n%s", c.Name, s.GetName(), s.id, objInfo)
|
|
}
|
|
|
|
func (s *Server) isDiscordAdmin(ds *discordgo.Session, m *discordgo.MessageCreate) bool {
|
|
for _, role := range m.Member.Roles {
|
|
for _, id := range s.erupeConfig.Discord.DevRoles {
|
|
if id == role {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// onDiscordMessage handles receiving messages from discord and forwarding them ingame.
|
|
func (s *Server) onDiscordMessage(ds *discordgo.Session, m *discordgo.MessageCreate) {
|
|
// Ignore messages from our bot, or ones that are not in the correct channel.
|
|
if m.Author.ID == ds.State.User.ID || !s.enable {
|
|
return
|
|
}
|
|
|
|
// Ignore other channels in devMode
|
|
if s.erupeConfig.Discord.DevMode && m.ChannelID != s.erupeConfig.Discord.RealtimeChannelID {
|
|
return
|
|
}
|
|
|
|
args := strings.Split(m.Content, " ")
|
|
commandName := args[0]
|
|
|
|
// Move to slash commadns
|
|
if commandName == "!players" {
|
|
ds.ChannelMessageSend(m.ChannelID, PlayerList(s))
|
|
return
|
|
}
|
|
|
|
if commandName == "-char" {
|
|
if len(args) < 2 {
|
|
ds.ChannelMessageSend(m.ChannelID, "Usage: !char <char name>")
|
|
return
|
|
}
|
|
|
|
charName := strings.Join(args[1:], " ")
|
|
ds.ChannelMessageSend(m.ChannelID, getCharInfo(s, charName))
|
|
return
|
|
}
|
|
|
|
if commandName == "!debug" && s.isDiscordAdmin(ds, m) {
|
|
ds.ChannelMessageSend(m.ChannelID, debug(s))
|
|
return
|
|
}
|
|
|
|
if commandName == "!questlist" && s.isDiscordAdmin(ds, m) {
|
|
ds.ChannelMessageSend(m.ChannelID, questlist(s))
|
|
return
|
|
}
|
|
|
|
if commandName == "!remove-stage" && s.isDiscordAdmin(ds, m) {
|
|
if len(args) < 2 {
|
|
ds.ChannelMessageSend(m.ChannelID, "Usage: !remove-stage <stage id>")
|
|
return
|
|
}
|
|
|
|
stageId := strings.Join(args[1:], " ")
|
|
ds.ChannelMessageSend(m.ChannelID, removeStageById(s, stageId))
|
|
return
|
|
}
|
|
|
|
if m.ChannelID == s.erupeConfig.Discord.RealtimeChannelID {
|
|
message := fmt.Sprintf("[DISCORD] %s: %s", m.Author.Username, m.Content)
|
|
s.BroadcastChatMessage(s.discordBot.NormalizeDiscordMessage(message))
|
|
}
|
|
}
|