Compare commits
	
		
			4 Commits
		
	
	
		
			be32dec202
			...
			3f7205d73e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3f7205d73e | |||
| 0731339fe8 | |||
| 71d42a8fd6 | |||
| 52ab45fe53 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | *.db | ||||||
| @ -26,6 +26,8 @@ const ( | |||||||
| 	Action_MOVE       Action_ActionType = 0 | 	Action_MOVE       Action_ActionType = 0 | ||||||
| 	Action_CHAT       Action_ActionType = 1 | 	Action_CHAT       Action_ActionType = 1 | ||||||
| 	Action_DISCONNECT Action_ActionType = 2 | 	Action_DISCONNECT Action_ActionType = 2 | ||||||
|  | 	Action_LOGIN      Action_ActionType = 3 | ||||||
|  | 	Action_REGISTER   Action_ActionType = 4 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Enum value maps for Action_ActionType. | // Enum value maps for Action_ActionType. | ||||||
| @ -34,11 +36,15 @@ var ( | |||||||
| 		0: "MOVE", | 		0: "MOVE", | ||||||
| 		1: "CHAT", | 		1: "CHAT", | ||||||
| 		2: "DISCONNECT", | 		2: "DISCONNECT", | ||||||
|  | 		3: "LOGIN", | ||||||
|  | 		4: "REGISTER", | ||||||
| 	} | 	} | ||||||
| 	Action_ActionType_value = map[string]int32{ | 	Action_ActionType_value = map[string]int32{ | ||||||
| 		"MOVE":       0, | 		"MOVE":       0, | ||||||
| 		"CHAT":       1, | 		"CHAT":       1, | ||||||
| 		"DISCONNECT": 2, | 		"DISCONNECT": 2, | ||||||
|  | 		"LOGIN":      3, | ||||||
|  | 		"REGISTER":   4, | ||||||
| 	} | 	} | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @ -76,6 +82,8 @@ type Action struct { | |||||||
| 	Y             int32                  `protobuf:"varint,3,opt,name=y,proto3" json:"y,omitempty"` | 	Y             int32                  `protobuf:"varint,3,opt,name=y,proto3" json:"y,omitempty"` | ||||||
| 	PlayerId      int32                  `protobuf:"varint,4,opt,name=player_id,json=playerId,proto3" json:"player_id,omitempty"` | 	PlayerId      int32                  `protobuf:"varint,4,opt,name=player_id,json=playerId,proto3" json:"player_id,omitempty"` | ||||||
| 	ChatMessage   string                 `protobuf:"bytes,5,opt,name=chat_message,json=chatMessage,proto3" json:"chat_message,omitempty"` | 	ChatMessage   string                 `protobuf:"bytes,5,opt,name=chat_message,json=chatMessage,proto3" json:"chat_message,omitempty"` | ||||||
|  | 	Username      string                 `protobuf:"bytes,6,opt,name=username,proto3" json:"username,omitempty"` | ||||||
|  | 	Password      string                 `protobuf:"bytes,7,opt,name=password,proto3" json:"password,omitempty"` | ||||||
| 	unknownFields protoimpl.UnknownFields | 	unknownFields protoimpl.UnknownFields | ||||||
| 	sizeCache     protoimpl.SizeCache | 	sizeCache     protoimpl.SizeCache | ||||||
| } | } | ||||||
| @ -145,11 +153,26 @@ func (x *Action) GetChatMessage() string { | |||||||
| 	return "" | 	return "" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (x *Action) GetUsername() string { | ||||||
|  | 	if x != nil { | ||||||
|  | 		return x.Username | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *Action) GetPassword() string { | ||||||
|  | 	if x != nil { | ||||||
|  | 		return x.Password | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
| type ActionBatch struct { | type ActionBatch struct { | ||||||
| 	state           protoimpl.MessageState `protogen:"open.v1"` | 	state           protoimpl.MessageState `protogen:"open.v1"` | ||||||
| 	PlayerId        int32                  `protobuf:"varint,1,opt,name=player_id,json=playerId,proto3" json:"player_id,omitempty"` | 	PlayerId        int32                  `protobuf:"varint,1,opt,name=player_id,json=playerId,proto3" json:"player_id,omitempty"` | ||||||
| 	Actions         []*Action              `protobuf:"bytes,2,rep,name=actions,proto3" json:"actions,omitempty"` | 	Actions         []*Action              `protobuf:"bytes,2,rep,name=actions,proto3" json:"actions,omitempty"` | ||||||
| 	Tick            int64                  `protobuf:"varint,3,opt,name=tick,proto3" json:"tick,omitempty"` | 	Tick            int64                  `protobuf:"varint,3,opt,name=tick,proto3" json:"tick,omitempty"` | ||||||
|  | 	ProtocolVersion int32                  `protobuf:"varint,4,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"` | ||||||
| 	unknownFields   protoimpl.UnknownFields | 	unknownFields   protoimpl.UnknownFields | ||||||
| 	sizeCache       protoimpl.SizeCache | 	sizeCache       protoimpl.SizeCache | ||||||
| } | } | ||||||
| @ -205,11 +228,19 @@ func (x *ActionBatch) GetTick() int64 { | |||||||
| 	return 0 | 	return 0 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (x *ActionBatch) GetProtocolVersion() int32 { | ||||||
|  | 	if x != nil { | ||||||
|  | 		return x.ProtocolVersion | ||||||
|  | 	} | ||||||
|  | 	return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
| type PlayerState struct { | type PlayerState struct { | ||||||
| 	state         protoimpl.MessageState `protogen:"open.v1"` | 	state         protoimpl.MessageState `protogen:"open.v1"` | ||||||
| 	PlayerId      int32                  `protobuf:"varint,1,opt,name=player_id,json=playerId,proto3" json:"player_id,omitempty"` | 	PlayerId      int32                  `protobuf:"varint,1,opt,name=player_id,json=playerId,proto3" json:"player_id,omitempty"` | ||||||
| 	X             int32                  `protobuf:"varint,2,opt,name=x,proto3" json:"x,omitempty"` | 	X             int32                  `protobuf:"varint,2,opt,name=x,proto3" json:"x,omitempty"` | ||||||
| 	Y             int32                  `protobuf:"varint,3,opt,name=y,proto3" json:"y,omitempty"` | 	Y             int32                  `protobuf:"varint,3,opt,name=y,proto3" json:"y,omitempty"` | ||||||
|  | 	Username      string                 `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"` | ||||||
| 	unknownFields protoimpl.UnknownFields | 	unknownFields protoimpl.UnknownFields | ||||||
| 	sizeCache     protoimpl.SizeCache | 	sizeCache     protoimpl.SizeCache | ||||||
| } | } | ||||||
| @ -265,11 +296,19 @@ func (x *PlayerState) GetY() int32 { | |||||||
| 	return 0 | 	return 0 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (x *PlayerState) GetUsername() string { | ||||||
|  | 	if x != nil { | ||||||
|  | 		return x.Username | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
| type ChatMessage struct { | type ChatMessage struct { | ||||||
| 	state         protoimpl.MessageState `protogen:"open.v1"` | 	state         protoimpl.MessageState `protogen:"open.v1"` | ||||||
| 	PlayerId      int32                  `protobuf:"varint,1,opt,name=player_id,json=playerId,proto3" json:"player_id,omitempty"` | 	PlayerId      int32                  `protobuf:"varint,1,opt,name=player_id,json=playerId,proto3" json:"player_id,omitempty"` | ||||||
| 	Content       string                 `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` | 	Username      string                 `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` | ||||||
| 	Timestamp     int64                  `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` | 	Content       string                 `protobuf:"bytes,3,opt,name=content,proto3" json:"content,omitempty"` | ||||||
|  | 	Timestamp     int64                  `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` | ||||||
| 	unknownFields protoimpl.UnknownFields | 	unknownFields protoimpl.UnknownFields | ||||||
| 	sizeCache     protoimpl.SizeCache | 	sizeCache     protoimpl.SizeCache | ||||||
| } | } | ||||||
| @ -311,6 +350,13 @@ func (x *ChatMessage) GetPlayerId() int32 { | |||||||
| 	return 0 | 	return 0 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (x *ChatMessage) GetUsername() string { | ||||||
|  | 	if x != nil { | ||||||
|  | 		return x.Username | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
| func (x *ChatMessage) GetContent() string { | func (x *ChatMessage) GetContent() string { | ||||||
| 	if x != nil { | 	if x != nil { | ||||||
| 		return x.Content | 		return x.Content | ||||||
| @ -331,6 +377,9 @@ type ServerMessage struct { | |||||||
| 	Players         []*PlayerState         `protobuf:"bytes,2,rep,name=players,proto3" json:"players,omitempty"` | 	Players         []*PlayerState         `protobuf:"bytes,2,rep,name=players,proto3" json:"players,omitempty"` | ||||||
| 	CurrentTick     int64                  `protobuf:"varint,3,opt,name=current_tick,json=currentTick,proto3" json:"current_tick,omitempty"` | 	CurrentTick     int64                  `protobuf:"varint,3,opt,name=current_tick,json=currentTick,proto3" json:"current_tick,omitempty"` | ||||||
| 	ChatMessages    []*ChatMessage         `protobuf:"bytes,4,rep,name=chat_messages,json=chatMessages,proto3" json:"chat_messages,omitempty"` | 	ChatMessages    []*ChatMessage         `protobuf:"bytes,4,rep,name=chat_messages,json=chatMessages,proto3" json:"chat_messages,omitempty"` | ||||||
|  | 	AuthSuccess     bool                   `protobuf:"varint,5,opt,name=auth_success,json=authSuccess,proto3" json:"auth_success,omitempty"` | ||||||
|  | 	ErrorMessage    string                 `protobuf:"bytes,6,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` | ||||||
|  | 	ProtocolVersion int32                  `protobuf:"varint,7,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"` | ||||||
| 	unknownFields   protoimpl.UnknownFields | 	unknownFields   protoimpl.UnknownFields | ||||||
| 	sizeCache       protoimpl.SizeCache | 	sizeCache       protoimpl.SizeCache | ||||||
| } | } | ||||||
| @ -393,11 +442,32 @@ func (x *ServerMessage) GetChatMessages() []*ChatMessage { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (x *ServerMessage) GetAuthSuccess() bool { | ||||||
|  | 	if x != nil { | ||||||
|  | 		return x.AuthSuccess | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *ServerMessage) GetErrorMessage() string { | ||||||
|  | 	if x != nil { | ||||||
|  | 		return x.ErrorMessage | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *ServerMessage) GetProtocolVersion() int32 { | ||||||
|  | 	if x != nil { | ||||||
|  | 		return x.ProtocolVersion | ||||||
|  | 	} | ||||||
|  | 	return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
| var File_actions_proto protoreflect.FileDescriptor | var File_actions_proto protoreflect.FileDescriptor | ||||||
|  |  | ||||||
| var file_actions_proto_rawDesc = []byte{ | var file_actions_proto_rawDesc = []byte{ | ||||||
| 	0x0a, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, | 	0x0a, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, | ||||||
| 	0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x06, 0x41, 0x63, 0x74, | 	0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x97, 0x02, 0x0a, 0x06, 0x41, 0x63, 0x74, | ||||||
| 	0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, | 	0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, | ||||||
| 	0x0e, 0x32, 0x1a, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, | 	0x0e, 0x32, 0x1a, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, | ||||||
| 	0x6f, 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, | 	0x6f, 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, | ||||||
| @ -406,43 +476,62 @@ var file_actions_proto_rawDesc = []byte{ | |||||||
| 	0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, | 	0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, | ||||||
| 	0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, | 	0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, | ||||||
| 	0x63, 0x68, 0x61, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, | 	0x63, 0x68, 0x61, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, | ||||||
| 	0x28, 0x09, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, | 	0x28, 0x09, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, | ||||||
| 	0x30, 0x0a, 0x0a, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, | 	0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, | ||||||
| 	0x04, 0x4d, 0x4f, 0x56, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x48, 0x41, 0x54, 0x10, | 	0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, | ||||||
| 	0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, | 	0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, | ||||||
| 	0x02, 0x22, 0x69, 0x0a, 0x0b, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, | 	0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x49, 0x0a, 0x0a, 0x41, 0x63, 0x74, 0x69, 0x6f, | ||||||
| 	0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, | 	0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4f, 0x56, 0x45, 0x10, 0x00, 0x12, | ||||||
| 	0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x29, 0x0a, | 	0x08, 0x0a, 0x04, 0x43, 0x48, 0x41, 0x54, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x44, 0x49, 0x53, | ||||||
| 	0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, | 	0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x4f, 0x47, | ||||||
| 	0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, | 	0x49, 0x4e, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, | ||||||
| 	0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x63, 0x6b, | 	0x10, 0x04, 0x22, 0x94, 0x01, 0x0a, 0x0b, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x61, 0x74, | ||||||
| 	0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x69, 0x63, 0x6b, 0x22, 0x46, 0x0a, 0x0b, | 	0x63, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, | ||||||
| 	0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, | 	0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, | ||||||
| 	0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, | 	0x29, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, | ||||||
| 	0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x02, 0x20, | 	0x32, 0x0f, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, | ||||||
| 	0x01, 0x28, 0x05, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, | 	0x6e, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, | ||||||
| 	0x05, 0x52, 0x01, 0x79, 0x22, 0x62, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, | 	0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x69, 0x63, 0x6b, 0x12, 0x29, | ||||||
| 	0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x69, 0x64, | 	0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, | ||||||
| 	0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, | 	0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, | ||||||
| 	0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, | 	0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x62, 0x0a, 0x0b, 0x50, 0x6c, 0x61, | ||||||
| 	0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, | 	0x79, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x79, | ||||||
| 	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, | 	0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, | ||||||
| 	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xba, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x72, | 	0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, | ||||||
| 	0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6c, | 	0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x01, | ||||||
| 	0x61, 0x79, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, | 	0x79, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, | ||||||
| 	0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, | 	0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x7e, 0x0a, | ||||||
| 	0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, | 	0x0b, 0x43, 0x68, 0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, | ||||||
| 	0x6e, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x07, | 	0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, | ||||||
| 	0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, | 	0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, | ||||||
| 	0x6e, 0x74, 0x5f, 0x74, 0x69, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, | 	0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, | ||||||
| 	0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x12, 0x39, 0x0a, 0x0d, 0x63, 0x68, | 	0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, | ||||||
| 	0x61, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, | 	0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, | ||||||
| 	0x0b, 0x32, 0x14, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x68, 0x61, 0x74, | 	0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, | ||||||
| 	0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x74, 0x4d, 0x65, 0x73, | 	0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xad, 0x02, | ||||||
| 	0x73, 0x61, 0x67, 0x65, 0x73, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x65, 0x61, 0x2e, 0x62, | 	0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, | ||||||
| 	0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x62, 0x65, 0x2f, 0x62, 0x64, 0x6e, 0x75, 0x67, 0x67, 0x65, 0x74, | 	0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, | ||||||
| 	0x2f, 0x67, 0x6f, 0x6f, 0x6e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x61, 0x63, 0x74, 0x69, | 	0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x07, | ||||||
| 	0x6f, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | 	0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, | ||||||
|  | 	0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x53, 0x74, | ||||||
|  | 	0x61, 0x74, 0x65, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, | ||||||
|  | 	0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, | ||||||
|  | 	0x28, 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x12, | ||||||
|  | 	0x39, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, | ||||||
|  | 	0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, | ||||||
|  | 	0x2e, 0x43, 0x68, 0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0c, 0x63, 0x68, | ||||||
|  | 	0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x75, | ||||||
|  | 	0x74, 0x68, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, | ||||||
|  | 	0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x23, 0x0a, | ||||||
|  | 	0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, | ||||||
|  | 	0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, | ||||||
|  | 	0x67, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, | ||||||
|  | 	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x70, 0x72, | ||||||
|  | 	0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x2c, 0x5a, | ||||||
|  | 	0x2a, 0x67, 0x69, 0x74, 0x65, 0x61, 0x2e, 0x62, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x62, 0x65, 0x2f, | ||||||
|  | 	0x62, 0x64, 0x6e, 0x75, 0x67, 0x67, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x6f, 0x6e, 0x73, 0x65, 0x72, | ||||||
|  | 	0x76, 0x65, 0x72, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, | ||||||
|  | 	0x74, 0x6f, 0x33, | ||||||
| } | } | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
|  | |||||||
| @ -9,6 +9,8 @@ message Action { | |||||||
|         MOVE = 0; |         MOVE = 0; | ||||||
|         CHAT = 1; |         CHAT = 1; | ||||||
|         DISCONNECT = 2; |         DISCONNECT = 2; | ||||||
|  |         LOGIN = 3; | ||||||
|  |         REGISTER = 4; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ActionType type = 1; |     ActionType type = 1; | ||||||
| @ -16,24 +18,29 @@ message Action { | |||||||
|     int32 y = 3; |     int32 y = 3; | ||||||
|     int32 player_id = 4; |     int32 player_id = 4; | ||||||
|     string chat_message = 5; |     string chat_message = 5; | ||||||
|  |     string username = 6; | ||||||
|  |     string password = 7; | ||||||
| } | } | ||||||
|  |  | ||||||
| message ActionBatch { | message ActionBatch { | ||||||
|     int32 player_id = 1; |     int32 player_id = 1; | ||||||
|     repeated Action actions = 2; |     repeated Action actions = 2; | ||||||
|     int64 tick = 3; |     int64 tick = 3; | ||||||
|  |     int32 protocol_version = 4; | ||||||
| } | } | ||||||
|  |  | ||||||
| message PlayerState { | message PlayerState { | ||||||
|     int32 player_id = 1; |     int32 player_id = 1; | ||||||
|     int32 x = 2; |     int32 x = 2; | ||||||
|     int32 y = 3; |     int32 y = 3; | ||||||
|  |     string username = 4; | ||||||
| } | } | ||||||
|  |  | ||||||
| message ChatMessage { | message ChatMessage { | ||||||
|     int32 player_id = 1; |     int32 player_id = 1; | ||||||
|     string content = 2; |     string username = 2; | ||||||
|     int64 timestamp = 3; |     string content = 3; | ||||||
|  |     int64 timestamp = 4; | ||||||
| } | } | ||||||
|  |  | ||||||
| message ServerMessage { | message ServerMessage { | ||||||
| @ -41,4 +48,7 @@ message ServerMessage { | |||||||
|     repeated PlayerState players = 2; |     repeated PlayerState players = 2; | ||||||
|     int64 current_tick = 3; |     int64 current_tick = 3; | ||||||
|     repeated ChatMessage chat_messages = 4; |     repeated ChatMessage chat_messages = 4; | ||||||
|  |     bool auth_success = 5; | ||||||
|  |     string error_message = 6; | ||||||
|  |     int32 protocol_version = 7; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										128
									
								
								db/db.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								db/db.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,128 @@ | |||||||
|  | package db | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"crypto/sha256" | ||||||
|  | 	"database/sql" | ||||||
|  | 	"encoding/hex" | ||||||
|  | 	"errors" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	_ "github.com/mattn/go-sqlite3" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var db *sql.DB | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	ErrUserExists         = errors.New("username already exists") | ||||||
|  | 	ErrInvalidCredentials = errors.New("invalid username or password") | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func InitDB(dbPath string) error { | ||||||
|  | 	var err error | ||||||
|  | 	db, err = sql.Open("sqlite3", dbPath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Create tables if they don't exist | ||||||
|  | 	_, err = db.Exec(` | ||||||
|  | 		CREATE TABLE IF NOT EXISTS players ( | ||||||
|  | 			id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|  | 			username TEXT UNIQUE NOT NULL, | ||||||
|  | 			password_hash TEXT NOT NULL, | ||||||
|  | 			created_at DATETIME NOT NULL | ||||||
|  | 		); | ||||||
|  |  | ||||||
|  | 		CREATE TABLE IF NOT EXISTS player_states ( | ||||||
|  | 			player_id INTEGER PRIMARY KEY, | ||||||
|  | 			x INTEGER NOT NULL, | ||||||
|  | 			y INTEGER NOT NULL, | ||||||
|  | 			last_seen DATETIME NOT NULL, | ||||||
|  | 			FOREIGN KEY(player_id) REFERENCES players(id) | ||||||
|  | 		); | ||||||
|  | 	`) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func hashPassword(password string) string { | ||||||
|  | 	hash := sha256.Sum256([]byte(password)) | ||||||
|  | 	return hex.EncodeToString(hash[:]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func RegisterPlayer(username, password string) (int, error) { | ||||||
|  | 	// Check if username exists | ||||||
|  | 	var exists bool | ||||||
|  | 	err := db.QueryRow("SELECT EXISTS(SELECT 1 FROM players WHERE username = ?)", username).Scan(&exists) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	if exists { | ||||||
|  | 		return 0, ErrUserExists | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Create new player | ||||||
|  | 	result, err := db.Exec(` | ||||||
|  | 		INSERT INTO players (username, password_hash, created_at) | ||||||
|  | 		VALUES (?, ?, ?)`, | ||||||
|  | 		username, hashPassword(password), time.Now().UTC(), | ||||||
|  | 	) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	id, err := result.LastInsertId() | ||||||
|  | 	return int(id), err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func AuthenticatePlayer(username, password string) (int, error) { | ||||||
|  | 	var id int | ||||||
|  | 	var storedHash string | ||||||
|  | 	err := db.QueryRow(` | ||||||
|  | 		SELECT id, password_hash  | ||||||
|  | 		FROM players  | ||||||
|  | 		WHERE username = ?`, | ||||||
|  | 		username, | ||||||
|  | 	).Scan(&id, &storedHash) | ||||||
|  |  | ||||||
|  | 	if err == sql.ErrNoRows { | ||||||
|  | 		return 0, ErrInvalidCredentials | ||||||
|  | 	} | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if storedHash != hashPassword(password) { | ||||||
|  | 		return 0, ErrInvalidCredentials | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return id, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func SavePlayerState(playerID int, x, y int) error { | ||||||
|  | 	_, err := db.Exec(` | ||||||
|  | 		INSERT OR REPLACE INTO player_states ( | ||||||
|  | 			player_id, x, y, last_seen | ||||||
|  | 		) VALUES (?, ?, ?, ?)`, | ||||||
|  | 		playerID, x, y, time.Now().UTC(), | ||||||
|  | 	) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func LoadPlayerState(playerID int) (x, y int, err error) { | ||||||
|  | 	err = db.QueryRow(` | ||||||
|  | 		SELECT x, y FROM player_states  | ||||||
|  | 		WHERE player_id = ?`, | ||||||
|  | 		playerID, | ||||||
|  | 	).Scan(&x, &y) | ||||||
|  | 	if err == sql.ErrNoRows { | ||||||
|  | 		// Return default position for new players | ||||||
|  | 		return 5, 5, nil | ||||||
|  | 	} | ||||||
|  | 	return x, y, err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func GetUsername(playerID int) (string, error) { | ||||||
|  | 	var username string | ||||||
|  | 	err := db.QueryRow("SELECT username FROM players WHERE id = ?", playerID).Scan(&username) | ||||||
|  | 	return username, err | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								go.mod
									
									
									
									
									
								
							| @ -2,4 +2,7 @@ module gitea.boner.be/bdnugget/goonserver | |||||||
|  |  | ||||||
| go 1.23.0 | go 1.23.0 | ||||||
|  |  | ||||||
| require google.golang.org/protobuf v1.36.3 | require ( | ||||||
|  | 	github.com/mattn/go-sqlite3 v1.14.24 | ||||||
|  | 	google.golang.org/protobuf v1.36.3 | ||||||
|  | ) | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							| @ -1,5 +1,7 @@ | |||||||
| github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= | ||||||
| github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||||
|  | github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= | ||||||
|  | github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= | google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= | ||||||
|  | |||||||
							
								
								
									
										187
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										187
									
								
								main.go
									
									
									
									
									
								
							| @ -11,6 +11,7 @@ import ( | |||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	pb "gitea.boner.be/bdnugget/goonserver/actions" | 	pb "gitea.boner.be/bdnugget/goonserver/actions" | ||||||
|  | 	"gitea.boner.be/bdnugget/goonserver/db" | ||||||
|  |  | ||||||
| 	"google.golang.org/protobuf/proto" | 	"google.golang.org/protobuf/proto" | ||||||
| ) | ) | ||||||
| @ -18,12 +19,14 @@ import ( | |||||||
| const ( | const ( | ||||||
| 	port         = ":6969" // Port to listen on | 	port         = ":6969" // Port to listen on | ||||||
| 	tickRate     = 600 * time.Millisecond | 	tickRate     = 600 * time.Millisecond | ||||||
|  | 	protoVersion = 1 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type Player struct { | type Player struct { | ||||||
| 	sync.Mutex | 	sync.Mutex | ||||||
| 	ID       int | 	ID       int | ||||||
| 	X, Y int // Position on the game grid | 	X, Y     int | ||||||
|  | 	Username string | ||||||
| } | } | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| @ -33,9 +36,14 @@ var ( | |||||||
| 	mu           sync.RWMutex                 // Add mutex for protecting shared maps | 	mu           sync.RWMutex                 // Add mutex for protecting shared maps | ||||||
| 	chatHistory  = make([]*pb.ChatMessage, 0, 100) | 	chatHistory  = make([]*pb.ChatMessage, 0, 100) | ||||||
| 	chatMutex    sync.RWMutex | 	chatMutex    sync.RWMutex | ||||||
|  | 	nextPlayerID = 1 // Assuming player IDs start from 1 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func main() { | func main() { | ||||||
|  | 	if err := db.InitDB("goonserver.db"); err != nil { | ||||||
|  | 		log.Fatalf("Failed to initialize database: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	ln, err := net.Listen("tcp", port) | 	ln, err := net.Listen("tcp", port) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatalf("Failed to listen on port %s: %v", port, err) | 		log.Fatalf("Failed to listen on port %s: %v", port, err) | ||||||
| @ -68,34 +76,162 @@ func main() { | |||||||
| func handleConnection(conn net.Conn) { | func handleConnection(conn net.Conn) { | ||||||
| 	defer conn.Close() | 	defer conn.Close() | ||||||
|  |  | ||||||
| 	mu.Lock() | 	// Read initial message for player ID | ||||||
| 	playerID := len(players) + 1 | 	reader := bufio.NewReader(conn) | ||||||
| 	newPlayer := &Player{ID: playerID, X: 5, Y: 5} |  | ||||||
| 	players[playerID] = newPlayer |  | ||||||
| 	playerConns[playerID] = conn |  | ||||||
| 	mu.Unlock() |  | ||||||
| 	fmt.Printf("Player %d connected\n", playerID) |  | ||||||
|  |  | ||||||
| 	// Send player ID to the client | 	// Wait for authentication | ||||||
| 	serverMsg := &pb.ServerMessage{ | 	lengthBuf := make([]byte, 4) | ||||||
| 		PlayerId:    int32(playerID), | 	if _, err := io.ReadFull(reader, lengthBuf); err != nil { | ||||||
| 		CurrentTick: 0, | 		log.Printf("Failed to read auth message length: %v", err) | ||||||
|  | 		return | ||||||
| 	} | 	} | ||||||
| 	if err := writeMessage(conn, serverMsg); err != nil { | 	messageLength := binary.BigEndian.Uint32(lengthBuf) | ||||||
| 		log.Printf("Failed to send player ID to player %d: %v", playerID, err) |  | ||||||
|  | 	messageBuf := make([]byte, messageLength) | ||||||
|  | 	if _, err := io.ReadFull(reader, messageBuf); err != nil { | ||||||
|  | 		log.Printf("Failed to read auth message: %v", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	batch := &pb.ActionBatch{} | ||||||
|  | 	if err := proto.Unmarshal(messageBuf, batch); err != nil { | ||||||
|  | 		log.Printf("Failed to unmarshal auth message: %v", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(batch.Actions) == 0 { | ||||||
|  | 		log.Printf("No auth action received") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	action := batch.Actions[0] | ||||||
|  | 	var playerID int | ||||||
|  | 	var authErr error | ||||||
|  |  | ||||||
|  | 	if batch.ProtocolVersion == 0 { | ||||||
|  | 		response := &pb.ServerMessage{ | ||||||
|  | 			AuthSuccess:     false, | ||||||
|  | 			ErrorMessage:    "Client using outdated protocol (pre-versioning)", | ||||||
|  | 			ProtocolVersion: protoVersion, | ||||||
|  | 		} | ||||||
|  | 		writeMessage(conn, response) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if batch.ProtocolVersion < protoVersion { | ||||||
|  | 		response := &pb.ServerMessage{ | ||||||
|  | 			AuthSuccess:     false, | ||||||
|  | 			ErrorMessage:    fmt.Sprintf("Client protocol version too old (client: %d, required: %d)", batch.ProtocolVersion, protoVersion), | ||||||
|  | 			ProtocolVersion: protoVersion, | ||||||
|  | 		} | ||||||
|  | 		writeMessage(conn, response) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	switch action.Type { | ||||||
|  | 	case pb.Action_REGISTER: | ||||||
|  | 		playerID, authErr = db.RegisterPlayer(action.Username, action.Password) | ||||||
|  | 	case pb.Action_LOGIN: | ||||||
|  | 		playerID, authErr = db.AuthenticatePlayer(action.Username, action.Password) | ||||||
|  | 	default: | ||||||
|  | 		log.Printf("Invalid initial action type: %v", action.Type) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Send auth response | ||||||
|  | 	response := &pb.ServerMessage{ | ||||||
|  | 		PlayerId:    int32(playerID), | ||||||
|  | 		AuthSuccess: authErr == nil, | ||||||
|  | 	} | ||||||
|  | 	if authErr != nil { | ||||||
|  | 		response.ErrorMessage = authErr.Error() | ||||||
|  | 		if err := writeMessage(conn, response); err != nil { | ||||||
|  | 			log.Printf("Failed to send auth response: %v", err) | ||||||
|  | 		} | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Load last known position | ||||||
|  | 	x, y, err := db.LoadPlayerState(playerID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Printf("Error loading state for player %d: %v", playerID, err) | ||||||
|  | 		x, y = 5, 5 // Default position | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	username, err := db.GetUsername(playerID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Printf("Error getting username for player %d: %v", playerID, err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	player := &Player{ | ||||||
|  | 		ID:       playerID, | ||||||
|  | 		X:        x, | ||||||
|  | 		Y:        y, | ||||||
|  | 		Username: username, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Prevent multiple logins | ||||||
|  | 	mu.Lock() | ||||||
|  | 	for _, p := range players { | ||||||
|  | 		if p.Username == username { | ||||||
|  | 			mu.Unlock() | ||||||
|  | 			response := &pb.ServerMessage{ | ||||||
|  | 				AuthSuccess:  false, | ||||||
|  | 				ErrorMessage: "Account already logged in", | ||||||
|  | 			} | ||||||
|  | 			writeMessage(conn, response) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	players[playerID] = player | ||||||
|  | 	playerConns[playerID] = conn | ||||||
|  | 	mu.Unlock() | ||||||
|  |  | ||||||
|  | 	// Send initial state with correct position | ||||||
|  | 	response = &pb.ServerMessage{ | ||||||
|  | 		PlayerId:    int32(playerID), | ||||||
|  | 		AuthSuccess: true, | ||||||
|  | 		Players: []*pb.PlayerState{{ | ||||||
|  | 			PlayerId: int32(playerID), | ||||||
|  | 			X:        int32(x), | ||||||
|  | 			Y:        int32(y), | ||||||
|  | 			Username: username, | ||||||
|  | 		}}, | ||||||
|  | 		ProtocolVersion: protoVersion, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Ensure player state is saved on any kind of disconnect | ||||||
|  | 	defer func() { | ||||||
|  | 		if err := db.SavePlayerState(playerID, player.X, player.Y); err != nil { | ||||||
|  | 			log.Printf("Error saving state for player %d: %v", playerID, err) | ||||||
|  | 		} | ||||||
|  | 		mu.Lock() | ||||||
|  | 		delete(players, playerID) | ||||||
|  | 		delete(playerConns, playerID) | ||||||
|  | 		delete(actionQueue, playerID) | ||||||
|  | 		mu.Unlock() | ||||||
|  | 		log.Printf("Player %d disconnected", playerID) | ||||||
|  | 	}() | ||||||
|  |  | ||||||
|  | 	// Send player ID to client | ||||||
|  | 	if err := writeMessage(conn, response); err != nil { | ||||||
|  | 		log.Printf("Failed to send player ID: %v", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Printf("Player %d connected\n", playerID) | ||||||
|  |  | ||||||
| 	// Listen for incoming actions from this player | 	// Listen for incoming actions from this player | ||||||
| 	reader := bufio.NewReader(conn) |  | ||||||
| 	for { | 	for { | ||||||
| 		// Read message length | 		// Read message length | ||||||
| 		lengthBuf := make([]byte, 4) | 		lengthBuf := make([]byte, 4) | ||||||
| 		if _, err := io.ReadFull(reader, lengthBuf); err != nil { | 		if _, err := io.ReadFull(reader, lengthBuf); err != nil { | ||||||
|  | 			if err == io.EOF { | ||||||
|  | 				log.Printf("Player %d disconnected gracefully", playerID) | ||||||
|  | 			} else { | ||||||
| 				log.Printf("Error reading message length from player %d: %v", playerID, err) | 				log.Printf("Error reading message length from player %d: %v", playerID, err) | ||||||
| 			delete(players, playerID) | 			} | ||||||
| 			delete(playerConns, playerID) |  | ||||||
| 			delete(actionQueue, playerID) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		messageLength := binary.BigEndian.Uint32(lengthBuf) | 		messageLength := binary.BigEndian.Uint32(lengthBuf) | ||||||
| @ -104,9 +240,6 @@ func handleConnection(conn net.Conn) { | |||||||
| 		messageBuf := make([]byte, messageLength) | 		messageBuf := make([]byte, messageLength) | ||||||
| 		if _, err := io.ReadFull(reader, messageBuf); err != nil { | 		if _, err := io.ReadFull(reader, messageBuf); err != nil { | ||||||
| 			log.Printf("Error reading message from player %d: %v", playerID, err) | 			log.Printf("Error reading message from player %d: %v", playerID, err) | ||||||
| 			delete(players, playerID) |  | ||||||
| 			delete(playerConns, playerID) |  | ||||||
| 			delete(actionQueue, playerID) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -120,10 +253,7 @@ func handleConnection(conn net.Conn) { | |||||||
| 		if batch.PlayerId == int32(playerID) { | 		if batch.PlayerId == int32(playerID) { | ||||||
| 			for _, action := range batch.Actions { | 			for _, action := range batch.Actions { | ||||||
| 				if action.Type == pb.Action_DISCONNECT { | 				if action.Type == pb.Action_DISCONNECT { | ||||||
| 					log.Printf("Player %d disconnected gracefully", playerID) | 					log.Printf("Player %d requested disconnect", playerID) | ||||||
| 					delete(players, playerID) |  | ||||||
| 					delete(playerConns, playerID) |  | ||||||
| 					delete(actionQueue, playerID) |  | ||||||
| 					return | 					return | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @ -133,11 +263,17 @@ func handleConnection(conn net.Conn) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func addChatMessage(playerID int32, content string) { | func addChatMessage(playerID int32, content string) { | ||||||
|  | 	player, exists := players[int(playerID)] | ||||||
|  | 	if !exists { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	chatMutex.Lock() | 	chatMutex.Lock() | ||||||
| 	defer chatMutex.Unlock() | 	defer chatMutex.Unlock() | ||||||
|  |  | ||||||
| 	msg := &pb.ChatMessage{ | 	msg := &pb.ChatMessage{ | ||||||
| 		PlayerId:  playerID, | 		PlayerId:  playerID, | ||||||
|  | 		Username:  player.Username, | ||||||
| 		Content:   content, | 		Content:   content, | ||||||
| 		Timestamp: time.Now().UnixNano(), | 		Timestamp: time.Now().UnixNano(), | ||||||
| 	} | 	} | ||||||
| @ -185,6 +321,7 @@ func processActions() { | |||||||
| 			PlayerId: int32(id), | 			PlayerId: int32(id), | ||||||
| 			X:        int32(p.X), | 			X:        int32(p.X), | ||||||
| 			Y:        int32(p.Y), | 			Y:        int32(p.Y), | ||||||
|  | 			Username: p.Username, | ||||||
| 		}) | 		}) | ||||||
| 		p.Unlock() | 		p.Unlock() | ||||||
| 	} | 	} | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user