Skip to content

Commit

Permalink
Merge pull request #197 from robinje/bloomfilter
Browse files Browse the repository at this point in the history
New Character Name Checking
  • Loading branch information
robinje authored Sep 23, 2024
2 parents a41c300 + a5ce993 commit 76dc933
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 27 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -47,8 +60,9 @@ 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.
- [ ] Add the ability to delete accounts.
- [ ] Implement an obscenity filter.
Expand Down
35 changes: 35 additions & 0 deletions core/character.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 2 additions & 0 deletions core/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions core/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
43 changes: 22 additions & 21 deletions core/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -54,27 +55,27 @@ 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
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 {
Expand Down
2 changes: 2 additions & 0 deletions ssh_server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions ssh_server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit 76dc933

Please sign in to comment.