overall improvements + keep up with querymanager v0.2
This commit is contained in:
parent
cd93a7c2bf
commit
48375acd7d
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ bin
|
||||
build
|
||||
local
|
||||
*.log
|
||||
config.cfg
|
||||
|
||||
67
common.go
67
common.go
@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// TReadBuffer
|
||||
@ -83,7 +84,11 @@ func (ReadBuffer *TReadBuffer) ReadString() string {
|
||||
|
||||
Result := ""
|
||||
if ReadBuffer.CanRead(Length) {
|
||||
Result = string(ReadBuffer.Buffer[ReadBuffer.Position:][:Length])
|
||||
// IMPORTANT(fusion): The game server uses LATIN1 encoding, which forces
|
||||
// the query manager to use LATIN1 encoding for text, at least on the
|
||||
// protocol level.
|
||||
Input := ReadBuffer.Buffer[ReadBuffer.Position:][:Length]
|
||||
Result = string(Latin1ToUTF8(Input))
|
||||
}
|
||||
ReadBuffer.Position += Length
|
||||
return Result
|
||||
@ -157,7 +162,11 @@ func (WriteBuffer *TWriteBuffer) Write32BE(Value uint32) {
|
||||
}
|
||||
|
||||
func (WriteBuffer *TWriteBuffer) WriteString(String string) {
|
||||
Length := len(String)
|
||||
// IMPORTANT(fusion): The game server uses LATIN1 encoding, which forces
|
||||
// the query manager to use LATIN1 encoding for text, at least on the
|
||||
// protocol level.
|
||||
Output := UTF8ToLatin1([]byte(String))
|
||||
Length := len(Output)
|
||||
if Length < 0xFFFF {
|
||||
WriteBuffer.Write16(uint16(Length))
|
||||
} else {
|
||||
@ -166,7 +175,7 @@ func (WriteBuffer *TWriteBuffer) WriteString(String string) {
|
||||
}
|
||||
|
||||
if WriteBuffer.CanWrite(Length) {
|
||||
copy(WriteBuffer.Buffer[WriteBuffer.Position:], String)
|
||||
copy(WriteBuffer.Buffer[WriteBuffer.Position:], Output)
|
||||
}
|
||||
WriteBuffer.Position += Length
|
||||
}
|
||||
@ -370,7 +379,7 @@ func WorldTypeString(Type int) string {
|
||||
}
|
||||
}
|
||||
|
||||
func TimestampString(Timestamp int) string {
|
||||
func FormatTimestamp(Timestamp int) string {
|
||||
String := "Never"
|
||||
if Timestamp > 0 {
|
||||
Time := time.Unix(int64(Timestamp), 0)
|
||||
@ -378,3 +387,53 @@ func TimestampString(Timestamp int) string {
|
||||
}
|
||||
return String
|
||||
}
|
||||
|
||||
func FormatDurationSince(Timestamp int) string {
|
||||
String := "N/A"
|
||||
if Timestamp > 0{
|
||||
Duration := time.Since(time.Unix(int64(Timestamp), 0))
|
||||
String = Duration.Truncate(time.Second).String()
|
||||
}
|
||||
return String
|
||||
}
|
||||
|
||||
func UTF8FindNextLeadingByte(Buffer []byte) int {
|
||||
Offset := 0
|
||||
for Offset < len(Buffer) {
|
||||
// NOTE(fusion): Allow the first byte to be a leading byte, in case we
|
||||
// just want to advance from one leading byte to another.
|
||||
if(Offset > 0 && utf8.RuneStart(Buffer[Offset])){
|
||||
break
|
||||
}
|
||||
Offset += 1
|
||||
}
|
||||
return Offset
|
||||
}
|
||||
|
||||
func UTF8ToLatin1(Buffer []byte) []byte {
|
||||
ReadPos := 0
|
||||
Result := []byte{}
|
||||
for ReadPos < len(Buffer) {
|
||||
Codepoint, Size := utf8.DecodeRune(Buffer[ReadPos:])
|
||||
if Codepoint != utf8.RuneError {
|
||||
ReadPos += Size
|
||||
}else{
|
||||
ReadPos += UTF8FindNextLeadingByte(Buffer[ReadPos:])
|
||||
}
|
||||
|
||||
if Codepoint >= 0 && Codepoint <= 0xFF {
|
||||
Result = append(Result, byte(Codepoint))
|
||||
}else{
|
||||
Result = append(Result, '?')
|
||||
}
|
||||
}
|
||||
return Result
|
||||
}
|
||||
|
||||
func Latin1ToUTF8(Buffer []byte) []byte {
|
||||
Result := []byte{}
|
||||
for ReadPos := range Buffer {
|
||||
Result = utf8.AppendRune(Result, rune(Buffer[ReadPos]))
|
||||
}
|
||||
return Result
|
||||
}
|
||||
|
||||
2
main.go
2
main.go
@ -563,7 +563,7 @@ func HandleWorld(Context *THttpRequestContext) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
g_Log.Print("Tibia Web Server v0.1")
|
||||
g_Log.Print("Tibia Web Server v0.2")
|
||||
if !ReadConfig("config.cfg", WebKVCallback) {
|
||||
return
|
||||
}
|
||||
|
||||
16
query.go
16
query.go
@ -45,8 +45,10 @@ type (
|
||||
Type string
|
||||
NumPlayers int
|
||||
MaxPlayers int
|
||||
OnlineRecord int
|
||||
OnlineRecordTime string
|
||||
OnlinePeak int
|
||||
OnlinePeakTimestamp int
|
||||
LastStartup int
|
||||
LastShutdown int
|
||||
}
|
||||
|
||||
TAccountSummary struct {
|
||||
@ -77,7 +79,7 @@ type (
|
||||
Level int
|
||||
Profession string
|
||||
Residence string
|
||||
LastLogin string
|
||||
LastLogin int
|
||||
PremiumDays int
|
||||
Online bool
|
||||
Deleted bool
|
||||
@ -389,7 +391,7 @@ func (Connection *TQueryManagerConnection) GetCharacterProfile(CharacterName str
|
||||
Character.Level = int(ReadBuffer.Read16())
|
||||
Character.Profession = ReadBuffer.ReadString()
|
||||
Character.Residence = ReadBuffer.ReadString()
|
||||
Character.LastLogin = TimestampString(int(ReadBuffer.Read32()))
|
||||
Character.LastLogin = int(ReadBuffer.Read32())
|
||||
Character.PremiumDays = int(ReadBuffer.Read16())
|
||||
Character.Online = ReadBuffer.ReadFlag()
|
||||
Character.Deleted = ReadBuffer.ReadFlag()
|
||||
@ -422,8 +424,10 @@ func (Connection *TQueryManagerConnection) GetWorlds() (Result int, Worlds []TWo
|
||||
Worlds[Index].Type = WorldTypeString(int(ReadBuffer.Read8()))
|
||||
Worlds[Index].NumPlayers = int(ReadBuffer.Read16())
|
||||
Worlds[Index].MaxPlayers = int(ReadBuffer.Read16())
|
||||
Worlds[Index].OnlineRecord = int(ReadBuffer.Read16())
|
||||
Worlds[Index].OnlineRecordTime = TimestampString(int(ReadBuffer.Read32()))
|
||||
Worlds[Index].OnlinePeak = int(ReadBuffer.Read16())
|
||||
Worlds[Index].OnlinePeakTimestamp = int(ReadBuffer.Read32())
|
||||
Worlds[Index].LastStartup = int(ReadBuffer.Read32())
|
||||
Worlds[Index].LastShutdown = int(ReadBuffer.Read32())
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
||||
@ -58,7 +58,13 @@ var (
|
||||
|
||||
func InitTemplates() bool {
|
||||
var Err error
|
||||
g_Templates, Err = template.ParseGlob("templates/*.tmpl")
|
||||
|
||||
CustomFuncs := template.FuncMap{
|
||||
"FormatTimestamp": FormatTimestamp,
|
||||
"FormatDurationSince": FormatDurationSince,
|
||||
}
|
||||
|
||||
g_Templates, Err = template.New("").Funcs(CustomFuncs).ParseGlob("templates/*.tmpl")
|
||||
if Err != nil {
|
||||
g_LogErr.Printf("Failed to parse templates: %v", Err)
|
||||
return false
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{{template "_header.tmpl" .Common}}
|
||||
<form class="box" action="/character/create" method="POST">
|
||||
<h1>Create Account</h1>
|
||||
<h1>Create Character</h1>
|
||||
|
||||
<label for="character_name">NAME</label>
|
||||
<input id="character_name" type="text" name="name"/>
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Last Login:</th>
|
||||
<td>{{.LastLogin}}</td>
|
||||
<td>{{FormatTimestamp .LastLogin}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Account Status:</th>
|
||||
|
||||
@ -16,13 +16,24 @@
|
||||
<td>{{.NumPlayers}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Online Record:</th>
|
||||
{{if .OnlineRecord}}
|
||||
<td>{{.OnlineRecord}} players (on {{.OnlineRecordTime}})</td>
|
||||
<th>Online Peak:</th>
|
||||
{{if eq .OnlinePeak 1}}
|
||||
<td>{{.OnlinePeak}} player (on {{FormatTimestamp .OnlinePeakTimestamp}})</td>
|
||||
{{else if gt .OnlinePeak 1}}
|
||||
<td>{{.OnlinePeak}} players (on {{FormatTimestamp .OnlinePeakTimestamp}})</td>
|
||||
{{else}}
|
||||
<td>None</td>
|
||||
{{end}}
|
||||
</tr>
|
||||
<tr>
|
||||
{{if gt .LastStartup .LastShutdown}}
|
||||
<th>Uptime:</th>
|
||||
<td>{{FormatDurationSince .LastStartup}}</td>
|
||||
{{else}}
|
||||
<th>Downtime:</th>
|
||||
<td style="color: #A11;">{{FormatDurationSince .LastShutdown}}</td>
|
||||
{{end}}
|
||||
</tr>
|
||||
</table>
|
||||
<a class="button" href="/killstatistics?world={{.Name}}">Kill Statistics</a>
|
||||
{{else}}
|
||||
|
||||
@ -7,12 +7,18 @@
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Players Online</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
{{range .Worlds}}
|
||||
<tr>
|
||||
<td><a href="/world?name={{.Name}}">{{.Name}}</a></td>
|
||||
<td>{{.Type}}</td>
|
||||
<td>{{.NumPlayers}}</td>
|
||||
{{if gt .LastStartup .LastShutdown}}
|
||||
<td style="color: #1A1;">Online</td>
|
||||
{{else}}
|
||||
<td style="color: #A11;">Offline</td>
|
||||
{{end}}
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user