Go Version : 1.21.5 2024 컴퓨터공학과 캡스톤디자인 - Next Reality
이전 내용 : 2024-05-11-GoLang으로 UDP 서버 만들기 (1)
에러 출력 변경
기존에 방법으로는 에러 출력이 제대로 되지 않는다는 단점이 있었음. 그래서 사용자 지정 타입인 리스너의 반환에 string을 추가함
// 에러가 있을 경우 string도 추가로 반환
type listeners func(ReceiveMessage, string) (bool, string)
플레이어 접속 확인 개선
기존 방법은 플레이어 아이디로 등록된 주소가 있는지 확인하는게 다였음 확실하게 하기 위해서 역방향 검사도 하고, 방에 들어간 플레이어 리스트에 있는지도 확인함
func isUserExists(userId string, addr string) bool {
_, usrExt := UserAddr[userId]
_, addExt := AddrUser[addr]
mapid, mapExt := UserMapid[userId]
userListExt := false
if mapExt {
mapidUserList := MapidUserList[mapid]
mapidUserIndex := sort.SearchStrings(mapidUserList, userId)
if mapidUserIndex != len(mapidUserList) {
userListExt = true
}
}
return usrExt && addExt && mapExt && userListExt
}
PlayerJoin 개선
플레이어가 접속해 있는지 확인하는 매커니즘이 명확하게 있지 않은 상태였어서 오류가 많이 발생했었음. 따라서 위에서 접속 확인 개선 이후에 이를 적용하고 왜 접속이 실패했는지도 확인 가능하도록 변경
func PlayerJoin(m ReceiveMessage, addr string) (bool, string) {
// PlayerJoin 메시지 형태 :
// PlayerJoin$sendUserId;SendTime;SendUserNickname;MapId
// otherMessage length: 2
if otherMessageLengthCheck(m.CommandName, len(m.OtherMessage)) {
mapid := m.OtherMessage[1]
fmt.Println(
aurora.Sprintf(
aurora.Gray(12, "PlayerJoin Input Address : %s"), addr))
_, isUserExists := UserAddr[m.SendUserId]
_, isAddrExists := AddrUser[addr]
/*
fmt.Println(
aurora.Sprintf(
aurora.Gray(12, "Users Address : %s"), usersAddress))
fmt.Println(
aurora.Sprintf(
aurora.Gray(12, "Users Name : %s"), usersName))
*/
if !isUserExists && !isAddrExists {
UserAddr[m.SendUserId] = addr
AddrUser[addr] = m.SendUserId
UserMapid[m.SendUserId] = mapid
mapUsers := append(MapidUserList[mapid], m.SendUserId)
if len(mapUsers) > 1 {
sort.Strings(mapUsers)
}
MapidUserList[mapid] = mapUsers
return true, aurora.Sprintf(aurora.Green("Success : User [%s] joined Map [%s]"), m.SendUserId, mapid)
} else if isUserExists { // 이미 유저ID가 있을 경우
return false, aurora.Sprintf(aurora.Yellow("Error : User [%s] is already in this game."), m.SendUserId)
} else if isAddrExists { // 이미 접속한 IP가 등록되어 있었을 경우
return false, aurora.Sprintf(aurora.Yellow("Error : Address [%s] is already in this game."), addr)
}
} else {
return false, aurora.Sprintf(aurora.Yellow("Error : PlayerJoin Message Length Error : need 2, received %d"), len(m.OtherMessage))
}
return false, aurora.Sprintf(aurora.Yellow("Error : Unknown (in PlayerJoin)"))
}
PlayerLeave 개선
위의 PlayerJoin 개선과 같은 내용
func PlayerLeave(m ReceiveMessage, addr string) (bool, string) {
// PlayerLeave 형태 :
// PlayerLeave$SendUserId;SendTime
// otherMessage length : 0
if otherMessageLengthCheck(m.CommandName, len(m.OtherMessage)) {
_, isUserAddrExists := UserAddr[m.SendUserId]
_, isUserMapidExists := UserMapid[m.SendUserId]
if isUserAddrExists {
delete(UserAddr, m.SendUserId)
delete(AddrUser, addr)
} else {
return false, aurora.Sprintf(aurora.Yellow("Error : Cannot Found User [%s]"), m.SendUserId)
}
if isUserMapidExists {
userMapid := UserMapid[m.SendUserId]
mapidUserList := MapidUserList[userMapid]
if len(mapidUserList) == 1 {
delete(MapidUserList, userMapid)
} else {
mapidUserIndex := sort.SearchStrings(mapidUserList, m.SendUserId)
if mapidUserIndex != len(mapidUserList) {
mapidUserList = append(mapidUserList[:mapidUserIndex], mapidUserList[mapidUserIndex+1:]...)
MapidUserList[userMapid] = mapidUserList
}
}
// delete(UserMapid, m.SendUserId)
return true, aurora.Sprintf(aurora.Green("Success : User [%s] left Map [%s]\n"), m.SendUserId, userMapid)
} else {
return false, aurora.Sprintf(aurora.Yellow("Error : Cannot Found Map ID of User [%s]"), m.SendUserId)
}
}
return false, aurora.Sprintf(aurora.Yellow("Error : Unknown (in PlayerLeave)"))
}
PlayerMove 기능 추가
이전에 만들어둔 PlayerMove 스키마 리스너 함수에 기능을 추가함
func PlayerMove(m ReceiveMessage, addr string) (bool, string) {
// PlayerMove 형태 :
// PlayerMove$SendUserId;SendTime;Position;Rotation
// otherMessage length : 2
// 보낸 유저가 있는 유저면 return true
// 딱히 더 할 작업은 없음
if isUserExists(m.SendUserId, addr) {
return true, aurora.Sprintf(aurora.Green("Success : User [%s] move\n"), m.SendUserId)
} else {
return false, aurora.Sprintf(aurora.Yellow("Error : Cannot Found User [%s]"), m.SendUserId)
}
}
Asset 관련 스키마 리스너 추가
서버에서 각 방에 있는 에셋 자체를 관리하지는 않기 때문에, AssetCreate, AssetMove, AssetDelete는 플레이어 접속만 확인하고 브로드캐스트하면 됨
func AssetCreate(m ReceiveMessage, addr string) (bool, string) {
// AssetCreate 형태 :
// AssetCreate$SendUserId;SendTime;AssetId;ObjectId;Position;Rotation;Scale;Type;MeshCollider;Rigidbody
// otherMessage length : 8
// 보낸 유저가 있는 유저고, Creator List에 있으면 return true
// 딱히 더 할 작업은 없음
if otherMessageLengthCheck(m.CommandName, len(m.OtherMessage)) {
if isUserExists(m.SendUserId, addr) {
return true, aurora.Sprintf(aurora.Green("Success : User [%s] Asset Create\n"), m.SendUserId)
} else {
return false, aurora.Sprintf(aurora.Yellow("Error : Cannot Found User [%s]"), m.SendUserId)
}
} else {
return false, aurora.Sprintf(aurora.Yellow("Error : AssetCreate Message Length Error : need 8, received %d"), len(m.OtherMessage))
}
}
func AssetMove(m ReceiveMessage, addr string) (bool, string) {
// AssetMove 형태 :
// AssetMove$SendUserId;SendTime;ObjectId;Position;Rotation;Scale
// otherMessage length : 4
// 보낸 유저가 있는 유저고, Creator List에 있으면 return true
// 딱히 더 할 작업은 없음
if otherMessageLengthCheck(m.CommandName, len(m.OtherMessage)) {
if isUserExists(m.SendUserId, addr) {
return true, aurora.Sprintf(aurora.Green("Success : User [%s] Asset Move\n"), m.SendUserId)
} else {
return false, aurora.Sprintf(aurora.Yellow("Error : Cannot Found User [%s]"), m.SendUserId)
}
} else {
return false, aurora.Sprintf(aurora.Yellow("Error : AssetMove Message Length Error : need 8, received %d"), len(m.OtherMessage))
}
}
func AssetDelete(m ReceiveMessage, addr string) (bool, string) {
// PlayerMove 형태 :
// PlayerMove$sendUserId;sendTime;ObjectId
// otherMessage length : 1
// 보낸 유저가 있는 유저고, Creator List에 있으면 return true
// 딱히 더 할 작업은 없음
if otherMessageLengthCheck(m.CommandName, len(m.OtherMessage)) {
if isUserExists(m.SendUserId, addr) {
return true, aurora.Sprintf(aurora.Green("Success : User [%s] Asset Delete\n"), m.SendUserId)
} else {
return false, aurora.Sprintf(aurora.Yellow("Error : Cannot Found User [%s]"), m.SendUserId)
}
} else {
return false, aurora.Sprintf(aurora.Yellow("Error : AssetDelete Message Length Error : need 8, received %d"), len(m.OtherMessage))
}
}