Refactored the mecha fabricator (#19264)

Refactored the mecha fabricator to use a queue system instead of
processing.
Typed a GLOB list for robolimbs.
Build time is now correct.
This commit is contained in:
Fluffy
2024-05-31 23:24:17 +02:00
committed by GitHub
parent 33fe9c55a1
commit 7fdfb4ce02
4 changed files with 183 additions and 66 deletions
+117 -64
View File
@@ -8,22 +8,6 @@
idle_power_usage = 20
active_power_usage = 5000
req_access = list(ACCESS_ROBOTICS)
var/speed = 1
var/mat_efficiency = 1
var/list/materials = list(DEFAULT_WALL_MATERIAL = 0, MATERIAL_GLASS = 0, MATERIAL_GOLD = 0, MATERIAL_SILVER = 0, MATERIAL_DIAMOND = 0, MATERIAL_PHORON = 0, MATERIAL_URANIUM = 0)
var/res_max_amount = 200000
var/datum/research/files
var/list/datum/design/queue = list()
var/progress = 0
var/busy = 0
var/list/categories = list()
var/category = null
var/sync_message = ""
var/limb_manufacturer
component_types = list(
/obj/item/circuitboard/mechfab,
/obj/item/stock_parts/matter_bin = 2,
@@ -32,6 +16,34 @@
/obj/item/stock_parts/console_screen
)
/**
* A `/list` of enqueued `/datum/design` to be printed, processed in the queue
*/
var/list/datum/design/queue = list()
/**
* How much efficient (or inefficient) the protolathe is at manufacturing things
*/
var/mat_efficiency = 1
/**
* The production speed of this specific protolathe, a factor
*/
var/production_speed = 1
var/list/materials = list(DEFAULT_WALL_MATERIAL = 0, MATERIAL_GLASS = 0, MATERIAL_GOLD = 0, MATERIAL_SILVER = 0, MATERIAL_DIAMOND = 0, MATERIAL_PHORON = 0, MATERIAL_URANIUM = 0)
var/res_max_amount = 200000
var/datum/research/files
var/list/categories = list()
var/category = null
var/sync_message = ""
var/limb_manufacturer
///The timer id for the build callback, if we're building something
var/build_callback_timer
/obj/machinery/mecha_part_fabricator/Initialize()
. = ..()
@@ -39,22 +51,10 @@
limb_manufacturer = GLOB.basic_robolimb.company
update_categories()
/obj/machinery/mecha_part_fabricator/process()
..()
if(stat)
return
if(busy)
update_use_power(POWER_USE_ACTIVE)
progress += speed
check_build()
else
update_use_power(POWER_USE_IDLE)
update_icon()
/obj/machinery/mecha_part_fabricator/update_icon()
ClearOverlays()
icon_state = "fab-base"
if(busy)
if(build_callback_timer)
AddOverlays("fab-active")
if(panel_open)
AddOverlays("fab-panel")
@@ -77,7 +77,7 @@
for(var/obj/item/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; speed is affected by both
T += M.rating
speed = T / 2 // 1 -> 3
production_speed = T / 2 // 1 -> 3
/obj/machinery/mecha_part_fabricator/attack_hand(var/mob/user)
if(..())
@@ -98,6 +98,7 @@
data["buildable"] = get_build_options()
data["category"] = category
data["categories"] = categories
if(GLOB.fabricator_robolimbs)
var/list/T = list()
for(var/A in GLOB.fabricator_robolimbs)
@@ -105,11 +106,18 @@
T += list(list("id" = A, "company" = R.company))
data["manufacturers"] = T
data["manufacturer"] = limb_manufacturer
data["materials"] = get_materials()
data["maxres"] = res_max_amount
data["sync"] = sync_message
//If we have something in the queue that we're trying to build, show the time left if the build is undergoing, otherwise null
//the logic of displaying it is handled client-side
if(current)
data["builtperc"] = round((progress / current.time) * 100)
if(build_callback_timer)
data["timeleft"] = round(timeleft(build_callback_timer))
else
data["timeleft"] = null
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
@@ -148,7 +156,7 @@
return 1
/obj/machinery/mecha_part_fabricator/attackby(obj/item/attacking_item, mob/user)
if(busy)
if(build_callback_timer)
to_chat(user, SPAN_NOTICE("\The [src] is busy. Please wait for completion of previous operation."))
return TRUE
if(default_deconstruction_screwdriver(user, attacking_item))
@@ -182,7 +190,7 @@
M.use(1)
count++
to_chat(user, SPAN_NOTICE("You insert [count] [sname] into \the [src]."))
update_busy()
else
to_chat(user, SPAN_NOTICE("\The [src] cannot hold more [sname]."))
return TRUE
@@ -250,27 +258,70 @@
if(1)
visible_message("[icon2html(src, viewers(get_turf(src)))] <b>[src]</b> beeps: \"No records in User DB\"")
/obj/machinery/mecha_part_fabricator/proc/update_busy()
if(queue.len)
if(can_build(queue[1]))
busy = 1
else
busy = 0
else
busy = 0
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(var/path)
/**
* Adds a design to the queue
*
* * path: The path of the design to add
*/
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(path)
var/datum/design/D = files.known_designs[path]
if(!D)
return
queue += D
update_busy()
/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(var/index)
if(index == 1)
progress = 0
//Wake up, we have things to do
handle_queue()
/**
* Removes a design from the queue
*
* * index: The index of the design to remove
*/
/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index)
queue.Cut(index, index + 1)
update_busy()
//If we're removing the first thing in the queue, stop the build timer
if(index == 1)
deltimer(build_callback_timer)
build_callback_timer = null
//Wake up, we have things to do
handle_queue()
/**
* Handle the construction queue
*/
/obj/machinery/mecha_part_fabricator/proc/handle_queue()
//No work to do or already busy, stop
if(!length(queue) || build_callback_timer)
//If we don't have a build in progress, revert to idle power usage
if(!build_callback_timer)
update_use_power(POWER_USE_IDLE)
update_icon()
return
//If there's no power, there's no building
if(stat & NOPOWER)
queue = list()
return
//Get the first design in the queue
var/datum/design/D = queue[1]
//If we can build it, process the request
if(can_build(D))
update_use_power(POWER_USE_ACTIVE)
//Add the callback timer for printing, and remove the design from the queue
build_callback_timer = addtimer(CALLBACK(src, PROC_REF(build), D), (D.time / production_speed), TIMER_UNIQUE|TIMER_STOPPABLE)
//No queue removal here because we show how long it takes to build in the UI
else
visible_message(SPAN_NOTICE("[icon2html(src, viewers(get_turf(src)))] \The [src] flashes: Insufficient materials to complete build: [D.name]."))
update_icon()
/obj/machinery/mecha_part_fabricator/proc/can_build(var/datum/design/D)
for(var/M in D.materials)
@@ -278,31 +329,34 @@
return 0
return 1
/obj/machinery/mecha_part_fabricator/proc/check_build()
if(!queue.len)
progress = 0
return
var/datum/design/D = queue[1]
if(!can_build(D))
progress = 0
return
if(D.time > progress)
return
for(var/M in D.materials)
materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency)
/**
* Builds the given design, assuming all the necessary conditions are met
*
* * design_to_build: The design to build
*/
/obj/machinery/mecha_part_fabricator/proc/build(datum/design/design_to_build)
//Consume the materials
for(var/M in design_to_build.materials)
materials[M] = max(0, materials[M] - design_to_build.materials[M] * mat_efficiency)
intent_message(MACHINE_SOUND)
if(D.build_path)
if(design_to_build.build_path)
var/loc_offset = get_step(src, dir)
var/obj/new_item = D.Fabricate(loc_offset, src)
var/obj/new_item = design_to_build.Fabricate(loc_offset, src)
visible_message("\The <b>[src]</b> pings, indicating that \the [new_item] is complete.", "You hear a ping.", intent_message = PING_SOUND)
if(mat_efficiency != 1)
if(new_item.matter && new_item.matter.len > 0)
for(var/i in new_item.matter)
new_item.matter[i] = new_item.matter[i] * mat_efficiency
//We finished building, clear the timer and remove the thing from the queue
build_callback_timer = null
remove_from_queue(1)
//Do the queue handling for the next item, or to stop
handle_queue()
/obj/machinery/mecha_part_fabricator/proc/get_queue_names()
. = list()
for(var/i = 2 to queue.len)
@@ -324,7 +378,7 @@
return english_list(F, and_text = ", ")
/obj/machinery/mecha_part_fabricator/proc/get_design_time(var/datum/design/D)
return time2text(round(10 * D.time / speed), "mm:ss")
return time2text(round(10 * D.time / production_speed), "mm:ss")
/obj/machinery/mecha_part_fabricator/proc/update_categories()
categories = list()
@@ -358,7 +412,6 @@
materials[material] -= ejected * S.perunit
if(recursive && materials[material] >= S.perunit)
eject_materials(material, -1)
update_busy()
/obj/machinery/mecha_part_fabricator/proc/sync()
sync_message = "Error: no console found."
+1 -1
View File
@@ -1,7 +1,7 @@
GLOBAL_LIST_EMPTY(all_robolimbs)
GLOBAL_LIST_EMPTY(internal_robolimbs)
GLOBAL_LIST_EMPTY(chargen_robolimbs)
GLOBAL_LIST_EMPTY(fabricator_robolimbs)
GLOBAL_LIST_EMPTY_TYPED(fabricator_robolimbs, /datum/robolimb)
GLOBAL_DATUM(basic_robolimb, /datum/robolimb)
/proc/populate_robolimb_list()
@@ -0,0 +1,60 @@
################################
# Example Changelog File
#
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
#
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
# When it is, any changes listed below will disappear.
#
# Valid Prefixes:
# bugfix
# - (fixes bugs)
# wip
# - (work in progress)
# qol
# - (quality of life)
# soundadd
# - (adds a sound)
# sounddel
# - (removes a sound)
# rscadd
# - (adds a feature)
# rscdel
# - (removes a feature)
# imageadd
# - (adds an image or sprite)
# imagedel
# - (removes an image or sprite)
# spellcheck
# - (fixes spelling or grammar)
# experiment
# - (experimental change)
# balance
# - (balance changes)
# code_imp
# - (misc internal code change)
# refactor
# - (refactors code)
# config
# - (makes a change to the config files)
# admin
# - (makes changes to administrator tools)
# server
# - (miscellaneous changes to server)
#################################
# Your name.
author: FluffyGhost
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
changes:
- refactor: "Refactored the mecha fabricator to use a queue system instead of processing."
- refactor: "Typed a GLOB list for robolimbs."
- bugfix: "Build time is now correct."
+5 -1
View File
@@ -41,7 +41,11 @@
{{if data.current}}
<div class="item">
<div class="itemLabelWide">
<b>Now: {{:data.current}}</b> ({{:data.builtperc}}% ready)
{{if data.timeleft}}
<b>Time left: {{:data.current}}</b> ({{:data.timeleft / 10}} seconds)
{{else}}
<b>{{:data.current}} (Awaiting to start)</b>
{{/if}}
</div>
<div class="itemContentMedium">
{{:helper.link('Cancel', null, {'remove' : 1})}}