Giter Site home page Giter Site logo

peter-kish / gloot Goto Github PK

View Code? Open in Web Editor NEW
408.0 7.0 17.0 1.89 MB

A universal inventory system for the Godot game engine.

License: MIT License

GDScript 100.00%
gdscript godot-engine godotengine inventory inventory-management inventory-system plugin godot inventory-management-system

gloot's People

Contributors

cooldotty avatar gumpdev avatar ilyabrin avatar leewannacott avatar muha0644 avatar peter-kish avatar polatrite avatar slashscreen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

gloot's Issues

Changing the `inventory` property of `CtrlInventoryGridEx` results in an assertion

So other thing I've noticed is that when I set an inventory for the CtrlInventoryGridEx via script, unset it and set it again... the sort messes up... also if I use the item (potion) in the inventory and remove it, I believe the empty slot is still selected and sometimes happens that the items change positions an overlap. Try setting it up this way... You have 1 HUD for the inventory and many units with their inventory that have for example consumable items... on click of the unit you set the HUD's ctrl inventory to that units inventory and if you use the item for an example potion of that unit and remove it by using remove_item(item) function and select other unit, you'll get errors like Assertion failed: Item not found in the inventory! The sorting will be messed etc.

Originally posted by @filipinyo in #59 (comment)

`InventoryGridEx` bad performance when mouse moves

  1. create a InventoryGridEx with a 20x40 or bigger inventory
  2. start the game
  3. move the mouse around a bit and see the framerate drop

tested in in godot 3.5.1

The problem seems to be in _input.

Running in a for loop over every cell to check a ton of properties and if the mouse is in each field seems to be connected to it, but I haven't read the code in detail. This is not a problem in the non-ex version of InventoryGrid

profiler

create_and_add_item() still seems to be only adding the first prototype

          Yup, there was a bug. Luckily it was an easy fix.

create_and_add_item() should be working properly now.

Originally posted by @peter-kish in #93 (comment)

I think this issue is still happening. I've tried several different methods to create the items, but the issue persists. get_prototype() does return the correct protoset however.

plugin.cfg

name="GLoot"
description="A universal inventory system for the Godot game engine"
author="Peter Kish"
version="2.2.0"
script="gloot.gd"

protoset

[
  {
    "id": "wheat",
    "name": "Wheat",
    "stack_size": "1",
    "weight": 1
  },
  {
    "id": "iron",
    "name": "Iron",
    "stack_size": "1",
    "weight": 10
  },
  {
    "id": "wood",
    "name": "Wood",
    "stack_size": "1",
    "weight": 5
  },
  {
    "id": "bread",
    "name": "Bread",
    "stack_size": "1",
    "weight": 2
  }
]

code for testing

var protoset = preload("res://gloot_inventory/items_protoset.tres")

func _ready():
	PlayerManager.player = self
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	
	
	#### testing
	var item = InventoryItem.new()
	item.prototype_id = "wheat"
	inventory_stacked.add_item_automerge(item) # creates wheat
	item = InventoryItem.new()
	item.prototype_id = "bread"
	inventory_stacked.add_item(item) # does not create bread
	inventory_stacked.create_and_add_item("bread") # does not create bread
	
	print(inventory_stacked.create_and_add_item("bread").get_title()) # does not create bread, returns wheat
	print(protoset.get_prototype("bread")) # outputs the correct prototype for bread
	#### testing

Handle double-click in the inspector plugin

Double-clicking items in the inspector plugin list could be used to either remove (analog to adding) or edit that item.
This could speed up inventory management workflows.

Cleaning up inside `_ready()` can have various side effects

CtrlInventoryGrid, CtrlInventory and CtrlItemSlot clean up all child nodes in case the node has been duplicated inside the editor. This is because duplicating a parent node often results in duplicate child nodes in case the child nodes are dynamically created inside _ready() (they get duplicated, plus dynamically created).

This can have some side effects, as not all child nodes are dynamically created. Some of them may have been created from the editor. Those would be cleaned up and end up missing in the duplicated parent node.

Ideally, _ready() would only clean up nodes that have been dynamically created.

Implement a `CtrlInventoryGrid` helper method to obtain the item under the mouse cursor

As discussed in #69, it would be useful to have a way of knowing which item is under the mouse cursor when working with CtrlInventoryGrid (but also with other Ctrl* classes).

Either by defining signals similar to the mouse_entered() and mouse_exited() signals of the Control class (for example mouse_entered_item(item) and mouse_exited_item(item)) which would trigger when the user hovers over the given items, or by just defining a method that will return the hovered item.

Implement drag and drop items between inventories to work out-of-the-box

Currently there is an example that demonstrates item transfers using drag and drop between two CtrlInventoryGrid controls. The purpose of this example is just to demonstrate how such a feature could be implemented by the user, but the plugin itself implements no item transfers using the provided UI controls (CtrlInventory, CtrlInventoryStacked and CtrlInventoryGrid).

Ideally, the user would be able to drag and drop items between inventories out-of-the-box: without the need for extra user code or special Control classes (as long as they use the same protoset).
This could be made so that it works with all UI control classes and with an arbitrary number of displayed controls (would probably require a globally visible autoloaded class to track the dragged InventoryItem).

Implement plugin settings

Some plugin parameters (size and position of UI controls etc.) could be stored as settings, making them persist across sessions.

Somewhat related to #22.

Changes for inventory_grid.gd regarding create_and_add_item for implementing get_item_at_position

Hey there. Since create_and_add_item function has been added yesterday, I believe that it needs a separate implementation for the inventory_grid.gd, because when we add and create an item in inventory_grid, it also gets added a position, but in the base inventory, item position is not added. I've noticed this because I wanted to implement a function that gets an item at the certain position in the inventory. This function would be useful for mapping items to hotkeys etc.

For getting item at the position I've made this function

func get_item_at_position(selected_position: Vector2) -> InventoryItem:
	if(
		selected_position.x < 0 || 
		selected_position.x > size.x ||
		selected_position.y < 0 ||
		selected_position.y > size.y
	):
		assert("Selected position out of bounds")

	for item in get_items():
		var item_position = item.get_property(KEY_GRID_POSITION, Vector2.ZERO)
		if (
			item_position.x == selected_position.x && 
			item_position.y == selected_position.y
		):
			return item
	
	return null

For overriding the base classes function we can use the same function which calls the inventory_grid's add_item functions that handles position properties.

func create_and_add_item(prototype_id: String) -> InventoryItem:
	var item: InventoryItem = InventoryItem.new()
	item.prototype_id = prototype_id
	if add_item(item):
		return item
	else:
		item.free()
		return null

If this is already possible in the current implementation, I'd like to know how, so I can use it the way it was meant to be used :D

PS: I really like the plugin

`CtrlInventoryGridEx` crashes when destroyed

This seems to happen when the linked InventoryGrid instance has been removed prior to the CtrlInventoryGridEx isntance.
A simple way to reproduce this is by making the InventoryGrid a child of the CtrlInventoryGridEx in the scene.

Assertions when desterilizing `Vector2` fields

Hello, I tried to recreate what was written on the readme page about serialization and deserialization, but it doesn't seem to work. Maybe I am doing something wrong? Here is how I try to use it. The file contains this:

{"node_name":"InventoryGridPlayer","item_protoset":"res://ItemProtoset.tres","items":[{"node_name":"2x2_bomb","protoset":"res://ItemProtoset.tres","prototype_id":"2x2_bomb"}],"size":"(10, 5)"}

The serialization code:

 if Input.is_action_just_pressed("save_and_close"):
  # Serialize the inventory into a JSON string
  var inventory: Inventory = get_node("Inventory/InventoryGridPlayer")
  var dict: Dictionary = inventory.serialize()
  var json = JSON.print(dict)
  # Save to file
  var file = File.new()
  file.open("res://inventory_save.res", File.WRITE)
  file.store_string(json)
  file.close()

then trying to deserialize the file on launch:

func _ready():
var file = File.new()
file.open("res://inventory_save.res", File.READ)
var read_file = file.get_as_text()
file.close()

Deserialize the inventory from a file

var inventory: Inventory = get_node("Inventory/InventoryGridPlayer")
var res: JSONParseResult = JSON.parse(read_file)
if res.error == OK:
var dict = res.result
inventory.deserialize(dict)

or I tried to deserialize on a button press, doesn't work either :(
The target inventory stays empty even if the file contained the json.
Also the Output is giving me this:

Key 'size' has wrong type! Expected '5', got '4'!

Maybe this is the reason, idk what this is, I was copying everything from the instruction.
Maybe I should refresh the inventory or something?

Originally posted by @Ingeniouz in #62

Add `create_and_add_item_at` and `get_item_at` helper methods in `InventoryGrid`

Discussed in #38

Originally posted by filipinyo August 16, 2022
Hey there. Since create_and_add_item function has been added yesterday, I believe that it needs a separate implementation for the inventory_grid.gd, because when we add and create an item in inventory_grid, it also gets added a position, but in the base inventory, item position is not added. I've noticed this because I wanted to implement a function that gets an item at the certain position in the inventory. This function would be useful for mapping items to hotkeys etc.

For getting item at the position I've made this function

func get_item_at_position(selected_position: Vector2) -> InventoryItem:
	if(
		selected_position.x < 0 || 
		selected_position.x > size.x ||
		selected_position.y < 0 ||
		selected_position.y > size.y
	):
		assert("Selected position out of bounds")

	for item in get_items():
		var item_position = item.get_property(KEY_GRID_POSITION, Vector2.ZERO)
		if (
			item_position.x == selected_position.x && 
			item_position.y == selected_position.y
		):
			return item
	
	return null

For overriding the base classes function we can use the same function which calls the inventory_grid's add_item functions that handles position properties.

func create_and_add_item(prototype_id: String) -> InventoryItem:
	var item: InventoryItem = InventoryItem.new()
	item.prototype_id = prototype_id
	if add_item(item):
		return item
	else:
		item.free()
		return null

If this is already possible in the current implementation, I'd like to know how, so I can use it the way it was meant to be used :D

PS: I really like the plugin

update_json_data nonexistent

When closing the ProtoSet editor, Godot throws
res://addons/gloot/editor/edit_protoset_button.gd:42 - Invalid call. Nonexistent function 'update_json_data' in base 'Resource (item_protoset.gd)'.

Protoset editor doesn't write the changes to the file system

Changes done to protosets using the protoset editor are often not written to the file system.
Both the protoset editor and the "Json Data" field reflect the changes, but by looking at the raw .tres file it is obvious that the changes are not saved.
This results in changes being lost after the Godot editor is closed.

However, adding some debug prints shows that protoset.emit_changed() is actually being called.

Will have to do some additional analysis to figure out if this is a Godot issue.

Merge and move getters for item icons and titles

Helper functions like _get_item_title() and _get_item_texture() are implemented in multiple places in different ways.
All of them should be merged together and moved into a single common place.

Crash with get_item_position

line 33 of inventory_grid.gd causes a crash while dragging an item from an inventory to another, when the first inventory is completely full, but the item was not dropped in a free space on the second inventory. commenting out this line fixes the issue.

Stack size support for `inventoryGrid` (Minecraft style)

In some games that use a grid based inventory system it would be useful to have the support for item stacks, similar to Minecraft.
This would require storing the current stack size for a given item, as well as the maximal stack size.

Undo/redo doesn't work after switching tabs

In some cases (adding/removing items) undo and redo operations don't work after switching tabs.

I assume that the inspector controls get re-instantiated after tab switch and methods registered with add_do_method and add_undo_method don't get called because the original control instance doesn't exist anymore.

add_item_automerge should not add if has custom properties

I'd expect that using add_item_automerge would only add to matching items, not ones with extra properties defined. Like say I have a unique version of an item you could get, if I get another normal version of that item, it shouldn't add to the unique item which it currently does unless I'm using it incorrectly somehow.

Crash during some drag and drop interactions

While creating a self-refilling container to allow dragging into other inventorys, i encountered a crash involving line 389 of ctrl_inventory_grid.gd.

A possible solution that has been working for me is to put this code before it:

if typeof(source_inventory) == TYPE_NIL:
		return

I was not sure what was causing the crash, but it seems to involve dragging a item that stopped existing in my code that deleted items that were dragged out of the inventory.

Adding items to inventories from code

ok I've been banging my head against this for the past half week. I'm having a heck of a time getting items to add to my inventory. Also, if you don't want these kind of question in the issues feel free to just close it. I'll completely understand.

I have a basic scene for my inventory with a CtrlInventoryGrid as a child node. I'm creating the InventoryGrid in code (see below). I'm fairly certain the InventoryGrid node is getting created and linked to the CtrlInventoryGrid via the inventory_path property. However when I try to find a free place for the item or add an item I get an error that says:

Invalid call. Nonexistent function 'get_property' in base 'NiL'.

Additionally, inventory_grid_node.get_item_by_id("laptop") seems to be null so it's acting like it's not even finding the item in the protoset.

[
    {
        "id": "laptop",
        "width": 2,
        "height": 2,
        "name": "Laptop",
        "description": "A general purpose laptop for business.",
        "image": "res://items/assets/laptop.png"
    }
]

I see that get_property is a method of InventoryItem. is the get_item_by_id function I'm trying to call just searching for the item id in the exiting inventory? also if thats the case, how does one add an item to an inventory in code?

func _ready():
	var inventory_grid = initialize_inventory_grid()
	create_inventory_grid(inventory_grid)
	assign_inventory_grid_to_panel(inventory_grid)

        var inventory_grid_node = get_node("InventoryGrid")
	
	add_item(inventory_grid_node)
	

func initialize_inventory_grid() -> InventoryGrid:
	var inventory_grid = load("res://addons/gloot/inventory_grid.gd").new()
	inventory_grid.size = Vector2(4, 5)
	inventory_grid.item_protoset = load("res://items/ItemProtoset.tres")
	inventory_grid.name = "InventoryGrid"
	return inventory_grid

func create_inventory_grid(inventory_grid):
	add_child(inventory_grid)

func assign_inventory_grid_to_panel(inventory_grid: InventoryGrid):
	var inventory_panel = get_node("CtrlInventoryGrid")
	inventory_panel.inventory_path = inventory_grid.get_path()

func add_item(inventory_grid_node):
	var item = inventory_grid_node.get_item_by_id("laptop")
	var item_position = inventory_grid_node.find_free_place(item)
	inventory_grid_node.add_item_at(item, item_position)

Clickthrough problem

scroll boxes do not obey mouse input filter flags on parent control objects I.E. Stop, Pass, Ignore.

instead of having input blocked by the filter, you can click behind a control node and interact with a inventory behind it, the same goes for control nodes with clipped outside checked, for example a scrollbox will allow you to drag items not visible due to scrolling.

Consider adding `CtrlInventoryGridEx`

So far I tried to avoid making the UI control classes "too customizable", simply because a UI is something very specific for each game and I was afraid that increasing customizability to cover as many of those cases as possible could overcomplicate those classes (apart from being a lot of work).

Because if that I was mostly focusing on making some very basic UI control classes that are easy to understand and that could easily be extended or build on top of by the user (I was even thinking about making the grid lines optional). Borders, background images, labels etc. I meant to be added in combination with other control nodes (TextureRect, ColorRect, Label etc.).

But seeing that a lot of people are using the plugin exactly because of the UI control nodes (especially CtrlInventoryGrid) I think adding something like a CtrInventoryGridEx (extended) node could be a compromise. It could support some additional customization, while CtrlInventoryGrid would stay "barebones" enough for anyone who wants to build something unique on top of it.

Originally posted by @peter-kish in #41 (comment)

Item icons are not displayed when editing ItemSlot

InventoryItem icons are not displayed when editing an ItemSlot node, which is not consistent with the other GLoot inspector controls.
The icon of the given item could be obtained in a similar way as in the other controls.

Implement `CtrlItemSlotEx`

Similar to CtrlInventoryGridEx, it could offer some extended customizability to CtrlItemSlot (customizable field style, highlighted field style etc.).

Is this line valid?

var old_prototype_id = prototype_id
if old_prototype_id != prototype_id:

Is this line have a possibility of getting triggered? Because old_prototype_id is set as prototype_id, in line 31 there's an if statement for that, when is that if expected to be called?

Item prototype categorization

With a growing number of item prototypes, it would be useful to be able to organize them inside various categories.
Categories should contain item prototypes, but also other categories if needed.
This would require a new protoset JSON structure that is also backward compatible.

Unable to load addon

Hey,

plugin looks cool but I ran into an error in gloot.gd

image

Couldn't fully preload the script, possible cyclic reference or compilation error. Use "load()" instead if a cyclic reference is intended.

My version of godot is 3.4.4 and I downloaded the freshest version released just couple of minutes ago.

Best regards

Getting a JSONItemPrototype from an ItemProtoset.

Apologies for the inconvenience, but I was running some code to dynamically create an ItemProtoset and found that when receiving a JSONItemPrototype, the received data is incorrect.

Here is some of my code that I used for it:

var item_set = ItemProtoset.new() #Create ItemProtoset

var item_dict = {"id":"TEST"} #Create Item with an id using a dictionary.
item_set.add_prototype(JSON.stringify(item_dict)) #Add JSONItemPrototype to ItemProtoset by converting the dictionary to JSON format.
print(JSON.stringify(item_dict)) #Print Item as JSON.
print(item_set.has_prototype(JSON.stringify(item_dict))) #Print 'true' if item exists.
print(item_set.get_prototype(JSON.stringify(item_dict))) #Print Item received from ItemProtoset.

The output is:

{"id":"TEST"}
true
{ "id": "{\"id\":\"TEST\"}" }

I'm not sure if this is an error of the plugin or an error of my code, but I've tried multiple different methods to get the data and this is the only way that I could find that didn't return an error.

How to transfer?

Hello, i have spend one Day on it, but i didn't find it out how i can transfer the Items to another Inventory....
Please... Help me...

Godot 4.1 editor plugin signature changed

Situation
when i upgraded godot to 4.1, the language server prompts this error

res://addons/gloot/editor/inventory_inspector_plugin.gd:47 - Parse Error: The function signature doesn't match the parent. Parent signature is "_parse_property(Object, Variant.Type, String, PropertyHint, String, int, bool) -> bool".

Upon checking, its related to upstream issue godotengine/godot#75311, where a code gen fix has resulted in changed function signature

Expected Behavior
Editor plugin to match the expected parent signature

i can raise a PR if you want, given its just 1 LOC :)

Add optional spacing between items in `CtrlInventoryGrid`

I think it's something that's fairly commonly used but would be difficult to implement on top of CtrlInventoryGrid and now I'm seriously considering to add it as an option.
As you already noted, displaying items that are larger than 1x1 tile would be somewhat of a challenge (the width of a 3x3 item is no longer 3 * field_dimensions.x, but 3 * field_dimensions.x + 2 * spacing) and the artwork would need be sized accordingly.

Originally posted by @peter-kish in #41 (comment)

Having trouble displaying an item's image in Controls, but they work fine inside the Inspector plugin

I followed the steps to setup the plugin (recapping here):

  1. Created an ItemProtoset, JSON below:
[
	{
		"id": "Fireball",
		"name": "Fireball",
		"image": "res://assets/items/health-potion.png"
	},
	{
		"id": "Pyroblast",
		"name": "Pyroblast",
		"image": "res://assets/items/health-potion.png"
	},
	{
		"id": "Meteor",
		"name": "Meteor",
		"image": "res://assets/items/health-potion.png"
	},
	{
		"id": "Flame Horizon",
		"name": "Flame Horizon",
		"image": "res://assets/items/health-potion.png"
	},
	{
		"id": "Rising Flames",
		"name": "Rising Flames",
		"image": "res://assets/items/health-potion.png"
	}
]
  1. Created both an InventoryGrid and InventoryStacked node in my debug scene.
  2. Assigned the above ItemProtoset to these nodes and configured the width/height and capacity respectively
  3. Added individual items to the inventory

image

  1. Created both a CtrlInventoryGrid and CtrlInventoryStacked, pointing at their respective Inventory nodes
  2. Made sure these are positioned well and visible within the scene
  3. Set the default_item_texture/icon properties in each

image

  1. Launch the project

image

Expected results:

The few items configured in each Inventory would display inside the controls.

Actual results:

The controls display fine, but have no items within them.

Version stuff:

Latest master d71a32358, Godot v3.5.beta4.official, GDscript binary (no mono), Windows 10

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.