From 8e467919190a73f850c9c2e1ece02426b29837a4 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Sat, 21 Sep 2024 21:22:02 -0400 Subject: [PATCH 1/4] Add Character Name Bloom Filter --- core/character.go | 35 +++++++++++++++++++++++++++++++++++ core/go.mod | 2 ++ core/types.go | 44 +++++++++++++++++++++++--------------------- ssh_server/go.mod | 2 ++ 4 files changed, 62 insertions(+), 21 deletions(-) diff --git a/core/character.go b/core/character.go index 192e6f1..5248e67 100644 --- a/core/character.go +++ b/core/character.go @@ -7,9 +7,12 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" + "github.com/bits-and-blooms/bloom/v3" "github.com/google/uuid" ) +const FalsePositiveRate = 0.01 // 1% false positive rate + // WearLocations defines all possible locations where an item can be worn var WearLocations = map[string]bool{ "head": true, @@ -94,6 +97,8 @@ func (s *Server) NewCharacter(name string, player *Player, room *Room, archetype Server: s, } + s.AddCharacterName(name) + if archetypeName != "" { if archetype, ok := s.Archetypes.Archetypes[archetypeName]; ok { character.Attributes = make(map[string]float64) @@ -192,6 +197,36 @@ func (kp *KeyPair) LoadCharacterNames() (map[string]bool, error) { return names, nil } +func (server *Server) InitializeBloomFilter() error { + characterNames, err := server.Database.LoadCharacterNames() + if err != nil { + return fmt.Errorf("failed to load character names: %w", err) + } + + n := uint(len(characterNames)) + fpRate := FalsePositiveRate + + server.CharacterBloomFilter = bloom.NewWithEstimates(n, fpRate) + + for name := range characterNames { + server.CharacterBloomFilter.Add([]byte(strings.ToLower(name))) + } + + return nil +} + +func (server *Server) AddCharacterName(name string) { + server.Mutex.Lock() + defer server.Mutex.Unlock() + + server.CharacterBloomFilter.AddString(strings.ToLower(name)) +} + +func (server *Server) CharacterNameExists(name string) bool { + + return server.CharacterBloomFilter.TestString(strings.ToLower(name)) +} + func SaveActiveCharacters(s *Server) error { s.Mutex.Lock() defer s.Mutex.Unlock() diff --git a/core/go.mod b/core/go.mod index 3379b4e..78d25ad 100644 --- a/core/go.mod +++ b/core/go.mod @@ -9,6 +9,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.40.5 github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.37.5 github.com/aws/aws-xray-sdk-go v1.8.4 + github.com/bits-and-blooms/bloom/v3 v3.7.0 github.com/google/uuid v1.6.0 golang.org/x/crypto v0.24.0 ) @@ -27,6 +28,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.30.5 // indirect github.com/aws/smithy-go v1.20.4 // indirect + github.com/bits-and-blooms/bitset v1.14.3 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/klauspost/compress v1.17.2 // indirect diff --git a/core/types.go b/core/types.go index aaf9fcb..5b6b9bf 100644 --- a/core/types.go +++ b/core/types.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs" "github.com/aws/aws-sdk-go/service/dynamodb" + "github.com/bits-and-blooms/bloom/v3" "github.com/google/uuid" "golang.org/x/crypto/ssh" ) @@ -54,27 +55,28 @@ type KeyPair struct { } type Server struct { - Port uint16 - Listener net.Listener - SSHConfig *ssh.ServerConfig - PlayerCount uint64 - Config Configuration - StartTime time.Time - Rooms map[int64]*Room - Database *KeyPair - PlayerIndex *Index - CharacterExists map[string]bool - Characters map[uuid.UUID]*Character - Balance float64 - AutoSave uint16 - Archetypes *ArchetypesData - Health uint16 - Essence uint16 - Items map[uint64]*Item - ItemPrototypes map[uint64]*Item - Context context.Context - Mutex sync.Mutex - ActiveMotDs []*MOTD + Port uint16 + Listener net.Listener + SSHConfig *ssh.ServerConfig + PlayerCount uint64 + Config Configuration + StartTime time.Time + Rooms map[int64]*Room + Database *KeyPair + PlayerIndex *Index + CharacterExists map[string]bool // Remove + CharacterBloomFilter *bloom.BloomFilter + Characters map[uuid.UUID]*Character + Balance float64 + AutoSave uint16 + Archetypes *ArchetypesData + Health uint16 + Essence uint16 + Items map[uint64]*Item + ItemPrototypes map[uint64]*Item + Context context.Context + Mutex sync.Mutex + ActiveMotDs []*MOTD } type Player struct { diff --git a/ssh_server/go.mod b/ssh_server/go.mod index 92f2e17..9d9ed25 100644 --- a/ssh_server/go.mod +++ b/ssh_server/go.mod @@ -31,6 +31,8 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.30.5 // indirect github.com/aws/aws-xray-sdk-go v1.8.4 // indirect github.com/aws/smithy-go v1.20.4 // indirect + github.com/bits-and-blooms/bitset v1.14.3 // indirect + github.com/bits-and-blooms/bloom/v3 v3.7.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/klauspost/compress v1.17.2 // indirect From b0541596ae587b9fa441400e1e577739daa79987 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Sat, 21 Sep 2024 21:26:39 -0400 Subject: [PATCH 2/4] Impliment Character Name Bloom Filter --- core/player.go | 4 ++-- core/types.go | 1 - ssh_server/server.go | 5 +++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/player.go b/core/player.go index b45a6d1..8eb5d60 100644 --- a/core/player.go +++ b/core/player.go @@ -306,8 +306,8 @@ func CreateCharacter(player *Player, server *Server) (*Character, error) { return nil, fmt.Errorf("character name must be 15 characters or fewer") } - if server.CharacterExists[strings.ToLower(charName)] { - return nil, fmt.Errorf("character already exists") + if server.CharacterNameExists(charName) { + return nil, fmt.Errorf("character name already exists") } var selectedArchetype string diff --git a/core/types.go b/core/types.go index 5b6b9bf..c66f350 100644 --- a/core/types.go +++ b/core/types.go @@ -64,7 +64,6 @@ type Server struct { Rooms map[int64]*Room Database *KeyPair PlayerIndex *Index - CharacterExists map[string]bool // Remove CharacterBloomFilter *bloom.BloomFilter Characters map[uuid.UUID]*Character Balance float64 diff --git a/ssh_server/server.go b/ssh_server/server.go index 59cf4ee..6e7b593 100644 --- a/ssh_server/server.go +++ b/ssh_server/server.go @@ -49,9 +49,10 @@ func NewServer(config core.Configuration) (*core.Server, error) { core.Logger.Info("Loading character names from database...") - server.CharacterExists, err = server.Database.LoadCharacterNames() + // Load the bloom filter from the database + err = server.InitializeBloomFilter() if err != nil { - core.Logger.Error("Error loading character names from database", "error", err) + core.Logger.Error("Error initializing bloom filter", "error", err) } server.Archetypes, err = server.Database.LoadArchetypes() From 1a6c5f9c104bc3b0754702c5862f6197f7bb9255 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Sat, 21 Sep 2024 21:28:03 -0400 Subject: [PATCH 3/4] Update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0941e78..08c4815 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ The current implementation includes an SSH server for secure authentication and - [x] Create function for creating items from prototypes. - [x] Ensure that a message is passed when a characters is added to the game. - [x] Add a Message of the Day (MOTD) command. +- [x] Add Bloom Filter to check for existing characters names being used. - [ ] Add the ability to delete characters. - [ ] Add the ability to delete accounts. - [ ] Implement an obscenity filter. From deaae9647a7c21e8189cde8e6bb1b0fb89d2680a Mon Sep 17 00:00:00 2001 From: "Jason E. Robinson" Date: Sun, 22 Sep 2024 19:00:52 -0400 Subject: [PATCH 4/4] Update ReadME --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 08c4815..d6ef393 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,16 @@ +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white) +![Dependabot](https://img.shields.io/badge/dependabot-025E8C?style=for-the-badge&logo=dependabot&logoColor=white) +![GitHub Actions](https://img.shields.io/badge/github%20actions-%232671E5.svg?style=for-the-badge&logo=githubactions&logoColor=white) +![AWS](https://img.shields.io/badge/AWS-%23FF9900.svg?style=for-the-badge&logo=amazon-aws&logoColor=white) +![AmazonDynamoDB](https://img.shields.io/badge/Amazon%20DynamoDB-4053D6?style=for-the-badge&logo=Amazon%20DynamoDB&logoColor=white) +![Webpack](https://img.shields.io/badge/webpack-%238DD6F9.svg?style=for-the-badge&logo=webpack&logoColor=black) +![Go](https://img.shields.io/badge/go-%2300ADD8.svg?style=for-the-badge&logo=go&logoColor=white) +![Python](https://img.shields.io/badge/python-3670A0?style=for-the-badge&logo=python&logoColor=ffdd54) +![JavaScript](https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E) +![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black) +![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=white) + # Multi-User Dungeon Engine The goal of this project is to create a commercial-quality multi-user dungeon (MUD) engine that is flexible enough to be used as either a conventional MUD or an interactive fiction game. @@ -16,7 +29,7 @@ The current implementation includes an SSH server for secure authentication and - [x] Build an interactive password change system. - [ ] Construct the item system. - [ ] Develop game mechanics. -- [ ] Design an ecenomic framework. +- [ ] Design an economic framework - [ ] Implement a world creation system. - [ ] Develop simple Non-Player Characters (NPCs). - [ ] Design and implement a quest system. @@ -47,7 +60,7 @@ The current implementation includes an SSH server for secure authentication and - [x] Implement Persistent Logging. - [x] Load item prototypes at start. - [x] Create function for creating items from prototypes. -- [x] Ensure that a message is passed when a characters is added to the game. +- [x] Ensure that a message is passed when a character is added to the game. - [x] Add a Message of the Day (MOTD) command. - [x] Add Bloom Filter to check for existing characters names being used. - [ ] Add the ability to delete characters.