From 06ea9d6ac2104f347c83f51b0c909adcb610473c Mon Sep 17 00:00:00 2001 From: Lohikar Date: Sat, 2 Sep 2017 16:47:01 -0500 Subject: [PATCH] Mining performance fixes (#3387) changes: Mining ore bags are no longer painfully slow. The ore summoner now sleeps instead of just giving up on TICK_CHECK. --- code/game/objects/items.dm | 3 +- .../objects/items/weapons/storage/bags.dm | 196 +++++++++--------- .../objects/items/weapons/storage/storage.dm | 93 +++++++-- code/modules/mining/mine_items.dm | 3 +- code/modules/mining/satchel_ore_boxdm.dm | 6 +- html/changelogs/lohikar-bagperf.yml | 5 + 6 files changed, 188 insertions(+), 118 deletions(-) create mode 100644 html/changelogs/lohikar-bagperf.yml diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 0235c428763..8ec95866b37 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -211,9 +211,10 @@ continue success = TRUE - S.handle_item_insertion(I, 1) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed. + S.handle_item_insertion_deferred(I, user) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed. CHECK_TICK // Because people insist on picking up huge-ass piles of stuff. + S.handle_storage_deferred(user) if(success && !failure) user << "You put everything in [S]." else if(success) diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index bce0d2c663e..a5b35a55693 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -22,6 +22,7 @@ display_contents_with_number = 0 // UNStABLE AS FuCK, turn on when it stops crashing clients use_to_pickup = 1 slot_flags = SLOT_BELT + var/use_deferred = TRUE // ----------------------------- // Trash bag @@ -58,7 +59,13 @@ bagfull = 1 break count++ - handle_item_insertion(L, 1)//value of 1 suppresses confirmation messages from this one + if (use_deferred) + handle_item_insertion_deferred(L, user) + else + handle_item_insertion(L, TRUE) + + if (use_deferred) + handle_storage_deferred(user) if (count) user << "You empty [count] broken bulbs into the trashbag." @@ -135,122 +142,119 @@ storage_slots = 7 allow_quick_empty = 1 // this function is superceded - New() - ..() - //verbs -= /obj/item/weapon/storage/verb/quick_empty - //verbs += /obj/item/weapon/storage/bag/sheetsnatcher/quick_empty + use_deferred = FALSE - can_be_inserted(obj/item/W as obj, stop_messages = 0) - if(!istype(W,/obj/item/stack/material)) - if(!stop_messages) - usr << "The snatcher does not accept [W]." - return 0 - var/current = 0 - for(var/obj/item/stack/material/S in contents) - current += S.amount - if(capacity == current)//If it's full, you're done - if(!stop_messages) - usr << "The snatcher is full." - return 0 - return 1 +/obj/item/weapon/storage/bag/sheetsnatcher/can_be_inserted(obj/item/W as obj, stop_messages = 0) + if(!istype(W,/obj/item/stack/material)) + if(!stop_messages) + usr << "The snatcher does not accept [W]." + return 0 + var/current = 0 + for(var/obj/item/stack/material/S in contents) + current += S.amount + if(capacity == current)//If it's full, you're done + if(!stop_messages) + usr << "The snatcher is full." + return 0 + return 1 // Modified handle_item_insertion. Would prefer not to, but... - handle_item_insertion(obj/item/W as obj, prevent_warning = 0) - var/obj/item/stack/material/S = W - if(!istype(S)) return 0 +/obj/item/weapon/storage/bag/sheetsnatcher/handle_item_insertion(obj/item/W as obj, prevent_warning = 0) + var/obj/item/stack/material/S = W + if(!istype(S)) return 0 - var/amount - var/inserted = 0 - var/current = 0 - for(var/obj/item/stack/material/S2 in contents) - current += S2.amount - if(capacity < current + S.amount)//If the stack will fill it up - amount = capacity - current + var/amount + var/inserted = 0 + var/current = 0 + for(var/obj/item/stack/material/S2 in contents) + current += S2.amount + if(capacity < current + S.amount)//If the stack will fill it up + amount = capacity - current + else + amount = S.amount + + for(var/obj/item/stack/material/sheet in contents) + if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects + sheet.amount += amount // they should only be removed through procs in this file, which split them up. + S.amount -= amount + inserted = 1 + break + + if(!inserted || !S.amount) + usr.remove_from_mob(S) + usr.update_icons() //update our overlays + if (usr.client && usr.s_active != src) + usr.client.screen -= S + S.dropped(usr) + if(!S.amount) + qdel(S) else - amount = S.amount + S.loc = src - for(var/obj/item/stack/material/sheet in contents) - if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects - sheet.amount += amount // they should only be removed through procs in this file, which split them up. - S.amount -= amount - inserted = 1 - break - - if(!inserted || !S.amount) - usr.remove_from_mob(S) - usr.update_icons() //update our overlays - if (usr.client && usr.s_active != src) - usr.client.screen -= S - S.dropped(usr) - if(!S.amount) - qdel(S) - else - S.loc = src - - orient2hud(usr) - if(usr.s_active) - usr.s_active.show_to(usr) - update_icon() - return 1 + orient2hud(usr) + if(usr.s_active) + usr.s_active.show_to(usr) + update_icon() + return 1 // Sets up numbered display to show the stack size of each stored mineral // NOTE: numbered display is turned off currently because it's broken - orient2hud(mob/user as mob) - var/adjusted_contents = contents.len +/obj/item/weapon/storage/bag/sheetsnatcher/orient2hud(mob/user as mob) + var/adjusted_contents = contents.len - //Numbered contents display - var/list/datum/numbered_display/numbered_contents - if(display_contents_with_number) - numbered_contents = list() - adjusted_contents = 0 - for(var/obj/item/stack/material/I in contents) - adjusted_contents++ - var/datum/numbered_display/D = new/datum/numbered_display(I) - D.number = I.amount - numbered_contents.Add( D ) + //Numbered contents display + var/list/datum/numbered_display/numbered_contents + if(display_contents_with_number) + numbered_contents = list() + adjusted_contents = 0 + for(var/obj/item/stack/material/I in contents) + adjusted_contents++ + var/datum/numbered_display/D = new/datum/numbered_display(I) + D.number = I.amount + numbered_contents.Add( D ) - var/row_num = 0 - var/col_count = min(7,storage_slots) -1 - if (adjusted_contents > 7) - row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width. - src.slot_orient_objs(row_num, col_count, numbered_contents) - return + var/row_num = 0 + var/col_count = min(7,storage_slots) -1 + if (adjusted_contents > 7) + row_num = round((adjusted_contents-1) / 7) // 7 is the maximum allowed width. + src.slot_orient_objs(row_num, col_count, numbered_contents) + return // Modified quick_empty verb drops appropriate sized stacks - quick_empty() - var/location = get_turf(src) - for(var/obj/item/stack/material/S in contents) - while(S.amount) - var/obj/item/stack/material/N = new S.type(location) - var/stacksize = min(S.amount,N.max_amount) - N.amount = stacksize - S.amount -= stacksize - if(!S.amount) - qdel(S) // todo: there's probably something missing here - orient2hud(usr) - if(usr.s_active) - usr.s_active.show_to(usr) - update_icon() +/obj/item/weapon/storage/bag/sheetsnatcher/quick_empty() + var/location = get_turf(src) + for(var/obj/item/stack/material/S in contents) + while(S.amount) + var/obj/item/stack/material/N = new S.type(location) + var/stacksize = min(S.amount,N.max_amount) + N.amount = stacksize + S.amount -= stacksize + if(!S.amount) + qdel(S) // todo: there's probably something missing here + orient2hud(usr) + if(usr.s_active) + usr.s_active.show_to(usr) + update_icon() // Instead of removing - remove_from_storage(obj/item/W as obj, atom/new_location) - var/obj/item/stack/material/S = W - if(!istype(S)) return 0 +/obj/item/weapon/storage/bag/sheetsnatcher/remove_from_storage(obj/item/W as obj, atom/new_location) + var/obj/item/stack/material/S = W + if(!istype(S)) return 0 - //I would prefer to drop a new stack, but the item/attack_hand code - // that calls this can't recieve a different object than you clicked on. - //Therefore, make a new stack internally that has the remainder. - // -Sayu + //I would prefer to drop a new stack, but the item/attack_hand code + // that calls this can't recieve a different object than you clicked on. + //Therefore, make a new stack internally that has the remainder. + // -Sayu - if(S.amount > S.max_amount) - var/obj/item/stack/material/temp = new S.type(src) - temp.amount = S.amount - S.max_amount - S.amount = S.max_amount + if(S.amount > S.max_amount) + var/obj/item/stack/material/temp = new S.type(src) + temp.amount = S.amount - S.max_amount + S.amount = S.max_amount - return ..(S,new_location) + return ..(S,new_location) // ----------------------------- // Sheet Snatcher (Cyborg) diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 0e3d4dceb2f..032bff6932c 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -360,34 +360,52 @@ //This proc handles items being inserted. It does not perform any checks of whether an item can or can't be inserted. That's done by can_be_inserted() //The stop_warning parameter will stop the insertion message from being displayed. It is intended for cases where you are inserting multiple items at once, //such as when picking up all the items on a tile with one click. -/obj/item/weapon/storage/proc/handle_item_insertion(obj/item/W as obj, prevent_warning = 0) +/obj/item/weapon/storage/proc/handle_item_insertion(obj/item/W as obj, prevent_warning = 0, mob/user = usr) if(!istype(W)) return 0 - if(usr) - usr.prepare_for_slotmove(W) - usr.update_icons() //update our overlays + if(user) + user.prepare_for_slotmove(W) W.forceMove(src) W.on_enter_storage(src) - if(usr) - if (usr.client && usr.s_active != src) - usr.client.screen -= W - W.dropped(usr) - add_fingerprint(usr) + if(user) + W.dropped(user) + add_fingerprint(user) if(!prevent_warning) - for(var/mob/M in viewers(usr, null)) + for(var/mob/M in viewers(user, null)) if (M == usr) usr << "You put \the [W] into [src]." else if (M in range(1)) //If someone is standing close enough, they can tell what it is... - M.show_message("\The [usr] puts [W] into [src].") + M.show_message("\The [user] puts [W] into [src].") else if (W && W.w_class >= 3) //Otherwise they can only see large or normal items from a distance... - M.show_message("\The [usr] puts [W] into [src].") + M.show_message("\The [user] puts [W] into [src].") - src.orient2hud(usr) - if(usr.s_active) - usr.s_active.show_to(usr) - update_icon() + orient2hud(user) + if(user.s_active) + user.s_active.show_to(user) + queue_icon_update() return 1 +// This is for inserting more than one thing at a time, you should call handle_storage_deferred after all the items have been inserted. +/obj/item/weapon/storage/proc/handle_item_insertion_deferred(obj/item/W, mob/user) + if (!istype(W)) + return FALSE + + if (user) + user.prepare_for_slotmove(W) + + W.forceMove(src) + W.on_enter_storage(src) + if (user) + W.dropped(user) + +/obj/item/weapon/storage/proc/handle_storage_deferred(mob/user) + add_fingerprint(user) + user.update_icons() + orient2hud(user) + if (user.s_active) + user.s_active.show_to(user) + queue_icon_update() + //Call this proc to handle the removal of an item from the storage item. The item will be moved to the atom sent as new_target /obj/item/weapon/storage/proc/remove_from_storage(obj/item/W as obj, atom/new_location) if(!istype(W)) return 0 @@ -422,6 +440,45 @@ update_icon() return 1 +/obj/item/weapon/storage/proc/remove_from_storage_deferred(obj/item/W, atom/new_location, mob/user) + if (!istype(W)) + return FALSE + + // fuck if I know. + for(var/mob/M in range(1, src.loc)) + if (M.s_active == src) + if (M.client) + M.client.screen -= W + + if (new_location) + if (ismob(loc)) + W.dropped(user) + if (ismob(new_location)) + W.layer = 20 + else + W.layer = initial(W.layer) + + W.forceMove(new_location) + else + W.forceMove(get_turf(src)) + + if (W.maptext) + W.maptext = "" + + W.on_exit_storage(src) + + return TRUE + +/obj/item/weapon/storage/proc/post_remove_from_storage_deferred(atom/oldloc, mob/user) + orient2hud(user) + if (user.s_active) + user.s_active.show_to(user) + + // who knows what the fuck this does + if (istype(src, /obj/item/weapon/storage/fancy)) + update_icon(1) + else + update_icon() //This proc is called when you want to place an item into the storage item. //Its a safe proc for adding things to the storage that does the necessary checks. Object will not be moved if it fails @@ -513,10 +570,12 @@ var/turf/T = get_turf(src) hide_from(usr) for(var/obj/item/I in contents) - remove_from_storage(I, T) + remove_from_storage_deferred(I, T, usr) CHECK_TICK + post_remove_from_storage_deferred(loc, usr) + // Override this to fill the storage object with stuff. /obj/item/weapon/storage/proc/fill() return diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 30d3adf7127..2ccf6266c01 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -1131,8 +1131,7 @@ var/list/total_extraction_beacons = list() single_spark(O.loc) do_teleport(O, user, 0) - if (TICK_CHECK) - return + CHECK_TICK /******************************Sculpting*******************************/ /obj/item/weapon/autochisel diff --git a/code/modules/mining/satchel_ore_boxdm.dm b/code/modules/mining/satchel_ore_boxdm.dm index 0c0aebe2db9..f0dd6e5d770 100644 --- a/code/modules/mining/satchel_ore_boxdm.dm +++ b/code/modules/mining/satchel_ore_boxdm.dm @@ -16,12 +16,14 @@ src.contents += W if (istype(W, /obj/item/weapon/storage)) var/obj/item/weapon/storage/S = W - S.hide_from(usr) + S.hide_from(user) for(var/obj/item/weapon/ore/O in S.contents) - S.remove_from_storage(O, src) //This will move the item to this item's contents + S.remove_from_storage_deferred(O, src, user) //This will move the item to this item's contents CHECK_TICK + S.post_remove_from_storage_deferred(loc, user) + user << span("notice", "You empty the satchel into the box.") update_ore_count() diff --git a/html/changelogs/lohikar-bagperf.yml b/html/changelogs/lohikar-bagperf.yml new file mode 100644 index 00000000000..ef9ad377510 --- /dev/null +++ b/html/changelogs/lohikar-bagperf.yml @@ -0,0 +1,5 @@ +author: Lohikar +delete-after: True +changes: + - experiment: "Storage code has been tweaked so ore bags should no longer take multiple seconds to fill/empty." + - tweak: "The ore summoner should actually transport useful amounts of ore now."