diff --git a/_datafiles/config.yaml b/_datafiles/config.yaml
index c3be12b6..ef610b9f 100755
--- a/_datafiles/config.yaml
+++ b/_datafiles/config.yaml
@@ -191,6 +191,7 @@ ConsistentAttackMessages: true
CorpsesEnabled: true
# - CorpseDecayTime -
# How long until corpses crumble to dust (Go away).
+# See ShopRestockRate comments for time format.
CorpseDecayTime: 1 hour
# - MaxAltCharacters -
# How many characters beyond their original character can they create? Players
@@ -217,6 +218,9 @@ NightHours: 8
# - LeaderboardSize -
# Maximum size of each leaderboard. 0 to disable.
LeaderboardSize: 10
+# - ContainerSizeMax -
+# Maximum number of objects a container can hold before stuff overflows
+ContainerSizeMax: 10
################################################################################
#
# MEMORY/CPU OPTIMIZATIONS
diff --git a/_datafiles/html/public/webclient.html b/_datafiles/html/public/webclient.html
index 1220b14d..80964688 100644
--- a/_datafiles/html/public/webclient.html
+++ b/_datafiles/html/public/webclient.html
@@ -20,7 +20,6 @@
position: relative; /* So absolutely positioned children can be placed relative to
*/
}
- /* Ensure the main container is positioned relatively */
#main-container {
flex: 1;
position: relative;
@@ -91,7 +90,6 @@
padding: 10px;
cursor: pointer;
z-index: 9999;
- /* Optional background to make it stand out: */
background-color: rgba(30,30,30, 0.8);
border-radius: 5px;
}
@@ -133,6 +131,22 @@
font-size: 20px;
color: #ccc;
}
+
+ /* Mute Checkbox */
+ #mute-container {
+ margin-bottom: 15px;
+ color: #ccc;
+ display: flex;
+ align-items: center;
+ }
+ #mute-container label {
+ cursor: pointer;
+ }
+ #mute-container input[type="checkbox"] {
+ margin-right: 8px;
+ transform: scale(1.2);
+ cursor: pointer;
+ }
@@ -148,8 +162,14 @@
@@ -173,11 +193,11 @@ Volume Controls
/////////////////////////////////////////////
//
- // Terminal emulation setup
+ // Terminal Setup
//
/////////////////////////////////////////////
const term = new window.Terminal({
- cols: 80,
+ cols: 80,
rows: 60,
cursorBlink: true,
fontSize: 20
@@ -186,30 +206,28 @@ Volume Controls
term.loadAddon(fitAddon);
term.open(document.getElementById('terminal'));
- // Resize the terminal to fit its container
- const resizeTerminal = () => {
+ function resizeTerminal() {
fitAddon.fit();
- };
- resizeTerminal();
+ }
window.addEventListener('resize', resizeTerminal);
+ resizeTerminal();
/////////////////////////////////////////////
//
- // Misc tracking
+ // Misc
//
/////////////////////////////////////////////
let payloadsReceived = 0;
let totalBytesReceived = 0;
let payloadsSent = 0;
let totalBytesSent = 0;
- // Command history
let commandHistory = [];
let historyPosition = 0;
let commandHistoryMaxLength = 30;
/////////////////////////////////////////////
//
- // Basic WebSocket code
+ // WebSocket
//
/////////////////////////////////////////////
let socket = null;
@@ -220,7 +238,6 @@ Volume Controls
const textOutput = document.getElementById('terminal');
const textInput = document.getElementById('command-input');
- // Key shortcuts
const codeShortcuts = {
"Numpad1": "southwest",
"Numpad2": "south",
@@ -261,12 +278,11 @@ Volume Controls
return false;
}
- connectButton.addEventListener('click', function() {
- if ( socket && socket.readyState === WebSocket.OPEN ) {
+ connectButton.addEventListener('click', () => {
+ if (socket && socket.readyState === WebSocket.OPEN) {
socket.close();
return;
}
-
debugLog("Connecting to: " + 'ws://'+location.host +':80/ws');
socket = new WebSocket('ws://'+location.host +':80/ws');
@@ -282,29 +298,28 @@ Volume Controls
totalBytesReceived += event.data.length;
// Check if it's a webclient command
- if ( event.data.length > 9 && event.data.substring(8, 9) === ':' ) {
- if ( handleWebclientCommand(event.data) ) {
+ if (event.data.length > 9 && event.data.substring(8, 9) === ':') {
+ if (handleWebclientCommand(event.data)) {
return;
}
}
// MSP commands
- if ( event.data.length > 9 && event.data.slice(0, 2) === "!!") {
- if ( event.data.slice(0, 8) === "!!MUSIC(" ) {
- const parts = event.data.slice(8, event.data.length-1).split(" ");
+ if (event.data.length > 9 && event.data.slice(0, 2) === "!!") {
+ if (event.data.slice(0, 8) === "!!MUSIC(") {
+ const parts = event.data.slice(8, event.data.length - 1).split(" ");
let fileName = parts[0];
let obj = {};
- for ( let i=1; iVolume Controls
let soundLevel = 1.0;
let loopMusic = true;
- if ( obj.L && obj.L !== "-1" ) {
+ if (obj.L && obj.L !== "-1") {
loopMusic = false;
}
- if ( obj.V ) {
+ if (obj.V) {
soundLevel = Number(obj.V)/100;
}
- if ( !MusicPlayer.isPlaying(baseMp3Url+fileName) ) {
- MusicPlayer.play(baseMp3Url+fileName, loopMusic, (sliderValues["music"]/100));
+ if (!MusicPlayer.isPlaying(baseMp3Url + fileName)) {
+ MusicPlayer.play(baseMp3Url + fileName, loopMusic, soundLevel*(sliderValues["music"] / 100));
}
}
}
- else if ( event.data.slice(0, 8) === "!!SOUND(" ) {
- const parts = event.data.slice(8, event.data.length-1).split(" ");
+ else if (event.data.slice(0, 8) === "!!SOUND(") {
+ const parts = event.data.slice(8, event.data.length - 1).split(" ");
let fileName = parts[0];
let obj = {};
- for ( let i=1; iVolume Controls
socket.onclose = function(event) {
if (event.wasClean) {
- term.writeln("Connection closed cleanly, code=${event.code}, reason=${event.reason}");
+ term.writeln(`Connection closed cleanly, code=${event.code}, reason=${event.reason}`);
} else {
term.writeln("Connection died");
}
connectButton.disabled = false;
- if ( textInput.type === "password" ) {
+ if (textInput.type === "password") {
textInput.value = '';
textInput.type = "text";
}
@@ -377,22 +403,22 @@ Volume Controls
textInput.addEventListener('keydown', function(event) {
// Macro support: F-keys
- if ( event.key.substring(0, 1) === "F" && event.key.length === 2 ) {
+ if (event.key.substring(0, 1) === "F" && event.key.length === 2) {
let macroNum = event.key.substring(1);
- SendData("="+macroNum);
+ SendData("=" + macroNum);
if (event.preventDefault) event.preventDefault();
return false;
}
// ArrowUp / ArrowDown for command history
- if ( event.key === 'ArrowUp' || event.key === 'ArrowDown' ) {
- if ( event.key === 'ArrowUp' ) {
+ if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
+ if (event.key === 'ArrowUp') {
historyPosition += 1;
} else {
historyPosition -= 1;
}
- if ( historyPosition < 1 ) historyPosition = 1;
- if ( historyPosition > commandHistory.length ) historyPosition = commandHistory.length;
+ if (historyPosition < 1) historyPosition = 1;
+ if (historyPosition > commandHistory.length) historyPosition = commandHistory.length;
event.target.value = commandHistory[ commandHistory.length - historyPosition ];
}
@@ -404,12 +430,12 @@ Volume Controls
}
// ENTER key
- if ( event.key === 'Enter' ) {
- if ( event.target.value !== '' ) {
- if ( textInput.type !== "password" ) {
+ if (event.key === 'Enter') {
+ if (event.target.value !== '') {
+ if (textInput.type !== "password") {
commandHistory.push(event.target.value);
historyPosition = 0;
- if ( commandHistory.length > commandHistoryMaxLength ) {
+ if (commandHistory.length > commandHistoryMaxLength) {
commandHistory = commandHistory.slice(commandHistory.length - commandHistoryMaxLength);
}
}
@@ -454,18 +480,10 @@ Volume Controls
}
}
- /////////////////////////////////////////////
- //
- // Keep terminal focus on mouse events
- //
- /////////////////////////////////////////////
- textOutput.addEventListener('mousedown', function() {
- isDragging = false;
- });
- textOutput.addEventListener('mousemove', function() {
- isDragging = true;
- });
- textOutput.addEventListener('mouseup', function() {
+ // Keep focus on terminal if user clicks inside
+ textOutput.addEventListener('mousedown', () => { isDragging = false; });
+ textOutput.addEventListener('mousemove', () => { isDragging = true; });
+ textOutput.addEventListener('mouseup', () => {
const selectedText = window.getSelection().toString();
if (!isDragging && !selectedText) {
textInput.focus();
@@ -475,82 +493,133 @@ Volume Controls
/////////////////////////////////////////////
//
- // Volume sliders with dynamic speaker icons
+ // Volume Sliders + Mute
//
/////////////////////////////////////////////
-
- // Our multiple volume controls:
- let sliderValues = { // defaults
+
+ // 1) Define default sliders (and new ones if needed!)
+ const defaultSliders = {
"music": 75,
"combat sounds": 75,
"movement sounds": 75,
- "other sounds": 75
+ "environment sounds": 75,
+ "other sounds": 75,
};
- // Returns an appropriate speaker icon based on value
+ // 2) We'll store final slider values
+ let sliderValues = { ...defaultSliders };
+
+ // 3) We'll also store unmuted slider values if user checks "Mute"
+ let unmutedSliderValues = null;
+
+ // Return speaker icon
function getSpeakerIcon(value) {
value = Number(value);
if (value === 0) {
- return "🔇"; // muted
+ return "🔇";
} else if (value < 33) {
- return "🔈"; // low
+ return "🔈";
} else if (value < 66) {
- return "🔉"; // medium
+ return "🔉";
} else {
- return "🔊"; // high
+ return "🔊";
}
}
+ // Build the sliders from sliderValues
function buildSliders() {
const container = document.getElementById('sliders-container');
- container.innerHTML = ""; // Clear any old content
+ container.innerHTML = "";
Object.keys(sliderValues).forEach(function(key) {
- // Create a container for each slider row
const wrapper = document.createElement('div');
wrapper.className = "slider-container";
- // Label for the name (Music, Sound FX, etc.)
const label = document.createElement('label');
label.textContent = key.toLowerCase().split(' ').map(function(word) {
return word.charAt(0).toUpperCase() + word.slice(1);
}).join(' ');
- // The slider
const slider = document.createElement('input');
slider.type = "range";
slider.min = 0;
slider.max = 100;
slider.value = sliderValues[key];
- // The speaker icon
const iconSpan = document.createElement('span');
iconSpan.className = "slider-icon";
- // Initial icon based on current value
iconSpan.textContent = getSpeakerIcon(sliderValues[key]);
- // On slider change, update the map + icon
+ // On slider change
slider.addEventListener('input', function(e) {
const val = e.target.value;
sliderValues[key] = Number(val);
iconSpan.textContent = getSpeakerIcon(val);
- // LOCALSTORAGE ADDED: update local storage for every slider change
+ // Update local storage
localStorage.setItem('sliderValues', JSON.stringify(sliderValues));
- // Example: update the global music volume
- MusicPlayer.setGlobalVolume(sliderValues["music"]/100);
+ // Update music volume
+ MusicPlayer.setGlobalVolume(sliderValues["music"] / 100);
+
+ // If user moves any slider up from 0, uncheck Mute
+ const muteCheckbox = document.getElementById('mute-checkbox');
+ if (muteCheckbox.checked && val > 0) {
+ muteCheckbox.checked = false;
+ localStorage.setItem('muteAllSound', JSON.stringify(false));
+ document.getElementById('mute-icon').textContent = "🔊";
+ }
});
- // Put them all together
wrapper.appendChild(label);
wrapper.appendChild(slider);
wrapper.appendChild(iconSpan);
-
container.appendChild(wrapper);
});
}
+ // Handle Mute
+ function toggleMuteAll() {
+ const muteCheckbox = document.getElementById('mute-checkbox');
+ const isChecked = muteCheckbox.checked;
+ const muteIcon = document.getElementById('mute-icon');
+
+ if (isChecked) {
+ // Save the unmuted state
+ unmutedSliderValues = { ...sliderValues };
+ localStorage.setItem('unmutedSliderValues', JSON.stringify(unmutedSliderValues));
+
+ // Set all to 0
+ Object.keys(sliderValues).forEach(key => {
+ sliderValues[key] = 0;
+ });
+ localStorage.setItem('sliderValues', JSON.stringify(sliderValues));
+
+ buildSliders();
+
+ muteIcon.textContent = "🔇";
+ MusicPlayer.setGlobalVolume(0);
+ localStorage.setItem('muteAllSound', JSON.stringify(true));
+ } else {
+ // Restore from unmuted
+ const savedUnmuted = localStorage.getItem('unmutedSliderValues');
+ if (savedUnmuted) {
+ // Merge defaultSliders just in case new keys appear
+ let loadedUnmuted = JSON.parse(savedUnmuted) || {};
+ loadedUnmuted = { ...defaultSliders, ...loadedUnmuted };
+ unmutedSliderValues = { ...loadedUnmuted };
+
+ sliderValues = { ...unmutedSliderValues };
+ localStorage.setItem('sliderValues', JSON.stringify(sliderValues));
+ }
+ buildSliders();
+
+ muteIcon.textContent = "🔊";
+ MusicPlayer.setGlobalVolume(sliderValues["music"] / 100);
+ localStorage.setItem('muteAllSound', JSON.stringify(false));
+ }
+ }
+
// Show/hide the floating menu
function toggleMenu() {
const menu = document.getElementById('floating-menu');
@@ -573,26 +642,73 @@ Volume Controls
function init() {
console.log("%cterminal commands:", "font-weight:bold;");
let longest = 0;
- for ( let i in specialCommands ) {
- longest = i.length > longest ? i.length : longest;
+ for (let i in specialCommands) {
+ if (i.length > longest) longest = i.length;
}
- for ( let i in specialCommands ) {
- console.log(' '+i.padEnd(longest)+" - " + specialCommands[i]);
+ for (let i in specialCommands) {
+ console.log(" " + i.padEnd(longest) + " - " + specialCommands[i]);
}
console.log("%cconsole commands:", "font-weight:bold;");
- // LOCALSTORAGE ADDED: load sliderValues from localStorage if available
+ // 1) Load from localStorage, if available
const savedValues = localStorage.getItem('sliderValues');
if (savedValues) {
try {
- sliderValues = JSON.parse(savedValues);
+ // Merge existing local storage with defaultSliders
+ const loaded = JSON.parse(savedValues);
+ sliderValues = { ...defaultSliders, ...loaded };
} catch (e) {
console.warn("Could not parse saved sliderValues, using defaults.");
}
+ } else {
+ // If no localStorage, ensure we set the defaults
+ localStorage.setItem('sliderValues', JSON.stringify(sliderValues));
+ }
+
+ // 2) Check if we have a "muteAllSound" property
+ const savedMute = localStorage.getItem('muteAllSound');
+ if (savedMute) {
+ try {
+ const isMuted = JSON.parse(savedMute);
+ document.getElementById('mute-checkbox').checked = isMuted;
+ } catch (e) {
+ console.warn("Could not parse muteAllSound, ignoring.");
+ }
}
- // Build all sliders from sliderValues
+ // 3) Build the sliders
buildSliders();
+
+ // 4) If currently muted, re-apply zero volumes
+ const muteCheckbox = document.getElementById('mute-checkbox');
+ const muteIcon = document.getElementById('mute-icon');
+
+ if (muteCheckbox.checked) {
+ // Possibly retrieve unmuted values from storage
+ const savedUnmuted = localStorage.getItem('unmutedSliderValues');
+ if (savedUnmuted) {
+ // Merge defaultSliders here, too
+ try {
+ let loadedUnmuted = JSON.parse(savedUnmuted) || {};
+ unmutedSliderValues = { ...defaultSliders, ...loadedUnmuted };
+ } catch(e) {
+ console.warn("Could not parse unmutedSliderValues.");
+ }
+ }
+ // Force all current sliders to 0
+ Object.keys(sliderValues).forEach(key => {
+ sliderValues[key] = 0;
+ });
+ localStorage.setItem('sliderValues', JSON.stringify(sliderValues));
+ buildSliders();
+
+ muteIcon.textContent = "🔇";
+ MusicPlayer.setGlobalVolume(0);
+ } else {
+ // If not muted, set music volume from slider
+ MusicPlayer.setGlobalVolume(sliderValues["music"] / 100);
+ muteIcon.textContent = "🔊";
+ }
}
diff --git a/_datafiles/html/static/public/audio/sound/environment/wind.mp3 b/_datafiles/html/static/public/audio/sound/environment/wind.mp3
new file mode 100644
index 00000000..deabc3a5
Binary files /dev/null and b/_datafiles/html/static/public/audio/sound/environment/wind.mp3 differ
diff --git a/_datafiles/world/default/templates/descriptions/insidecontainer.template b/_datafiles/world/default/templates/descriptions/insidecontainer.template
index f87804e8..ef140eea 100644
--- a/_datafiles/world/default/templates/descriptions/insidecontainer.template
+++ b/_datafiles/world/default/templates/descriptions/insidecontainer.template
@@ -1,13 +1,11 @@
{{- $displayed := 0 -}}
-{{- $itemCt := len . -}}
+{{ $itemCt := len .ItemNames -}}
┌─────────────────────────────────────────────────────────────────────────┐
- Inside you see:
+ Inside:
{{- if ne $itemCt 0 -}}
- {{- range $index, $itemName := . -}}
- {{- $displayed = add $displayed 1 -}}
- {{ $itemName }} {{- if ne $displayed $itemCt }}{{- if ne $displayed (sub $itemCt 1) }}, {{ else }} and {{ end }}{{ end -}}
- {{- end }}
+ {{ $formattedNames := .ItemNamesFormatted -}}{{- $strlen := 0 -}}{{- $lineCt := 1 -}}
+ {{ range $index, $name := .ItemNames -}}{{ $proposedLength := (add 2 (add $strlen (len $name))) }}{{- if gt $proposedLength 66 -}}{{- $strlen = 0 -}}{{- $lineCt = (add 1 $lineCt) -}}{{- printf "\n " -}}{{- end -}}{{ index $formattedNames $index }}{{- if ne $index (sub $itemCt 1) }}, {{ $strlen = (add 2 (add $strlen (len $name))) }}{{ end }}{{ end }}
{{ else -}}
Nothing
{{ end }}
diff --git a/_datafiles/world/empty/templates/descriptions/insidecontainer.template b/_datafiles/world/empty/templates/descriptions/insidecontainer.template
index 7d201aeb..ef140eea 100644
--- a/_datafiles/world/empty/templates/descriptions/insidecontainer.template
+++ b/_datafiles/world/empty/templates/descriptions/insidecontainer.template
@@ -1,13 +1,11 @@
{{- $displayed := 0 -}}
-{{- $itemCt := len . -}}
+{{ $itemCt := len .ItemNames -}}
┌─────────────────────────────────────────────────────────────────────────┐
-Inside you see:
+ Inside:
{{- if ne $itemCt 0 -}}
- {{- range $index, $itemName := . -}}
- {{- $displayed = add $displayed 1 -}}
- {{ $itemName }} {{- if ne $displayed $itemCt }}{{- if ne $displayed (sub $itemCt 1) }}, {{ else }} and {{ end }}{{ end -}}
- {{- end }}
+ {{ $formattedNames := .ItemNamesFormatted -}}{{- $strlen := 0 -}}{{- $lineCt := 1 -}}
+ {{ range $index, $name := .ItemNames -}}{{ $proposedLength := (add 2 (add $strlen (len $name))) }}{{- if gt $proposedLength 66 -}}{{- $strlen = 0 -}}{{- $lineCt = (add 1 $lineCt) -}}{{- printf "\n " -}}{{- end -}}{{ index $formattedNames $index }}{{- if ne $index (sub $itemCt 1) }}, {{ $strlen = (add 2 (add $strlen (len $name))) }}{{ end }}{{ end }}
{{ else -}}
Nothing
{{ end }}
diff --git a/internal/configs/configs.go b/internal/configs/configs.go
index 29b372c7..62b02ee9 100644
--- a/internal/configs/configs.go
+++ b/internal/configs/configs.go
@@ -99,7 +99,8 @@ type Config struct {
CorpsesEnabled ConfigBool `yaml:"CorpsesEnabled"` // Whether corpses are left behind after mob/player deaths
CorpseDecayTime ConfigString `yaml:"CorpseDecayTime"` // How long until corpses decay to dust (go away)
- LeaderboardSize ConfigInt `yaml:"LeaderboardSize"` // Maximum size of leaderboard
+ LeaderboardSize ConfigInt `yaml:"LeaderboardSize"` // Maximum size of leaderboard
+ ContainerSizeMax ConfigInt `yaml:"ContainerSizeMax"` // How many objects containers can hold before overflowing
SeedInt int64 `yaml:"-"`
diff --git a/internal/events/eventtypes.go b/internal/events/eventtypes.go
index 314f1545..dd1a9ad1 100644
--- a/internal/events/eventtypes.go
+++ b/internal/events/eventtypes.go
@@ -96,6 +96,7 @@ type MSP struct {
UserId int
SoundType string // SOUND or MUSIC
SoundFile string
+ Volume int // 1-100
Category string // special category/type for MSP string
}
diff --git a/internal/mobcommands/go.go b/internal/mobcommands/go.go
index 2318bf66..2e7239f8 100644
--- a/internal/mobcommands/go.go
+++ b/internal/mobcommands/go.go
@@ -138,8 +138,8 @@ func Go(rest string, mob *mobs.Mob, room *rooms.Room) (bool, error) {
destRoom.SendTextToExits(`You hear someone moving around.`, true, room.GetPlayers(rooms.FindAll)...)
- room.PlaySound(`sound/movement/room-exit.mp3`, `movement`)
- destRoom.PlaySound(`sound/movement/room-enter.mp3`, `movement`)
+ room.PlaySound(`sound/movement/room-exit.mp3`, `movement`, 100)
+ destRoom.PlaySound(`sound/movement/room-enter.mp3`, `movement`, 100)
return true, nil
}
diff --git a/internal/mobcommands/put.go b/internal/mobcommands/put.go
index 08109e38..a19f67b3 100644
--- a/internal/mobcommands/put.go
+++ b/internal/mobcommands/put.go
@@ -5,6 +5,7 @@ import (
"strconv"
"strings"
+ "github.com/volte6/gomud/internal/configs"
"github.com/volte6/gomud/internal/items"
"github.com/volte6/gomud/internal/mobs"
"github.com/volte6/gomud/internal/rooms"
@@ -79,8 +80,8 @@ func Put(rest string, mob *mobs.Mob, room *rooms.Room) (bool, error) {
room.SendText(fmt.Sprintf(`%s places their %s into the %s `, mob.Character.Name, item.DisplayName(), containerName))
- // current hard limit of 10 max items.
- if len(container.Items) > 10 {
+ // Enforce container size limits
+ if len(container.Items) > int(configs.GetConfig().ContainerSizeMax) {
randItemToRemove := util.Rand(len(container.Items))
oopsItem := container.Items[randItemToRemove]
diff --git a/internal/rooms/rooms.go b/internal/rooms/rooms.go
index 399ad95a..a273bec4 100644
--- a/internal/rooms/rooms.go
+++ b/internal/rooms/rooms.go
@@ -248,7 +248,13 @@ func (r *Room) SendText(txt string, excludeUserIds ...int) {
}
-func (r *Room) PlaySound(soundFile string, category string, excludeUserIds ...int) {
+func (r *Room) PlaySound(soundFile string, category string, volume int, excludeUserIds ...int) {
+
+ if volume < 1 {
+ volume = 1
+ } else if volume > 100 {
+ volume = 100
+ }
for _, userId := range r.players {
@@ -272,6 +278,7 @@ func (r *Room) PlaySound(soundFile string, category string, excludeUserIds ...in
UserId: userId,
SoundType: `SOUND`,
SoundFile: soundFile,
+ Volume: volume,
Category: category,
})
}
diff --git a/internal/usercommands/look.go b/internal/usercommands/look.go
index 04588aeb..fd9d2b74 100644
--- a/internal/usercommands/look.go
+++ b/internal/usercommands/look.go
@@ -143,6 +143,9 @@ func Look(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
containerName := room.FindContainerByName(lookAt)
if containerName != `` {
+ itemNames := []string{}
+ itemNamesFormatted := []string{}
+
container := room.Containers[containerName]
if container.Lock.IsLocked() {
@@ -152,10 +155,9 @@ func Look(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
return true, nil
}
- chestStuff := []string{}
-
if container.Gold > 0 {
- chestStuff = append(chestStuff, fmt.Sprintf(`%d gold `, container.Gold))
+ itemNames = append(itemNames, fmt.Sprintf(`%d gold`, container.Gold))
+ itemNamesFormatted = append(itemNamesFormatted, fmt.Sprintf(`%d gold `, container.Gold))
}
for _, item := range container.Items {
@@ -163,7 +165,9 @@ func Look(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
room.RemoveItem(item, false)
continue
}
- chestStuff = append(chestStuff, item.DisplayName())
+
+ itemNames = append(itemNames, item.Name())
+ itemNamesFormatted = append(itemNamesFormatted, fmt.Sprintf(`%s `, item.DisplayName()))
}
if len(container.Recipes) > 0 {
@@ -182,14 +186,16 @@ func Look(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
user.SendText(``)
finalItem := items.New(finalItemId)
- user.SendText(fmt.Sprintf(` To receive 1 %s : `, finalItem.DisplayName()))
+ user.SendText(fmt.Sprintf(` To receive 1 %s : `, finalItem.DisplayName()))
for inputItemId, qtyNeeded := range neededItems {
tmpItem := items.New(inputItemId)
totalContained := container.Count(inputItemId)
- colorClass := "9"
+ colorClass := "8" // None fulfilled
if totalContained == qtyNeeded {
- colorClass = "14"
+ colorClass = "10"
+ } else if totalContained > 0 {
+ colorClass = "3"
}
user.SendText(fmt.Sprintf(` [%d/%d] %s `, colorClass, totalContained, qtyNeeded, tmpItem.DisplayName()))
}
@@ -198,6 +204,11 @@ func Look(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
}
+ chestStuff := map[string]any{
+ `ItemNames`: itemNames,
+ `ItemNamesFormatted`: itemNamesFormatted,
+ }
+
textOut, _ := templates.Process("descriptions/insidecontainer", chestStuff)
user.SendText(``)
diff --git a/internal/usercommands/put.go b/internal/usercommands/put.go
index b1b1620b..16740a56 100644
--- a/internal/usercommands/put.go
+++ b/internal/usercommands/put.go
@@ -5,6 +5,7 @@ import (
"strconv"
"strings"
+ "github.com/volte6/gomud/internal/configs"
"github.com/volte6/gomud/internal/items"
"github.com/volte6/gomud/internal/rooms"
"github.com/volte6/gomud/internal/users"
@@ -93,14 +94,15 @@ func Put(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
}
if itemFound {
+
container.AddItem(item)
user.Character.RemoveItem(item)
user.SendText(fmt.Sprintf(`You place your %s into the %s `, item.DisplayName(), containerName))
room.SendText(fmt.Sprintf(`%s places their %s into the %s `, user.Character.Name, item.DisplayName(), containerName), user.UserId)
- // current hard limit of 10 max items.
- if len(container.Items) > 10 {
+ // Enforce container size limits
+ if len(container.Items) > int(configs.GetConfig().ContainerSizeMax) {
randItemToRemove := util.Rand(len(container.Items))
oopsItem := container.Items[randItemToRemove]
diff --git a/internal/usercommands/use.go b/internal/usercommands/use.go
index 53b82f34..1c664853 100644
--- a/internal/usercommands/use.go
+++ b/internal/usercommands/use.go
@@ -47,7 +47,7 @@ func Use(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
container.AddItem(newItem)
room.Containers[containerName] = container
- room.PlaySound(`sound/other/change.mp3`, `other`)
+ room.PlaySound(`sound/other/change.mp3`, `other`, 100)
user.SendText(``)
user.SendText(fmt.Sprintf(`The %s produces a %s !`, containerName, newItem.DisplayName()))
diff --git a/internal/users/userrecord.go b/internal/users/userrecord.go
index 41c3d61b..b9eadd4f 100644
--- a/internal/users/userrecord.go
+++ b/internal/users/userrecord.go
@@ -151,16 +151,28 @@ func (u *UserRecord) PlayMusic(musicFile string) {
UserId: u.UserId,
SoundType: `MUSIC`,
SoundFile: musicFile,
+ Volume: 100,
})
}
-func (u *UserRecord) PlaySound(soundFile string, category string) {
+func (u *UserRecord) PlaySound(soundFile string, category string, volume ...int) {
+
+ v := 100
+ if len(volume) > 0 {
+ v = volume[0]
+ if v < 1 {
+ v = 1
+ } else if v > 100 {
+ v = 100
+ }
+ }
events.AddToQueue(events.MSP{
UserId: u.UserId,
SoundType: `SOUND`,
SoundFile: soundFile,
+ Volume: v,
Category: category,
})
diff --git a/world.go b/world.go
index e7de5061..068b4c26 100644
--- a/world.go
+++ b/world.go
@@ -1007,7 +1007,7 @@ func (w *World) MessageTick() {
user.LastMusic = msp.SoundFile
- msg := []byte("!!MUSIC(" + msp.SoundFile + " V=80 L=-1 C=1)")
+ msg := []byte("!!MUSIC(" + msp.SoundFile + " V=" + strconv.Itoa(msp.Volume) + " L=-1 C=1)")
if connections.IsWebsocket(user.ConnectionId()) {
@@ -1026,7 +1026,7 @@ func (w *World) MessageTick() {
}
} else {
- msg := []byte("!!SOUND(" + msp.SoundFile + " T=" + msp.Category + ")")
+ msg := []byte("!!SOUND(" + msp.SoundFile + " T=" + msp.Category + " V=" + strconv.Itoa(msp.Volume) + ")")
if connections.IsWebsocket(user.ConnectionId()) {