diff --git a/WebHostLib/static/assets/weighted-settings.js b/WebHostLib/static/assets/weighted-settings.js
index 91789c2f..496b0c15 100644
--- a/WebHostLib/static/assets/weighted-settings.js
+++ b/WebHostLib/static/assets/weighted-settings.js
@@ -128,19 +128,22 @@ const buildUI = (settingData) => {
expandButton.classList.add('invisible');
gameDiv.appendChild(expandButton);
- const optionsDiv = buildOptionsDiv(game, settingData.games[game].gameSettings);
- gameDiv.appendChild(optionsDiv);
+ const weightedSettingsDiv = buildWeightedSettingsDiv(game, settingData.games[game].gameSettings);
+ gameDiv.appendChild(weightedSettingsDiv);
+
+ const itemsDiv = buildItemsDiv(game, settingData.games[game].gameItems);
+ gameDiv.appendChild(itemsDiv);
gamesWrapper.appendChild(gameDiv);
collapseButton.addEventListener('click', () => {
collapseButton.classList.add('invisible');
- optionsDiv.classList.add('invisible');
+ weightedSettingsDiv.classList.add('invisible');
expandButton.classList.remove('invisible');
});
expandButton.addEventListener('click', () => {
collapseButton.classList.remove('invisible');
- optionsDiv.classList.remove('invisible');
+ weightedSettingsDiv.classList.remove('invisible');
expandButton.classList.add('invisible');
});
});
@@ -207,10 +210,10 @@ const buildGameChoice = (games) => {
gameChoiceDiv.appendChild(table);
};
-const buildOptionsDiv = (game, settings) => {
+const buildWeightedSettingsDiv = (game, settings) => {
const currentSettings = JSON.parse(localStorage.getItem('weighted-settings'));
- const optionsWrapper = document.createElement('div');
- optionsWrapper.classList.add('settings-wrapper');
+ const settingsWrapper = document.createElement('div');
+ settingsWrapper.classList.add('settings-wrapper');
Object.keys(settings).forEach((settingName) => {
const setting = settings[settingName];
@@ -268,27 +271,6 @@ const buildOptionsDiv = (game, settings) => {
break;
case 'range':
- const hintText = document.createElement('p');
- hintText.classList.add('hint-text');
- hintText.innerHTML = 'This is a range option. You may enter valid numerical values in the text box below, ' +
- `then press the "Add" button to add a weight for it.
Minimum value: ${setting.min}
` +
- `Maximum value: ${setting.max}`;
- settingWrapper.appendChild(hintText);
-
- const addOptionDiv = document.createElement('div');
- addOptionDiv.classList.add('add-option-div');
- const optionInput = document.createElement('input');
- optionInput.setAttribute('id', `${game}-${settingName}-option`);
- optionInput.setAttribute('placeholder', `${setting.min} - ${setting.max}`);
- addOptionDiv.appendChild(optionInput);
- const addOptionButton = document.createElement('button');
- addOptionButton.innerText = 'Add';
- addOptionDiv.appendChild(addOptionButton);
- settingWrapper.appendChild(addOptionDiv);
- optionInput.addEventListener('keydown', (evt) => {
- if (evt.key === 'Enter') { addOptionButton.dispatchEvent(new Event('click')); }
- });
-
const rangeTable = document.createElement('table');
const rangeTbody = document.createElement('tbody');
@@ -324,6 +306,79 @@ const buildOptionsDiv = (game, settings) => {
rangeTbody.appendChild(tr);
}
} else {
+ const hintText = document.createElement('p');
+ hintText.classList.add('hint-text');
+ hintText.innerHTML = 'This is a range option. You may enter a valid numerical value in the text box ' +
+ `below, then press the "Add" button to add a weight for it.
Minimum value: ${setting.min}
` +
+ `Maximum value: ${setting.max}`;
+ settingWrapper.appendChild(hintText);
+
+ const addOptionDiv = document.createElement('div');
+ addOptionDiv.classList.add('add-option-div');
+ const optionInput = document.createElement('input');
+ optionInput.setAttribute('id', `${game}-${settingName}-option`);
+ optionInput.setAttribute('placeholder', `${setting.min} - ${setting.max}`);
+ addOptionDiv.appendChild(optionInput);
+ const addOptionButton = document.createElement('button');
+ addOptionButton.innerText = 'Add';
+ addOptionDiv.appendChild(addOptionButton);
+ settingWrapper.appendChild(addOptionDiv);
+ optionInput.addEventListener('keydown', (evt) => {
+ if (evt.key === 'Enter') { addOptionButton.dispatchEvent(new Event('click')); }
+ });
+
+ addOptionButton.addEventListener('click', () => {
+ const optionInput = document.getElementById(`${game}-${settingName}-option`);
+ let option = optionInput.value;
+ if (!option || !option.trim()) { return; }
+ option = parseInt(option, 10);
+ if ((option < setting.min) || (option > setting.max)) { return; }
+ optionInput.value = '';
+ if (document.getElementById(`${game}-${settingName}-${option}-range`)) { return; }
+
+ const tr = document.createElement('tr');
+ const tdLeft = document.createElement('td');
+ tdLeft.classList.add('td-left');
+ tdLeft.innerText = option;
+ tr.appendChild(tdLeft);
+
+ const tdMiddle = document.createElement('td');
+ tdMiddle.classList.add('td-middle');
+ const range = document.createElement('input');
+ range.setAttribute('type', 'range');
+ range.setAttribute('id', `${game}-${settingName}-${option}-range`);
+ range.setAttribute('data-game', game);
+ range.setAttribute('data-setting', settingName);
+ range.setAttribute('data-option', option);
+ range.setAttribute('min', 0);
+ range.setAttribute('max', 50);
+ range.addEventListener('change', updateGameSetting);
+ range.value = currentSettings[game][settingName][parseInt(option, 10)];
+ tdMiddle.appendChild(range);
+ tr.appendChild(tdMiddle);
+
+ const tdRight = document.createElement('td');
+ tdRight.setAttribute('id', `${game}-${settingName}-${option}`)
+ tdRight.classList.add('td-right');
+ tdRight.innerText = range.value;
+ tr.appendChild(tdRight);
+
+ const tdDelete = document.createElement('td');
+ tdDelete.classList.add('td-delete');
+ const deleteButton = document.createElement('span');
+ deleteButton.classList.add('range-option-delete');
+ deleteButton.innerText = '❌';
+ deleteButton.addEventListener('click', () => {
+ range.value = 0;
+ range.dispatchEvent(new Event('change'));
+ rangeTbody.removeChild(tr);
+ });
+ tdDelete.appendChild(deleteButton);
+ tr.appendChild(tdDelete);
+
+ rangeTbody.appendChild(tr);
+ });
+
Object.keys(currentSettings[game][settingName]).forEach((option) => {
if (currentSettings[game][settingName][option] > 0) {
const tr = document.createElement('tr');
@@ -403,58 +458,6 @@ const buildOptionsDiv = (game, settings) => {
rangeTable.appendChild(rangeTbody);
settingWrapper.appendChild(rangeTable);
-
- addOptionButton.addEventListener('click', () => {
- const optionInput = document.getElementById(`${game}-${settingName}-option`);
- let option = optionInput.value;
- if (!option || !option.trim()) { return; }
- option = parseInt(option, 10);
- if ((option < setting.min) || (option > setting.max)) { return; }
- optionInput.value = '';
- if (document.getElementById(`${game}-${settingName}-${option}-range`)) { return; }
-
- const tr = document.createElement('tr');
- const tdLeft = document.createElement('td');
- tdLeft.classList.add('td-left');
- tdLeft.innerText = option;
- tr.appendChild(tdLeft);
-
- const tdMiddle = document.createElement('td');
- tdMiddle.classList.add('td-middle');
- const range = document.createElement('input');
- range.setAttribute('type', 'range');
- range.setAttribute('id', `${game}-${settingName}-${option}-range`);
- range.setAttribute('data-game', game);
- range.setAttribute('data-setting', settingName);
- range.setAttribute('data-option', option);
- range.setAttribute('min', 0);
- range.setAttribute('max', 50);
- range.addEventListener('change', updateGameSetting);
- range.value = currentSettings[game][settingName][parseInt(option, 10)];
- tdMiddle.appendChild(range);
- tr.appendChild(tdMiddle);
-
- const tdRight = document.createElement('td');
- tdRight.setAttribute('id', `${game}-${settingName}-${option}`)
- tdRight.classList.add('td-right');
- tdRight.innerText = range.value;
- tr.appendChild(tdRight);
-
- const tdDelete = document.createElement('td');
- tdDelete.classList.add('td-delete');
- const deleteButton = document.createElement('span');
- deleteButton.classList.add('range-option-delete');
- deleteButton.innerText = '❌';
- deleteButton.addEventListener('click', () => {
- range.value = 0;
- range.dispatchEvent(new Event('change'));
- rangeTbody.removeChild(tr);
- });
- tdDelete.appendChild(deleteButton);
- tr.appendChild(tdDelete);
-
- rangeTbody.appendChild(tr);
- });
break;
default:
@@ -462,10 +465,92 @@ const buildOptionsDiv = (game, settings) => {
return;
}
- optionsWrapper.appendChild(settingWrapper);
+ settingsWrapper.appendChild(settingWrapper);
});
- return optionsWrapper;
+ return settingsWrapper;
+};
+
+const buildItemsDiv = (game, items) => {
+ const currentSettings = JSON.parse(localStorage.getItem('weighted-settings'));
+ const itemsDiv = document.createElement('div');
+ itemsDiv.classList.add('items-div');
+
+ const itemsDivHeader = document.createElement('h3');
+ itemsDivHeader.innerText = 'Item Management';
+ itemsDiv.appendChild(itemsDivHeader);
+
+ const itemsDescription = document.createElement('p');
+ itemsDescription.classList.add('setting-description');
+ itemsDescription.innerText = 'Choose if you would like to start with items, or control if they are placed in ' +
+ 'your seed or someone else\'s.';
+ itemsDiv.appendChild(itemsDescription);
+
+ const itemsHint = document.createElement('p');
+ itemsHint.classList.add('hint-text');
+ itemsHint.innerText = 'Drag and drop items from one box to another.';
+ itemsDiv.appendChild(itemsHint);
+
+ const itemsWrapper = document.createElement('div');
+ itemsWrapper.classList.add('items-wrapper');
+
+ // Create container divs for each category
+ const availableItemsWrapper = document.createElement('div');
+ availableItemsWrapper.classList.add('item-set-wrapper');
+ availableItemsWrapper.innerText = 'Available Items';
+ const availableItems = document.createElement('div');
+ availableItems.classList.add('item-container');
+ availableItems.setAttribute('id', `${game}-available-items`);
+
+ const startInventoryWrapper = document.createElement('div');
+ startInventoryWrapper.classList.add('item-set-wrapper');
+ startInventoryWrapper.innerText = 'Start Inventory';
+ const startInventory = document.createElement('div');
+ startInventory.classList.add('item-container');
+ startInventory.setAttribute('id', `${game}-start-inventory`);
+
+ const localItemsWrapper = document.createElement('div');
+ localItemsWrapper.classList.add('item-set-wrapper');
+ localItemsWrapper.innerText = 'Local Items';
+ const localItems = document.createElement('div');
+ localItems.classList.add('item-container');
+ localItems.setAttribute('id', `${game}-local-items`);
+
+ const nonLocalItemsWrapper = document.createElement('div');
+ nonLocalItemsWrapper.classList.add('item-set-wrapper');
+ nonLocalItemsWrapper.innerText = 'Non-Local Items';
+ const nonLocalItems = document.createElement('div');
+ nonLocalItems.classList.add('item-container');
+ nonLocalItems.setAttribute('id', `${game}-remote-items`);
+
+ // Populate the divs
+ items.sort().forEach((item) => {
+ const itemDiv = document.createElement('div');
+ itemDiv.classList.add('item-div');
+ itemDiv.setAttribute('id', `${game}-${item}`);
+ itemDiv.innerText = item;
+
+ if (currentSettings[game].start_inventory.includes(item)){
+ startInventory.appendChild(itemDiv);
+ } else if (currentSettings[game].local_items.includes(item)) {
+ localItems.appendChild(itemDiv);
+ } else if (currentSettings[game].non_local_items.includes(item)) {
+ nonLocalItems.appendChild(itemDiv);
+ } else {
+ availableItems.appendChild(itemDiv);
+ }
+ });
+
+ availableItemsWrapper.appendChild(availableItems);
+ startInventoryWrapper.appendChild(startInventory);
+ localItemsWrapper.appendChild(localItems);
+ nonLocalItemsWrapper.appendChild(nonLocalItems);
+ itemsWrapper.appendChild(availableItemsWrapper);
+ itemsWrapper.appendChild(startInventoryWrapper);
+ itemsWrapper.appendChild(localItemsWrapper);
+ itemsWrapper.appendChild(nonLocalItemsWrapper);
+ itemsDiv.appendChild(itemsWrapper);
+ return itemsDiv;
};
const updateVisibleGames = () => {
diff --git a/WebHostLib/static/styles/weighted-settings.css b/WebHostLib/static/styles/weighted-settings.css
index ae488aff..28ab4a10 100644
--- a/WebHostLib/static/styles/weighted-settings.css
+++ b/WebHostLib/static/styles/weighted-settings.css
@@ -90,6 +90,38 @@ html{
cursor: pointer;
}
+#weighted-settings .items-wrapper{
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
+#weighted-settings .items-div h3{
+ margin-bottom: 0.5rem;
+}
+
+#weighted-settings .items-wrapper .item-set-wrapper{
+ width: 24%;
+}
+
+#weighted-settings .items-wrapper .item-container{
+ border: 1px solid #ffffff;
+ border-radius: 2px;
+ width: 100%;
+ height: 300px;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+#weighted-settings .items-wrapper .item-container .item-div{
+ padding: 0.15rem;
+ cursor: pointer;
+}
+
+#weighted-settings .items-wrapper .item-container .item-div:hover{
+ background-color: rgba(0, 0, 0, 0.1);
+}
+
#weighted-settings #weighted-settings-button-row{
display: flex;
flex-direction: row;