Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions _datafiles/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,9 @@ LocalPort: 9999
# - WebPort -
# The port the server listens on for web requests
WebPort: 80
# - MspFileUrl -
# The base URL sound files are played from
MspFileUrl: http://localhost/static/public/audio/
################################################################################
#
# LOOT GOBLIN CONFIGURATIONS
Expand Down
79 changes: 79 additions & 0 deletions _datafiles/html/public/webclient.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
<link rel="stylesheet" href="/static/public/css/xterm.css" />
<script src="/static/public/js/xterm.4.19.0.js"></script>
<script src="/static/public/js/xterm-addon-fit.js"></script>
<script src="/static/public/js/mp3.js"></script>
</head>
<body onLoad="init(); return false;">
<div id="main-container">
Expand All @@ -97,6 +98,11 @@

<script>

// Music/Sound players:
let baseMp3Url = "";
const MusicPlayer = new MP3Player(false);
const SoundPlayer = new MP3Player(true);

/////////////////////////////////////////////
//
// Terminal emulation setup
Expand Down Expand Up @@ -239,6 +245,79 @@
}
}

// Is it an MSP command?
if ( event.data.length > 9 && event.data.slice(0, 2) == "!!" ) {

if ( event.data.slice(0, 8) == "!!MUSIC(" ) {

parts = event.data.slice(8, event.data.length-1).split(" ");
fileName = parts[0];
obj = {};
for ( i=1; i<parts.length; i++) {
prop = parts[i].split("=");
if ( prop.length == 2 ) {
obj[prop[0]] = prop[1];
}
}

if ( fileName == "Off" ) {
if ( obj.U ) {
baseMp3Url = obj.U;
if ( baseMp3Url[baseMp3Url.length-1] != "/" ) {
baseMp3Url += "/";
}
} else {
MusicPlayer.stop();
}

} else {

soundLevel = 1.0;
loopMusic = true;

if ( obj.L && obj.L != "-1" ) {
Loop = false;
}
if ( obj.V ) {
soundLevel = Number(obj.V)/100;
}

if ( !MusicPlayer.isPlaying(baseMp3Url+fileName) ) {
MusicPlayer.play(baseMp3Url+fileName, loopMusic, soundLevel);
}
}

} else if ( event.data.slice(0, 8) == "!!SOUND(" ) {

parts = event.data.slice(8, event.data.length-1).split(" ");
fileName = parts[0];
obj = {};
for ( i=1; i<parts.length; i++) {
prop = parts[i].split("=");
if ( prop.length == 2 ) {
obj[prop[0]] = prop[1];
}
}

if ( fileName == "Off" ) {
if ( obj.U ) {
baseMp3Url = obj.U;
if ( baseMp3Url[baseMp3Url.length-1] != "/" ) {
baseMp3Url += "/";
}
} else {
SoundPlayer.stop();
}

} else {
SoundPlayer.play(baseMp3Url+fileName, true, 1.0);
}

}
return
}


term.write(event.data);

};
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
82 changes: 82 additions & 0 deletions _datafiles/html/static/public/js/mp3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
class MP3Player {
constructor(allowMultiple = false) {
this.audioCache = new Map();
this.currentUrl = null;
this.loop = true;
this.allowMultiple = allowMultiple;
this.activeAudios = new Set();
}

play(url, loop = true, volume = 1.0) {
if (!this.allowMultiple) {
this.stopAll();
}

let audio;
if (this.audioCache.has(url)) {
audio = this.audioCache.get(url);
} else {
audio = new Audio();
audio.src = url;
audio.preload = "auto";
this.audioCache.set(url, audio);
}

audio.loop = loop;
audio.volume = volume;
audio.play().catch((e) => console.error("Playback failed:", e));
this.activeAudios.add(audio);
this.currentUrl = url;
}

pause(url) {
if (this.audioCache.has(url)) {
this.audioCache.get(url).pause();
}
}

stop(url) {
if (this.audioCache.has(url)) {
let audio = this.audioCache.get(url);
audio.pause();
audio.currentTime = 0;
this.activeAudios.delete(audio);
}
}

stopAll() {
this.activeAudios.forEach(audio => {
audio.pause();
audio.currentTime = 0;
});
this.activeAudios.clear();
}

setVolume(url, level) {
if (level < 0 || level > 1) {
console.error("Volume must be between 0 and 1");
return;
}
if (this.audioCache.has(url)) {
this.audioCache.get(url).volume = level;
}
}

setLoop(url, loop) {
if (this.audioCache.has(url)) {
this.audioCache.get(url).loop = loop;
}
}

isPlaying(url) {
return this.audioCache.has(url) && !this.audioCache.get(url).paused;
}

getCurrentTime(url) {
return this.audioCache.has(url) ? this.audioCache.get(url).currentTime : 0;
}

getDuration(url) {
return this.audioCache.has(url) ? this.audioCache.get(url).duration : 0;
}
}
1 change: 1 addition & 0 deletions _datafiles/world/default/rooms/catacombs/32.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ zoneconfig:
autoscale:
minimum: 8
maximum: 13
musicfile: music/catacombs.mp3
title: Entrance to the Catacombs
description: Beneath the Sanctuary of the Benevolent Heart lies the labyrinthine expanse
known as the Catacombs. A network of narrow, winding tunnels and chambers, the Catacombs
Expand Down
1 change: 1 addition & 0 deletions _datafiles/world/default/rooms/dark_forest/300.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ zoneconfig:
roomid: 300
mutators:
- mutatorid: forest-mist
musicfile: music/dark-forest.mp3
title: Forest Road
description: As you venture further along the old road, it leads you into the heart
of the foreboding Dark Forest. The transition from the tranquil Frost Lake to this
Expand Down
1 change: 1 addition & 0 deletions _datafiles/world/default/rooms/frost_lake/304.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ zoneconfig:
autoscale:
minimum: 10
maximum: 13
musicfile: music/frost-lake.mp3
title: Frost Lake Shore
description: The stillness here is profound, the world holding its breath in reverence
for this enchanting realm. The silence is broken only by the soft, melodic chime
Expand Down
1 change: 1 addition & 0 deletions _datafiles/world/default/rooms/frostfang/1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ zoneconfig:
autoscale:
minimum: 1
maximum: 5
musicfile: music/frostfang.mp3
title: Town Square
description: In the shimmering heart of Frostfang, a city wrapped in a perpetual blanket
of snow and illuminated by the ethereal glow of the auroras, lies the Town Square.
Expand Down
1 change: 1 addition & 0 deletions _datafiles/world/default/rooms/frostfang_slums/439.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ zoneconfig:
maximum: 10
mutators:
- mutatorid: pvp-enabled
musicfile: music/frostfang-slums.mp3
title: Poorly Lit Street
description: 'Tucked away in the heart of Frostfang''s sprawling slums, a dimly lit
alleyway meanders from the bustling Beggars Lane. This concealed corner, a world
Expand Down
1 change: 1 addition & 0 deletions _datafiles/world/default/rooms/mirror_caves/218.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ roomid: 218
zone: Mirror Caves
zoneconfig:
roomid: 218
musicfile: music/mirror-caves.mp3
title: Cave Entrance
description: "As you cautiously step into the entrance of the mirror caves, a chilling
draft greets you, carrying the faint scent of earth and ancient stone. The cave's
Expand Down
1 change: 1 addition & 0 deletions _datafiles/world/default/rooms/mystarion/612.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ roomid: 612
zone: Mystarion
zoneconfig:
roomid: 612
musicfile: music/mystarion.mp3
title: Main road
description: The road itself becomes a cobblestone path, the stones worn smooth by
centuries of use, each one seemingly placed with intention, leading inexorably towards
Expand Down
1 change: 1 addition & 0 deletions _datafiles/world/default/rooms/stormshards/575.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ roomid: 575
zone: Stormshards
zoneconfig:
roomid: 575
musicfile: music/stormshards.mp3
title: Mountain path
description: As the path ascends, the terrain becomes more rugged; the trees thin
out, giving way to rocky outcrops and steep, craggy inclines. The earth underfoot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ zoneconfig:
autoscale:
minimum: 15
maximum: 25
musicfile: music/whispering-wastes.mp3
title: Stormwatchers Keep
description: The Halls of Stormwatchers Keep are a labyrinthine network of grand corridors
and chambers carved into the heart of a colossal glacier. Each hall is adorned with
Expand Down
1 change: 1 addition & 0 deletions _datafiles/world/default/rooms/sun_anvil/1000.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ zoneconfig:
roomid: 1000
mutators:
- mutatorid: desert-sun
musicfile: music/sun-anvil.mp3
title: Desert's Edge
description: You find yourself at the threshold of the Sun Anvil Desert, where the
air itself seems to shimmer under the relentless glare of a merciless sun. The ground
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ zoneconfig:
maximum: 15
mutators:
- mutatorid: freezing-cold
musicfile: music/whispering-wastes.mp3
title: Frozen Wasteland
description: The relentless blizzard swallows the world in a veil of white. The sky,
a perpetual twilight, casts a surreal glow over the endless expanse of snow and
Expand Down
22 changes: 20 additions & 2 deletions _datafiles/world/default/templates/help/about.template
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ or modified to build your own world using built-in tools.
<ansi fg="187">:::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187"></ansi>
' `--' `.-' `--' `--' `--' `-.' `--' `</ansi>

<ansi fg="black-bold">.:</ansi> <ansi fg="magenta"></ansi><ansi fg="command">GoMud</ansi> History
<ansi fg="black-bold">.:</ansi> <ansi fg="magenta"><ansi fg="command">GoMud</ansi> History</ansi>

<ansi fg="command">GoMud</ansi> development began in <ansi fg="red">late 2023</ansi> with several key goals in mind:
<ansi fg="command">GoMud</ansi> development began in <ansi fg="red">late 2023</ansi> by <ansi fg="14">Dylan Squires</ansi> (aka <ansi fg="11">Volte6</ansi>) with
several key goals in mind:

<ansi fg="red-bold">1.</ansi> <ansi fg="11">Offer a new, free code base in a modern language.</ansi>
<ansi fg="command">Go</ansi> was selected as it has a fast build process and excellent OS/CPU
Expand All @@ -40,3 +41,20 @@ or modified to build your own world using built-in tools.
<ansi fg="6"> .--. .-'. .--. .--. .--. .--. .`-. .--.
<ansi fg="187">:::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187">::::::::.</ansi>\<ansi fg="187"></ansi>
' `--' `.-' `--' `--' `--' `-.' `--' `</ansi>

<ansi fg="black-bold">.:</ansi> <ansi fg="magenta">Special Thanks</ansi>

<ansi fg="8">Those who contributed to <ansi fg="command">GoMud</ansi> via <ansi fg="15">testing</ansi>, <ansi fg="15">content</ansi>, <ansi fg="15">code</ansi>, and <ansi fg="15">discussion</ansi>
during its first year of development. In alphabetical order:</ansi>

<ansi fg="14">Andrew Burns</ansi> aka <ansi fg="11">mister_burns</ansi>
<ansi fg="14">Arin Bennett</ansi> aka <ansi fg="11">Sloan</ansi>
<ansi fg="14">Colin Senner</ansi> aka <ansi fg="11">colinsenner</ansi>
<ansi fg="14">Durf Durfleton</ansi> aka <ansi fg="11">Durf</ansi>
<ansi fg="14">Ethan Samuels</ansi> aka <ansi fg="11">ethaburd</ansi>
<ansi fg="14">Jake</ansi> aka <ansi fg="11">Jake</ansi>
<ansi fg="14">Jeff</ansi> aka <ansi fg="11">Armoredartist</ansi>
<ansi fg="14">Jeffrey Edwards</ansi> aka <ansi fg="11">Miphon</ansi>
<ansi fg="14">Michael Myers</ansi> aka <ansi fg="11">avatus</ansi>
<ansi fg="14">Scott</ansi> aka <ansi fg="11">Neopong</ansi>
<ansi fg="14">William L</ansi> aka <ansi fg="11">1aw123</ansi>
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

The <ansi fg="command">password</ansi> command allows you to change your password.

Type ansi fg="command">password</ansi> and answer the prompts to make the change.
Type <ansi fg="command">password</ansi> and answer the prompts to make the change.
21 changes: 21 additions & 0 deletions _datafiles/world/empty/buffs/24-death_recovery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@


// Invoked every time the buff is triggered (see roundinterval)
function onTrigger(actor, triggersLeft) {

healAmt = actor.AddHealth(UtilDiceRoll(1, 10))
manaAmt = actor.AddMana(UtilDiceRoll(1, 10))

if ( healAmt > 0 && manaAmt > 0 ) {
SendUserMessage(actor.UserId(), 'The shadow realm heals you for <ansi fg="healing">'+String(healAmt)+' damage</ansi> and restores <ansi fg="mana-100">'+String(manaAmt)+' mana</ansi>!')
} else if ( healAmt > 0 ) {
SendUserMessage(actor.UserId(), 'The shadow realm heals you for <ansi fg="healing">'+String(healAmt)+' damage</ansi>!')
} else if ( manaAmt > 0 ) {
SendUserMessage(actor.UserId(), 'The shadow realm restores <ansi fg="mana-100">'+String(manaAmt)+' mana</ansi>!')
}

if ( healAmt > 0 || manaAmt > 0 ) {
SendRoomMessage(actor.GetRoomId(), actor.GetCharacterName(true)+' is recovering from a recent death.', actor.UserId())
}
}

5 changes: 5 additions & 0 deletions _datafiles/world/empty/buffs/24-death_recovery.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
buffid: 24
name: Death Recovery
description: You are recovering from dying
triggerrate: 1 rounds
triggercount: 15
2 changes: 1 addition & 1 deletion _datafiles/world/empty/templates/help/password.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

The <ansi fg="command">password</ansi> command allows you to change your password.

Type ansi fg="command">password</ansi> and answer the prompts to make the change.
Type <ansi fg="command">password</ansi> and answer the prompts to make the change.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/volte6/gomud

go 1.23
go 1.24

require (
github.com/Volte6/ansitags v0.0.0-20240205002851-61e010ad9511
Expand Down
1 change: 1 addition & 0 deletions internal/configs/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type Config struct {
TelnetPort ConfigSliceString `yaml:"TelnetPort"` // One or more Ports used to accept telnet connections
LocalPort ConfigInt `yaml:"LocalPort"` // Port used for admin connections, localhost only
WebPort ConfigInt `yaml:"WebPort"` // Port used for web requests
MspFileUrl ConfigString `yaml:"MspFileUrl"` // Where sound and music files reside for MSP protocol support
NextRoomId ConfigInt `yaml:"NextRoomId"` // The next room id to use when creating a new room
LootGoblinRoom ConfigInt `yaml:"LootGoblinRoom"` // The room the loot goblin spawns in
LootGoblinRoundCount ConfigInt `yaml:"LootGoblinRoundCount"` // How often to spawn a loot goblin
Expand Down
6 changes: 6 additions & 0 deletions internal/connections/clientsettings.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ type ClientSettings struct {
Client ClientType
// Enabled GMCP Modules
GMCPModules map[string]int
// Is MSP enabled?
MSPEnabled bool
}

type DisplaySettings struct {
Expand All @@ -28,6 +30,10 @@ func (c ClientSettings) IsMudlet() bool {
return c.Client.IsMudlet
}

func (c ClientSettings) IsMsp() bool {
return c.MSPEnabled
}

// Check whether a GMCP module is enabled on the client
func (c ClientSettings) GmcpEnabled(moduleName string) bool {
if len(c.GMCPModules) == 0 {
Expand Down
Loading