Paste #108305: Vanilla Breaking Time Proc

Date: 2023/04/02 15:08:57 UTC-07:00
Type: Denizen Script

View Raw Paste Download This Paste
Copy Link


breaking_time:
    type: procedure
    debug: false
    definitions: args
    script:
        - define args <[args].as[map].if_null[<[args]>]> if:<[args].object_type.equals[element].is_truthy>
        - define null <util.random_decimal>
        # ~~~ ARGS ~~~ #
        - define hardness <[args.hardness].if_null[]>
        - define item     <[args.item].if_null[]>
        - define hand     <[args.is_hand_valid].if_null[]>
        - define tools    <[args.valid_tools].if_null[]>
        # ~~~ DEFAULTS ~~~ #
        - define hardness <[args].if_null[<[null]>]> if:<[hardness].equals[]>
        - define item     <item[air]>                if:<[item].equals[]>
        - define hand     false                      if:<[hand].equals[]>
        - define tools    <list>                     if:<[tools].equals[]>
        # ~~~ ERROR CHECKING ~~~ #
        - define error <proc[error_missing_check].context[hardness|<[null]>|<[hardness]>|<queue>]>
        - define error <proc[error_type_check].context[item|item|<[item]>|<queue>]>            if:<[error].not>
        - define error <proc[error_type_check].context[is_hand_vaid|element|<[hand]>|<queue>]> if:<[error].not>
        - define error <proc[error_type_check].context[valid_tools|list|<[tools]>|<queue>]>    if:<[error].not>
        - foreach <[tools]>:
            - define error <proc[error_type_check].context[valid_tools[<[loop_index]>]|item,element|<[value]>|<queue>]> if:<[error].not>
        - define error <proc[error_boolean_check].context[is_hand_vaid|<[hand]>|<queue>]> if:<[error].not>
        - determine <empty> if:<[error]>
        # ~~~ LOGIC ~~~ #
        - determine <util.int_max> if:<[hardness].equals[<util.int_max>]>
        - determine 0              if:<[hardness].equals[-1]>
        - determine 0.30           if:<[hardness].equals[0]>
        - foreach <[tools]>:
            - if <[item]> matches <[key]>:
                - define speed <[value]>
                - define harvestable true
                - foreach stop
        - define speed          <empty> if:<[speed].if_null[true]>
        - define in_air         <player.location.material.is_solid.not>
        - define in_water       <player.eye_location.material.advanced_matches[*water]>
        - define aqua_affinity  <player.equipment_map.filter_tag[<[filter_value].enchantment_map.get[aqua_affinity].exists>].any>
        - define haste          <player.effects_data.filter_tag[<[filter_value.type].equals[fast_digging]>].first.if_null[]>
        - define fatigue        <player.effects_data.filter_tag[<[filter_value.type].equals[slow_digging]>].first.if_null[]>
        - define efficiency     <[item].enchantment_map.get[efficiency].if_null[]>
        - define harvestable false
        - define haste       0    if:<[haste].equals[]>
        - define fatigue     0    if:<[fatigue].equals[]>
        - define efficiency  0    if:<[efficiency].equals[]>
        - define speed       1    if:<[speed].equals[]>
        - define harvestable true if:<[hand].is_truthy>
        - define speed:+:<[efficiency].mul[<[efficiency]>].add[1]> if:<[harvestable].and[<[efficiency].is_more_than[0]>]>
        - define speed:*:<[haste].mul[0.2].add[1]>                 if:<player.has_effect[fast_digging]>
        - define speed:*:<element[0.3].power[<[fatigue].min[4]>]>  if:<player.has_effect[slow_digging]>
        - if <[in_air]> and not <[aqua_affinity]>:
            - define speed:/:5
        - else if <[in_air]>:
            - define speed:/:5
        - define damage <[speed].div[<[hardness]>]>
        - if <[harvestable]>:
            - define damage:*:0.03333333
        - else:
            - define damage:*:0.01
        # If the tool and enchantments immediately exceed the hardness times 30, the block breaks with no delay
        - determine 0   if:<[damage].is_more_than[<[hardness].mul[30]>]>
        - determine 0.3 if:<[damage].is_more_than[1]>
        - determine <element[1].div[<[damage]>].round_up.div[20]>
    data:
        args:
            hardness:
                type: elementTag
                description: A number between -1 and <util.int_max>. <util.int_max> is treated as an infinite break time, and will return <util.int_max> seconds. A hardness of zero returns a break time of zero, which is a delayed infinite break time (similiar to breaking blocks in creative while just holding down left click). A hardness of -1 is treated as a no delay break time, similar to mining stone with an Efficency 5 diamond pickaxe and Haste 3. Everything else uses the vanilla breaking formula which can be found <&click[https://minecraft.fandom.com/wiki/Breaking#:~:text=Combining<&pc>20all<&pc>20of<&pc>20the<&pc>20information<&pc>20above].on_click[open_url]>here<&end_click>.
                required: true
            valid_tools:
                type: mapTag<&lt>itemTag|elementTag=elementTag<&gt>
                description: A map of items/item names, with the speed at which the item can break the block at. For example, you may want an iron sword to be twice as effective as a wooden sword, so you'd create a map that looked something like <&lt>map[iron_sword=10;wooden_sword=5]<&gt>. You can also input item script names, or use a matcher, such as *sword. These values are used in the process of finding the breaking speed, and are not directly translatable to amount of time. The vanilla values of tool materials can be found <&click[https://minecraft.fandom.com/wiki/Breaking#:~:text=Tool<&pc>20Speed].on_click[open_url]>here<&end_click>.
                required: false
            is_hand_valid:
                type: elementTag
                description: Whether a hand is a valid "tool" to break with. If this is true, it effectively overwrites valid_tools, since every tool is valid if a hand is valid. If not specified, defaults to false.
                required: false
            item:
                type: itemTag
                description: The item you're using to break with. If no item is provided, the equation is run assuming a hand. An air item is also treated as attempting to break with a hand.
                required: false
        description: Takes an item, and a hardness value, and calculates the amount of seconds it would take to be mined. Attempts to follow vanilla Minecraft breaking logic, based on the information from the <&click[https://minecraft.fandom.com/wiki/Breaking].on_click[open_url]>Breaking<&end_click> page on the Minecraft wiki.
        determines: elementTag
        usage:
            - define tools:->:<player.item_in_hand>
            - define hardness <player.eye_location.ray_trace[return=block].material.hardness>
            - narrate "It will take <proc[breaking_time].context[valid_tools=<[tools]>;item=<[tools].first>;hardness=<[hardness]>]> seconds to break the block I'm looking at with the tool in my hand."

#========================================#

error_type_check:
    type: procedure
    debug: false
    definitions: name|types|object|queue
    script:
        - define types  <[types].split[,]> if:<[types].object_type.equals[element]>
        - define actual <[object].object_type>
        - if <[actual].to_lowercase> not in <[types]>:
            - define formatted <&sq><[types].first><&sq>
            - foreach <[types].get[2].to[-2]> if:<[types].size.is_more_than[2]>:
                - define formatted "<[formatted]>, '<[value]>'"
            - define formatted "<[formatted]> or '<[types].last>'" if:<[types].size.is_more_than[1]>
            - debug error "<[queue].script.name.to_uppercase>: Argument '<[name]>' is supposed to be of <[formatted]>, but was instead of type '<[actual]>'."
            - determine true
        - determine false

error_missing_check:
    type: procedure
    debug: false
    definitions: name|null|object|queue
    script:
        - if <[object]> == <[null]>:
            - debug error "<[queue].script.name.to_uppercase>: Missing argument '<[name]>'."
            - determine true
        - determine false

error_boolean_check:
    type: procedure
    debug: false
    definitions: name|object|queue
    script:
        - if not <[object].is_boolean>:
            - debug error "<[queue].script.name.to_uppercase>: Argument '<[name]>' is not a boolean value."
            - determine true
        - determine false