diff --git a/src/smithed_libraries/packs/interaction/README.md b/src/smithed_libraries/packs/interaction/README.md
new file mode 100644
index 0000000..248513c
--- /dev/null
+++ b/src/smithed_libraries/packs/interaction/README.md
@@ -0,0 +1,22 @@
+
+
+
+
+# Interaction
+
+This library serves to enable easier usage of interaction entities as well as enabling custom addons to this usage.
+
+## Usage
+[Documentation](https://docs.smithed.dev/libraries/interaction/)
+## Downloading
+You can download it from [here](https://smithed.net/packs/interaction)
+or
+You can build it from source using [beet](https://github.com/mcbeet/beet)
+
+### Building
+```
+$ pip install beet mecha
+$ git clone https://github.com/Smithed-MC/Libraries
+$ cd Libraries/interaction
+$ beet -s 'meta.libraries = ["interaction"]'
+```
diff --git a/src/smithed_libraries/packs/interaction/beet.yaml b/src/smithed_libraries/packs/interaction/beet.yaml
new file mode 100644
index 0000000..c1119eb
--- /dev/null
+++ b/src/smithed_libraries/packs/interaction/beet.yaml
@@ -0,0 +1,21 @@
+extend: "@smithed_libraries/common.yaml"
+
+id: smithed.interaction
+name: Smithed Interaction
+version: "1.0.0"
+description: Interaction Library for Smithed
+author: runcows
+
+data_pack:
+ name: Smithed Interaction
+ load:
+ data/smithed.interaction/modules: modules
+
+require:
+ - bolt
+
+meta:
+ bolt:
+ entrypoint: ["*"]
+ mecha:
+ formatting: minify
diff --git a/src/smithed_libraries/packs/interaction/modules/core.bolt b/src/smithed_libraries/packs/interaction/modules/core.bolt
new file mode 100644
index 0000000..e2bba8c
--- /dev/null
+++ b/src/smithed_libraries/packs/interaction/modules/core.bolt
@@ -0,0 +1,80 @@
+# ---------------------------------------------------- #
+# -------------------- --------------------- #
+# --------------- CORE --------------- #
+# -------------------- --------------------- #
+# ---------------------------------------------------- #
+function smithed.interaction:impl/technical/load:
+ raw # core
+ scoreboard objectives add smithed.interaction.temp dummy
+
+for action in [
+ {"type": "interaction", "trigger": "minecraft:player_interacted_with_entity", "data_location": "on_right_click", "on": "target"},
+ {"type": "attack", "trigger": "minecraft:player_hurt_entity", "data_location": "on_left_click", "on": "attacker"}
+]:
+ ADV_LOC = "smithed.interaction:impl/" + action['type']
+ DATA_LOC = "data.smithed_interaction." + action['data_location']
+ CMD_LOC = DATA_LOC + ".command"
+ FUNC_LOC = DATA_LOC + ".function"
+ SHORTCUT_LOC = DATA_LOC + ".custom"
+ TIMESTAMP = action['type'] + ".timestamp"
+
+ advancement ADV_LOC:
+ criteria:
+ requirement:
+ trigger: action['trigger']
+ conditions:
+ entity:
+ type: "minecraft:entity_properties"
+ entity: "this"
+ predicate:
+ "minecraft:entity_type": "minecraft:interaction"
+ "minecraft:entity_tags":
+ all_of:
+ - "smithed.interaction"
+ rewards:
+ function: ADV_LOC
+
+ def try_action(type: str, command_to_try: str, nbt_location: str, fail_text: str):
+ scoreboard players set #success smithed.interaction.temp 0
+ with entity @s DATA_LOC:
+ scoreboard players set #success smithed.interaction.temp 1
+ raw command_to_try
+ if score #success smithed.interaction.temp matches 0 tellraw @p[tag=smithed.interaction.player] [
+ {text:"", color:"red"}, f"Interaction's {type} failed: ",
+ {text:"\"",color:"aqua"}, {entity:"@s",nbt: nbt_location, interpret:true, color:"green"},
+ {text:"\"",color:"aqua"}, (" " + fail_text)
+ ]
+
+ function ADV_LOC:
+ advancement revoke @s only ADV_LOC
+ store result score #current_gametime smithed.interaction.temp run time query gametime
+ tag @s add smithed.interaction.player
+ # CONSIDER LATER: Do we want to macro in the players entity interaction range?
+ # | This is probably not worth, but it does make this feel incomplete
+ as @e[tag=smithed.interaction, type=interaction, distance=..16] if data entity @s action['type'] function ~/process:
+ store result score #check_gametime smithed.interaction.temp run data get entity @s TIMESTAMP
+ unless score #check_gametime smithed.interaction.temp = #current_gametime smithed.interaction.temp run return run data remove entity @s action['type']
+ raw f"execute on {action['on']} unless entity @s[tag=smithed.interaction.player] run return fail"
+ if data entity @s SHORTCUT_LOC at @s function ~/try_shortcut:
+ try_action(
+ "custom shortcut",
+ "$function #smithed.interaction:event/on_right_click/custom/$(custom)",
+ SHORTCUT_LOC,
+ "is not a valid shortcut. Cannot contain characters not valid in a function path!"
+ )
+ if data entity @s FUNC_LOC at @s function ~/try_function:
+ try_action(
+ "function",
+ "$function $(function)",
+ FUNC_LOC,
+ "is not a valid function location!"
+ )
+ if data entity @s CMD_LOC at @s function ~/try_command:
+ try_action(
+ "command",
+ "$$(command)",
+ CMD_LOC,
+ "is not a valid command!"
+ )
+ data remove entity @s action['type']
+ tag @s remove smithed.interaction.player
diff --git a/src/smithed_libraries/packs/interaction/modules/sit.bolt b/src/smithed_libraries/packs/interaction/modules/sit.bolt
new file mode 100644
index 0000000..92bf20c
--- /dev/null
+++ b/src/smithed_libraries/packs/interaction/modules/sit.bolt
@@ -0,0 +1,80 @@
+# --------------------------------------------------- #
+# -------------------- -------------------- #
+# --------------- SIT --------------- #
+# -------------------- -------------------- #
+# --------------------------------------------------- #
+function smithed.interaction:impl/custom/sit:
+ # Functions
+ AT_HEIGHT = ~/at_height
+ SEC = ~/sec
+ TICK = ~/tick
+
+ # Predicates
+ HAS_TEMP_ID = ~/has_temp_id
+ HAS_PASSENGER = ~/has_passenger
+
+ predicate HAS_PASSENGER {
+ "type":"minecraft:entity_properties",
+ "entity":"this",
+ "predicate":{
+ "minecraft:passenger":{}
+ }
+ }
+ predicate HAS_TEMP_ID {
+ "type": "minecraft:int_value_check",
+ "value": {
+ "type": "minecraft:score",
+ "target": {"type": "minecraft:fixed","name": "#temp"},
+ "score": "smithed.interaction.sittable_id"
+ },
+ "test": {
+ "type": "minecraft:score",
+ "target": "this",
+ "score": "smithed.interaction.sittable_id"
+ }
+ }
+
+ append function_tag smithed.interaction:event/on_right_click/custom/sit {"values":[(~/)]}
+ # Follow
+ if data entity @s data.smithed_interaction.on_right_click{height:"follow"} return:
+ tag @s add smithed.interaction.sittable_interaction.follow
+ unless score @s smithed.interaction.sittable_id matches -2147483648..2147483647 store result score @s smithed.interaction.sittable_id run scoreboard players add #next smithed.interaction.sittable_id 1
+ store result score #temp smithed.interaction.sittable_id run scoreboard players get @s smithed.interaction.sittable_id
+ unless entity @e[tag=smithed.interaction.sittable_display.follow,type=item_display,distance=..0.001,predicate=(HAS_TEMP_ID)] summon item_display:
+ scoreboard players operation @s smithed.interaction.sittable_id = #temp smithed.interaction.sittable_id
+ tag @s add smithed.interaction.sittable_display
+ tag @s add smithed.interaction.sittable_display.follow
+ ride @p[tag=smithed.interaction.player] dismount
+ ride @p[tag=smithed.interaction.player] mount @s
+
+ # Normal
+ store result storage smithed.interaction:temp sitting.height double 0.5 run data get entity @s height
+ data modify storage smithed.interaction:temp sitting.height set from entity @s data.smithed_interaction.on_right_click.height
+
+ with storage smithed.interaction:temp sitting:
+ raw f"$execute positioned ~ ~$(height) ~ run function {AT_HEIGHT}"
+ function AT_HEIGHT:
+ kill @e[tag=smithed.interaction.sittable_display,distance=..0.01,type=item_display,predicate=!(HAS_PASSENGER)]
+ unless entity @e[tag=smithed.interaction.sittable_display,distance=..0.01,type=item_display] summon item_display:
+ tag @s add smithed.interaction.sittable_display
+ ride @p[tag=smithed.interaction.player] dismount
+ ride @p[tag=smithed.interaction.player] mount @s
+
+ ## Helpers :D
+ append function smithed.interaction:impl/technical/load:
+ raw # custom : sit
+ scoreboard objectives add smithed.interaction.sittable_id dummy
+ scoreboard players add #next smithed.interaction.sittable_id 0
+ schedule function SEC 1t
+ schedule function TICK 1t
+
+ function SEC:
+ schedule function ~/ 20t
+ kill @e[tag=smithed.interaction.sittable_display,type=item_display,predicate=!(HAS_PASSENGER)]
+
+ function TICK:
+ schedule function ~/ 1t
+ as @e[tag=smithed.interaction.sittable_display.follow,type=item_display] at @s:
+ store result score #temp smithed.interaction.sittable_id run scoreboard players get @s smithed.interaction.sittable_id
+ unless entity @e[tag=smithed.interaction.sittable_interaction.follow,type=interaction,distance=..0.001,predicate=(HAS_TEMP_ID)]:
+ tp @s @n[tag=smithed.interaction.sittable_interaction.follow,type=interaction,predicate=(HAS_TEMP_ID)]
diff --git a/src/smithed_libraries/packs/interaction/pack.png b/src/smithed_libraries/packs/interaction/pack.png
new file mode 100644
index 0000000..02154cf
Binary files /dev/null and b/src/smithed_libraries/packs/interaction/pack.png differ