Skip to content

Commit

Permalink
v3.0.0 release (#19)
Browse files Browse the repository at this point in the history
* v3.0.0 release candidate

* Update README.md

* Update README.md

* fix unique multipickup
  • Loading branch information
ChapelR authored Feb 20, 2024
1 parent d20a7bb commit e87a248
Show file tree
Hide file tree
Showing 21 changed files with 181 additions and 100 deletions.
4 changes: 2 additions & 2 deletions dist/simple-inventory.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions dist/simple-inventory.js

Large diffs are not rendered by default.

36 changes: 22 additions & 14 deletions docs/Guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Both of the above would remove 10 items with the ID `"wood"` and 5 items with th
> [!TIP]
> If the inventory doesn't contain an item it's asked to drop, nothing happens. No errors will be thrown, and the items that are present in the command, if any, will be removed as normal. Please be careful as this may hide some bugs.
You can also remove all of the items in one inventory from another inventory by <em>**un**merging</em> the latter drom the former. Like merging, unmerging does not affect the giving inventory, if you want to remove the items from one inventory and add them to another, see [transfers](#transfers) below.
You can also remove all of the items in one inventory from another inventory by <em>**un**merging</em> the latter from the former. Like merging, unmerging does not affect the giving inventory, if you want to remove the items from one inventory and add them to another, see [transfers](#transfers) below.

```
<<newinv _stolenItems>>
Expand Down Expand Up @@ -282,7 +282,15 @@ Want to add an option to drop all items? And how about a way to inspect the item

![Inventory with everything](media/inv-fully-loaded.jpg)

You may also provide the flag`stack` to allow players to drop/transfer entire stacks of items all at once:
There is also a built-in search/filter UI element you can add with the `filter` flag. This will allow players to type to filter the inventory.

```
<<inv $backpack use drop inspect all filter>>
```

![Inventory with everything](media/filter.jpg)

You may also provide the flag `stack` to allow players to drop/transfer entire stacks of items all at once:

```
<<inv $backpack use drop inspect stack all>>
Expand Down Expand Up @@ -317,23 +325,23 @@ You can change the default strings used by the built-in interfaces, for example,

The strings that can be changed in the special passage are as follows:

- `inspect`: **not used** in the default interface, since the user clicks on the names of items to see their descriptions, however, a link for inspecting items may be needed in the future or by users. Default: `"Inspect"`
- `drop`: appears as link text when users can drop items in the interface. Default: `"Drop"`
- `take`: can appear as link text when users can transfer items in the interface. Default: `"Take"`
- `give`: can appear as link text when users can transfer items in the interface. Default: `"Give"`
- `use`: link text for the action allowing consumables to be used. Default: `"Use"`
- `stack`: the text used to refer to an item stack when dropping or transferring whole stacks in the default interface. Default: `"stack"`
- `stackPre`: string appears before the item stack counts. Default: `"&nbsp;&times;&nbsp;"` (that is,&nbsp;&times;&nbsp;)
- `stackPost`: string appears after the item stack counts. Default: `"&nbsp;"`
- `empty`: this string appears when an empty inventory is displayed. In the API, this is handled by a separate property, `Inventory.emptyMessage`, passing this value to `Inventory.strings` won't have any effect! Default: `"&hellip;"`
- `inspect`: **not used** in the default interface, since the user clicks on the names of items to see their descriptions, however, a link for inspecting items may be needed in the future or by users. Default: `Inspect`
- `drop`: appears as link text when users can drop items in the interface. Default: `Drop`
- `take`: can appear as link text when users can transfer items in the interface. Default: `Take`
- `give`: can appear as link text when users can transfer items in the interface. Default: `Give`
- `use`: link text for the action allowing consumables to be used. Default: `Use`
- `stack`: the text used to refer to an item stack when dropping or transferring whole stacks in the default interface. Default: `stack`
- `stackPre`: string appears before the item stack counts. Default: `&nbsp;&times;&nbsp;` (that is,&nbsp;&times;&nbsp;)
- `stackPost`: string appears after the item stack counts. Default: `&nbsp;`
- `empty`: this string appears when an empty inventory is displayed. In the API, this is handled by a separate property, `Inventory.emptyMessage`, passing this value to `Inventory.strings` won't have any effect! Default: `&hellip;`

For example, an `inventory.strings` special passage may look like this:

```
:: inventory.strings
use: "Activate"
take: "Swipe"
empty: "The inventory is empty!"
use: Activate
take: Swipe
empty: The inventory is empty!
```

To do the same thing with the API, the JavaScript code would look like this:
Expand Down
12 changes: 10 additions & 2 deletions docs/Macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ These macros can be used to show the default user-interface components for manag
- `use` allows the player to "use" an item if it is considered a consumable, and using it will expend one of the items and cause it's use code, if any, to be run. Refer to the `<<item>>` macro below.
- `stack` shows a "Drop/Give/Take stack" option at the end of each item listing with more than 1 item in it.
- `all` shows a "Drop/Give/Take all" option at the bottom of the inventory list.
- `filter` shows filter/search box for players to filter their inventories with.

#### Examples

Expand All @@ -226,6 +227,12 @@ These macros can be used to show the default user-interface components for manag

![Inventory with everything](media/inv-fully-loaded.jpg)

```
<<inv $backpack use drop inspect all filter>>
```

![Inventory with filter box](media/filter.jpg)

```
<<inv $backpack use drop inspect stack all>>
```
Expand Down Expand Up @@ -314,8 +321,9 @@ For example:

```
:: inventory.strings
use: "Activate"
take: "Swipe"
use: Activate
take: Swipe
drop: Discard
```

The strings you can change are:
Expand Down
30 changes: 14 additions & 16 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Simple Inventory 3

> [!NOTE]
> Simple Inventory v3 is in beta right now. It should work, but there may be bugs and rough edges. Please [report any issues](https://github.com/ChapelR/simple-inventory/issues/new) you encounter!
The new simple inventory system. No longer a part of [my macro collection](https://macros.twinelab.net/), it's now its own thing. If you need the old version, grab [an older release (v2.10.0 or lower) of my custom macro collection](https://github.com/ChapelR/custom-macros-for-sugarcube-2/releases). If you find any bugs or have any issues, please [let me know](https://github.com/ChapelR/simple-inventory/issues/new)!

The new version of my simple inventory system. No longer a part of [my macro collection](https://macros.twinelab.net/), it's now its own thing. If you need the old version, grab [an older release (v2.10.0 or lower) of my custom macro collection](https://github.com/ChapelR/custom-macros-for-sugarcube-2/releases).
> [!TIP]
> New to Simple Inventory? Start with the [guide](Guide.md) and [recipes](Recipes.md) to see what the system is capable of!
- [Downloads](https://github.com/ChapelR/simple-inventory/releases)
- [Installation](#getting-started)
Expand All @@ -20,19 +20,17 @@
- [Demo](demo.html ":ignore")
- [Source Code](https://github.com/ChapelR/simple-inventory/)

Version 3 includes most of the features and functionality of v2, and adds:

- Consumables. Items can be associated with SugarCube code (sort of like a widget) or a callback function that can be executed when the item is "used."
- Item descriptions (as dialogs).
- Item names. You can provide items with both names and IDs, using the ID in code while the name will be used for displaying it in the game.
- Item and inventory tags. You can add tags to items and inventories as metadata.
- Item stacking. Duplicate items in an inventory can now *stack* meaning they'll take up one visual "slot" in the inventory, but will have a counter showing how many are present.
- More robust built-in UI options and components.
- A cleaned up, mostly simplified API and code structure.

Most new features are optional; you don't have to define items, for example. With the exception of stacking, it's possible to use this inventory in almost exactly the same way as v2.

This new simple inventory is totally incompatible with previous versions. Updating will require rewrites, so you may want to stick with v2 in ongoing projects.
Features:
- Support for an arbitrary number of inventories, so they can be used as player inventories, chests, rooms, NPC inventories, etc.
- Simple interfaces for complex operations, like inventory transfers, merges, and comparisons.
- Items can optionally be predefined, but you may also just use bare strings for ultimate simplicity.
- Premade logic for unique and un-tradeable items.
- Built-in support for "consumables" like potions, which can be paired with a code "handler" for easy item creation.
- Duplicate items in a given inventory "stack" automatically.
- A suite of customizable UI components for displaying and allowing users to manage inventories easily.
- Text search/filter system built-in as an optional UI component.

Most features are optional; you don't have to define items, for example. With the exception of stacking, it's possible to use this inventory in almost exactly the same way as v2. Note that this new simple inventory is totally incompatible with previous versions. Updating will require code rewrites, so you may want to stick with v2 in ongoing projects.

## Getting Started

Expand Down
18 changes: 9 additions & 9 deletions docs/demo.html

Large diffs are not rendered by default.

Binary file added docs/media/filter.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions docs/recipes/collectibles.html

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions docs/recipes/crafting.html

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions docs/recipes/equipment.html

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions docs/recipes/keys.html

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions docs/recipes/potions.html

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions docs/recipes/shop.html

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions docs/recipes/shop/index.twee
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Gold: @@#gold;<<= $gold>>@@
<</link>>

:: Inventory
<<inv $player>>
<<inv $player filter>>

:: Start
You are at your house.
Expand All @@ -115,10 +115,10 @@ Next to you is your storage locker!
[[Go to the market|Market]]

:: Storage
<h2>On hand:</h2>
<<give $player $storage stack all>>
<h2>In storage:</h2>
<<take $storage $player stack all>>
<h2>On hand:</h2>\
<<give $player $storage stack all filter>>
<h2>In storage:</h2>\
<<take $storage $player stack all filter>>

[[Go back|Start]]

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "simple-inventory",
"version": "3.0.0-beta2",
"version": "3.0.0",
"description": "Simple inventory system for Twine/SugarCube-2.",
"main": "index.js",
"directories": {
Expand Down
63 changes: 54 additions & 9 deletions src/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
text = text || Inventory.strings.inspect;
return $(document.createElement(button ? 'button' : 'a'))
.addClass('inspect-link')
.wiki("" + text)
.wiki("" + id)
.ariaClick(() => {
Item.get(id).inspect();
});
Expand All @@ -91,8 +91,10 @@

// undocumented UI helper
function dropLink (self, id, text, button = false, target = null) {
if (String(text).toLowerCase().trim() === "give" || !!target) {
text = Inventory.strings.give
if (String(text).toLowerCase().trim() === "give") {
text = Inventory.strings.give;
} else if (String(text).toLowerCase().trim() === "take") {
text = Inventory.strings.take;
} else if (!text || String(text).toLowerCase().trim() === "drop") {
text = Inventory.strings.drop;
}
Expand All @@ -113,8 +115,10 @@
}

function dropStackLink (self, id, text, button = false, target = null) {
if (String(text).toLowerCase().trim() === "give" || !!target) {
text = Inventory.strings.give
if (String(text).toLowerCase().trim() === "give") {
text = Inventory.strings.give;
} else if (String(text).toLowerCase().trim() === "take") {
text = Inventory.strings.take;
} else if (!text || String(text).toLowerCase().trim() === "drop") {
text = Inventory.strings.drop;
}
Expand All @@ -136,8 +140,10 @@
}

function dropAllLink (self, text, button = false, target = null) {
if (String(text).toLowerCase().trim() === "give" || !!target) {
text = Inventory.strings.give
if (String(text).toLowerCase().trim() === "give") {
text = Inventory.strings.give;
} else if (String(text).toLowerCase().trim() === "take") {
text = Inventory.strings.take;
} else if (!text || String(text).toLowerCase().trim() === "drop") {
text = Inventory.strings.drop;
}
Expand Down Expand Up @@ -191,9 +197,10 @@
$entries = self.list.map(id => {

const appendMe = [];
const itemName = !!(Item.has(id) && Item.get(id).displayName) ? Item.get(id).displayName : id;

if (options.description && Item.has(id) && Item.get(id).description) {
appendMe.push(inspectLink(self, id, Item.has(id) ? Item.get(id).name : id));
appendMe.push(inspectLink(self, id, itemName));
} else {
appendMe.push($(document.createElement('span')).append(Item.has(id) ? Item.get(id).name : id).addClass('item-name'));
}
Expand Down Expand Up @@ -222,7 +229,10 @@
return $(document.createElement('li'))
.append(appendMe)
.addClass('simple-inventory-listing')
.attr('data-item-id', iid);
.attr({
'data-item-id' : iid,
'data-keyword' : itemName
});
});

if (options.all) {
Expand All @@ -246,13 +256,48 @@
return $list;
}

function searchbox () {
const $wrapper = $(document.createElement("div")).addClass("simple-inventory-filter");
const $textbox = $(document.createElement("input"))
.attr({
type : "text",
placeholder : "Filter..."
})
.on("input", function () {
const value = $textbox.val().trim().toLowerCase();
const $listings = $wrapper.parent().find("ul.simple-inventory-list li.simple-inventory-listing:not(.all-listing)");
if (!value) {
$listings.show();
return;
}
$listings.each( function (i, el) {
const $el = $(el);
if (!$el || !$el.length) {
return;
}
const keyword = $el.attr("data-keyword");
if (keyword.substring(0, value.length).trim().toLowerCase() !== value) {
$el.hide();
} else {
$el.show();
}
});
});
$wrapper.append($textbox);
return $wrapper;
}

// constructs inventory interface
// very opinionated by necessity
// include resipes for different UIs in docs
Inventory.prototype.interface = function (opts = {}, el = null) {
const self = this;

const $wrapper = $(document.createElement('div')).addClass('simple-inventory-wrapper');

if (opts.filter) {
$wrapper.append(searchbox());
}
$wrapper.append(displayInventoryList(this, opts));

$(document).on(':inventory-update.simple-inventory.gui-built-in', () => {
Expand Down
4 changes: 4 additions & 0 deletions src/inv.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
if (Object.keys(dataOrInv).includes(item) && isUnique(item)) {
return; // item is unique, can't be added.
}

if (num > 1 && isUnique(item)) {
num = 1;
}

if (!Object.keys(dataOrInv).includes(item)) {
dataOrInv[item] = 0;
Expand Down
1 change: 1 addition & 0 deletions src/macros.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
drop : this.args.includes('drop'),
all : this.args.includes('all'),
stack : this.args.includes('stack'),
filter : this.args.includes('filter'),
dropActionText : this.name === 'inv' ? 'Drop' : Inventory.strings[this.name.trim().toLowerCase()],
classes : `macro-${this.name}`
};
Expand Down
24 changes: 15 additions & 9 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,33 @@
.split(/\n/g);
}

function breakPairs (line, sep) {
sep = sep || DEFAULT_SEPARATOR;
return line.trim().split(sep);
function breakPairs (line) {
return line.trim().split(DEFAULT_SEPARATOR);
}

function parseText (text, sep) {
function parseText (text) {
const lines = splitLines(text);
const ret = {};
lines.forEach(l => {
const pair = breakPairs(l, sep);
ret[pair[0].trim()] = pair[1].trim();
if (l && l.trim() && l.includes(DEFAULT_SEPARATOR)) {
const pair = breakPairs(l);
ret[pair[0].trim()] = pair[1].trim();
}
});
return ret;
}

function parseSourcePassage (psg) {
if (!Story.has(psg)) {
try {
if (!Story.has(psg)) {
return {};
}
const settings = parseText(Story.get(psg).text);
return settings;
} catch (err) {
console.error(err.message, err);
return {};
}
const settings = parseText(Story.get(psg).text);
return settings;
}

// parse source passage and set strings
Expand Down
8 changes: 8 additions & 0 deletions src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,12 @@ ul.simple-inventory-list {
.drop-link:focus,
.drop-link:hover {
color: #f88;
}

.simple-inventory-filter {
text-align: right;
}

.simple-inventory-filter input {
display: inline-block;
}
Loading

0 comments on commit e87a248

Please sign in to comment.