[don't fix] some way to lock cursor stack

Place to ask discuss and request the modding support of Factorio. Don't request mods here.
Post Reply
User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

[don't fix] some way to lock cursor stack

Post by aubergine18 »

Problem described here: viewtopic.php?f=25&t=33935

Possible solution: a flag that indicates an item can't move from cursor stack to an inventory.

An event could be triggered (event properties would be the stack, and target inventory):

* I could do nothing = item remains in cursor stack
* I could clear cursor stack and programatically put item (or some other item) in to target inventory

Note: Within the event I might want to change the cursor stack to some other item. For example:

* Stack contains item Y
* I choose to put item Y in to target inventory
* I put item X in to cursor stack

An alternate approach: New event for when item moves from cursor stack to inventory. I could just leave it in that inventory, or delete it from the inventory, or put it back in cursor stack, etc.
Last edited by aubergine18 on Sun Oct 09, 2016 8:41 am, edited 3 times in total.
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

Rseding91
Factorio Staff
Factorio Staff
Posts: 13250
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: some way to lock cursor stack

Post by Rseding91 »

This isn't likely to ever happen. It's a very specific thing that the entire game doesn't support. Right now everything is setup in a way that items can go anywhere and changing that would add a ton of needless complexity to what's already complex.
If you want to get ahold of me I'm almost always on Discord.

User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: [wont fix] some way to lock cursor stack

Post by aubergine18 »

I've managed to work around the issue (as far as I can tell) as follows:

Code: Select all

when cursor stack changes
  if i know i was holding special item
    check in following places for that item (as applicable)
      - player
      - player.selected
      - player.opened
      - floor
    ..and if found, delete the item/stack and create new one in player cursor
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

Nexela
Smart Inserter
Smart Inserter
Posts: 1828
Joined: Wed May 25, 2016 11:09 am
Contact:

Re: [wont fix] some way to lock cursor stack

Post by Nexela »

aubergine18 wrote:I've managed to work around the issue (as far as I can tell) as follows:

Code: Select all

when cursor stack changes
  if i know i was holding special item
    check in following places for that item (as applicable)
      - player
      - player.selected
      - player.opened
      - floor
    ..and if found, delete the item/stack and create new one in player cursor
Nice -- until on_player_dropped_item how are you implementing the floor checking (or will this wait until said event) if someone is using some obscenely high reach etc. I can't remember if long reach dropping is a thing or not :)

As far as I can tell I think that should cover most everything. player.selected would cover belts and quick-transfering-into-entitys, .opened covers inventorys. etc etc

I would surely be interested in using whatever you come up with in my works if you are ok with that also

User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: [don't fix] some way to lock cursor stack

Post by aubergine18 »

This is a WIP (requires some bits of Stdlib; Position and Tile):

Code: Select all

-- luacheck: globals script global game Position Tile

_G.cursor = {}

--[[ INTERFACE ]]

function _G.cursor.latch( player, itemName, onCancel, data )
  global.cursor = global.cursor or {}
  global.cursor[player.name] = { itemName = itemName, onCancel = onCancel, data = data }
end

function _G.cursor.state( player )
  global.cursor = global.cursor or {}
  return global.cursor[player.name]
end

function _G.cursor.unlatch( player )
  global.cursor = global.cursor or {}
  global.cursor[player.name] = nil
end

function _G.cursor.pickUp( player, itemName, cursor )
  player.clean_cursor()

  cursor = cursor or player.cursor_stack

  local stack = type(itemName) == 'table' and itemName or { name = itemName }

  if cursor.can_set_stack( stack ) then
    cursor.set_stack( stack )
    game.print('picked up '..itemName)
    return true
  else
    game.print('failed to pick up '..itemName)
    return false
  end
end

--[[ HELPERS ]]--

-- is itemName inside target?
local function isInside( target, itemName )
  if not target then return end
  if target.get_item_count( itemName ) > 0 then
    target.remove_item( itemName )
    game.print 'found in an entity'
    return true
  end
end

-- is itemName on floor near player?
local function dropNear( player, itemName )
  -- doesn't search belts: https://forums.factorio.com/viewtopic.php?p=213509#p213509
  local found = player.surface.find_entities_filtered {
    type = 'item-entity';
    name = 'item-on-ground';
    area = Position.expand_to_area( Tile.from_position( player.position ), 32 );
  }
  for _,item in pairs(found) do
    if item.stack.valid_for_read and item.stack.name == itemName then
      item.destroy()
      game.print 'found on floor'
      return true
    end
  end
end

--[[ EVENTS ]]-- events.lua

function _G.cursor.onChange( player )

  local monitor = global.cursor and global.cursor[player.name]

  if monitor then

    local itemName = monitor.itemName
    local cursor   = player.cursor_stack

    if cursor.valid_for_read and cursor.name == itemName then
      return -- these are not the droids you are looking for...
    end

    local selected = player.selected
    local opened   = player.opened

    -- construction cancelled?
    if isInside( player, itemName ) then
      game.print 'player cancelled construction'
      -- unlatch cursor
      _G.cursor.unlatch( player )

      -- trigger cancel event?
      if monitor.onCancel then
        game.print 'trigger cancel event'
        monitor.onCancel( player, itemName, monitor.data )
      end

      return
    end

    -- find item and pick it up
    -- TODO: vehicle?
    if isInside( selected, itemName )
    or isInside( opened  , itemName )
    or dropNear( player  , itemName ) then
      _G.cursor.pickUp( player, itemName )
    else
      game.print 'could not find monitored item'
    end
  end
end
It needs wiring up to the cursor change event like so:

Code: Select all

-- cursor stack change
script.on_event( defines.events.on_player_cursor_stack_changed, function( data )
  local player = game.players[data.player_index]
  _G.cursor.onChange( player )
end )
When you want to latch whatever the player is holding, use _G.cursor.latch()

Get current state for a player with _G.cursor.state()

Clear latch for player with _G.cursor.unlatch()

While latched:

* Player can cancel build by pressing Q or putting cursor stack in their quickbar or inventory
* If they try dropping it, or putting it in some other inventory (eg. chest, assembler, etc) it won't be allowed

Seems to work pretty well in my current experimenting, although I've not tested stuff like vehicles yet. As for reach distance, meh. Hopefully that `on_player_dropped_item ` (or similar) event can be added to mitigate issues with reach distance (and also remove need to to area surface search for item-entity entities).

Also, for my use case, the stack size is always 1 so I've not bothered testing for larger stack sizes.
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

Nexela
Smart Inserter
Smart Inserter
Posts: 1828
Joined: Wed May 25, 2016 11:09 am
Contact:

Re: [don't fix] some way to lock cursor stack

Post by Nexela »

I did a quick glance (5am, eyesbleed,upfordays) but didn't see checking for dropping on a belt :)
Edit: Just seen your comment --- so I give you some pseudo code! : I think what rsedding was getting at is dropping to a belt is handled differently as the item is basically inserted into a transport line "inventory" and not "on ground"

Code: Select all

if player.selected.type = "transportbelttypes" --just hint because this is not a type obviously :)

player.selected.get_transport_line(1).remove_items(blah)
player.selected.get_transport_line(2).remove_items(blah)
Last edited by Nexela on Sun Oct 09, 2016 9:37 am, edited 1 time in total.

Nexela
Smart Inserter
Smart Inserter
Posts: 1828
Joined: Wed May 25, 2016 11:09 am
Contact:

Re: [don't fix] some way to lock cursor stack

Post by Nexela »

Also some possible (minor) performance tweaks

Code: Select all

  if target.get_item_count( itemName ) > 0 then
    target.remove_item( itemName )
I don't think the get_item_count check is needed since all entities inherit remove_item. If you want it for the debug message it could be written as

Code: Select all

if target.remove_item(itemName) > 0 then print("Removed item from entity")
This could replace most of your "inside" functions actually since selected and opened are both entities and would cover cars etc.

User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: [don't fix] some way to lock cursor stack

Post by aubergine18 »

Good call!

Code: Select all

local function isInside( target, itemName )
  return target and target.remove_item( itemName ) > 0
end
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: [don't fix] some way to lock cursor stack

Post by aubergine18 »

Code: Select all

if player.selected.type = "transport-belt" then
  player.selected.get_transport_line(1).remove_items(blah)  
  player.selected.get_transport_line(2).remove_items(blah)
end
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

Post Reply

Return to “Modding interface requests”