Implemented basic server
This commit is contained in:
parent
aa2c60013c
commit
aeb8f642d6
193
main.go
193
main.go
@ -1,21 +1,194 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
//TIP <p>To run your code, right-click the code and select <b>Run</b>.</p> <p>Alternatively, click
|
||||
// the <icon src="AllIcons.Actions.Execute"/> icon in the gutter and select the <b>Run</b> menu item from here.</p>
|
||||
const (
|
||||
HandshakePacketID = 0x00
|
||||
StatusRequestID = 0x00
|
||||
StatusResponseID = 0x00
|
||||
)
|
||||
|
||||
type HandshakePacket struct {
|
||||
ProtocolVersion int
|
||||
ServerAddress string
|
||||
ServerPort uint16
|
||||
NextState int
|
||||
}
|
||||
|
||||
type StatusResponse struct {
|
||||
Version VersionInfo `json:"version"`
|
||||
Players PlayerInfo `json:"players"`
|
||||
Description Chat `json:"description"`
|
||||
}
|
||||
|
||||
type VersionInfo struct {
|
||||
Name string `json:"name"`
|
||||
Protocol int `json:"protocol"`
|
||||
}
|
||||
|
||||
type PlayerInfo struct {
|
||||
Max int `json:"max"`
|
||||
Online int `json:"online"`
|
||||
Sample []Player `json:"sample"`
|
||||
}
|
||||
|
||||
type Player struct {
|
||||
Name string `json:"name"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type Chat struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
//TIP <p>Press <shortcut actionId="ShowIntentionActions"/> when your caret is at the underlined text
|
||||
// to see how GoLand suggests fixing the warning.</p><p>Alternatively, if available, click the lightbulb to view possible fixes.</p>
|
||||
s := "gopher"
|
||||
fmt.Println("Hello and welcome, %s!", s)
|
||||
listener, err := net.Listen("tcp", ":25565")
|
||||
if err != nil {
|
||||
fmt.Println("Error starting server:", err)
|
||||
return
|
||||
}
|
||||
defer listener.Close()
|
||||
|
||||
for i := 1; i <= 5; i++ {
|
||||
//TIP <p>To start your debugging session, right-click your code in the editor and select the Debug option.</p> <p>We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
|
||||
// for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.</p>
|
||||
fmt.Println("i =", 100/i)
|
||||
fmt.Println("Server started on port 25565")
|
||||
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
fmt.Println("Error accepting connection:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
go handleConnection(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handleConnection(conn net.Conn) {
|
||||
var packetID byte
|
||||
if err := readByte(conn, &packetID); err != nil {
|
||||
fmt.Println("Error reading packet ID:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if packetID == HandshakePacketID {
|
||||
handleHandshake(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handleHandshake(conn net.Conn) {
|
||||
var handshake HandshakePacket
|
||||
if err := readHandshakePacket(conn, &handshake); err != nil {
|
||||
fmt.Println("Error reading handshake packet:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if handshake.NextState == 1 {
|
||||
handleStatusRequest(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handleStatusRequest(conn net.Conn) {
|
||||
var packetID byte
|
||||
if err := readByte(conn, &packetID); err != nil {
|
||||
fmt.Println("Error reading packet ID:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if packetID == StatusRequestID {
|
||||
status := StatusResponse{
|
||||
Version: VersionInfo{
|
||||
Name: "1.17.1",
|
||||
Protocol: 756,
|
||||
},
|
||||
Players: PlayerInfo{
|
||||
Max: 100,
|
||||
Online: 5,
|
||||
Sample: []Player{},
|
||||
},
|
||||
Description: Chat{
|
||||
Text: "A Minecraft Server",
|
||||
},
|
||||
}
|
||||
|
||||
response, err := json.Marshal(status)
|
||||
if err != nil {
|
||||
fmt.Println("Error marshaling status response:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := writeByte(conn, StatusResponseID); err != nil {
|
||||
fmt.Println("Error writing response ID:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := writeVarInt(conn, len(response)); err != nil {
|
||||
fmt.Println("Error writing response length:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := conn.Write(response); err != nil {
|
||||
fmt.Println("Error writing response:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readByte(conn net.Conn, b *byte) error {
|
||||
buf := make([]byte, 1)
|
||||
_, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*b = buf[0]
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeByte(conn net.Conn, b byte) error {
|
||||
_, err := conn.Write([]byte{b})
|
||||
return err
|
||||
}
|
||||
|
||||
func writeVarInt(conn net.Conn, value int) error {
|
||||
for {
|
||||
temp := byte(value & 0x7F)
|
||||
value >>= 7
|
||||
if value != 0 {
|
||||
temp |= 0x80
|
||||
}
|
||||
if _, err := conn.Write([]byte{temp}); err != nil {
|
||||
return err
|
||||
}
|
||||
if value == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readVarInt(conn net.Conn, value *int) error {
|
||||
var result int
|
||||
var shift uint
|
||||
for {
|
||||
var b byte
|
||||
if err := readByte(conn, &b); err != nil {
|
||||
return err
|
||||
}
|
||||
result |= int(b&0x7F) << shift
|
||||
shift += 7
|
||||
if b&0x80 == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
*value = result
|
||||
return nil
|
||||
}
|
||||
|
||||
func readHandshakePacket(conn net.Conn, packet *HandshakePacket) error {
|
||||
if err := readVarInt(conn, &packet.ProtocolVersion); err != nil {
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user