No settings button in Options
If Mod Menu is installed, the separate Options entry is intentionally hidden. Open the mod’s Configure screen from Mod Menu, or assign the optional settings keybind.
Make held items react to the way you play. Learn the mod, configure its effects, and build your own first-person interactions with Vyn.
Start with installation, try the bundled interactions, then tune the mod and pack settings.
Install InteractiveStuffBuild a resource pack, transform a held model, and add particles, physics and player-facing options.
Create your first packInteractiveStuff adds visual and sound interactions to held items. Its rendering hooks let resource packs replace or split models, move their parts, apply biome colors, simulate spring motion and draw first-person particles. The bundled InteractiveStuff resource pack supplies the ready-to-use effects.
The mod provides the engine and global controls. A resource pack provides scripts, models, textures and its own options. This distinction matters: disabling a pack effect does not disable the engine for other packs.
This offline guide covers the InteractiveStuff 0.8.0 feature set. Keyframe animation files and controls are documented separately in the 0.9.0 guide. Use the contents or search for an item, option or function. Expandable source listings and copy buttons work without a server.
mods folder.Install the mod on the client. Its held-item effects do not require a server installation and do not add server-side gameplay or physical world entities.
With Mod Menu installed, use Mods → InteractiveStuff → Configure. Without Mod Menu, use the InteractiveStuff button in Minecraft’s Options screen. A configurable settings keybind is also available under Controls; it starts unbound.
These are the minimum versions declared by this project’s current profiles, rather than a claim about the newest available releases. Use Fabric API and Mod Menu builds for the same Minecraft version. Optional Mod Menu builds may impose a higher Loader minimum of their own.
The render callback’s itemRendered is the actual current render model. Apply rendering changes to it there. The objects returned by player.getMainHandItem() and related getters are useful for inspecting stacks; changing one outside a rendering callback is not a persistent replacement for the active renderer.
| Name | Type / purpose |
|---|---|
player | Local Player wrapper |
world | Current World wrapper |
config | InteractiveStuffConfig read-only access |
key | Key translation helper |
modLoader | Installed mod, pack and game-version queries |
particles | Session-wide particle counts and clearing |
| Function | Behavior |
|---|---|
importScript(packId, script) | Execute an importable library in this script’s environment. The script name omits .vyn. |
excludeScript(packId, script) | Exclude the specified script from active callback dispatch. |
debugText(text) | Queue diagnostic text when the calling pack’s debug mode is enabled. |
debugText(text, visible) | Use an explicit boolean visibility flag, useful for a pack-owned counter switch. |
translateText(key, ...arguments) | Resolve a Minecraft language key to a displayed string, with optional format arguments. |
getDelta() | Frame duration normalized to 60 FPS: approximately 1 at 60 FPS. Paused frames use 0; the clock caps elapsed time at 50 ms (delta 3). It is not seconds or game ticks. |
getFrameId() | Monotonic frame identifier for preventing duplicate work in one render frame. |
wait ticks do … end | Schedule a block after a tick delay; this does not block the rest of the script. A nominal second is 20 ticks. |
task onSwingHand do
check !player.isHoldingItem("minecraft:stick") do reply nothing end
player.playSound("minecraft:ui.button.click", 0.4, 1.0)
wait 10 do
player.playSound("minecraft:ui.button.click", 0.4, 1.4)
end
endTop-level declarations run when a script loads; state persists between callbacks until reload/session reset. Scheduled work, model queues and particles are cleared when the session changes or scripts reload. A runtime error marks that script failed; check the game log, fix it and reload resources.
A render callback may run for both hands. Do not advance shared progress blindly in each call. Use getFrameId(), state keyed by logical hand and item ID, or the bundled smoothItemProgress helper. Logical main/off hand and physical left/right hand are different; prefer the appropriate ItemModel hand query.
InteractiveStuff ships with a resource pack of Vyn scripts that add client-side, first-person item rendering effects. These examples are enabled with the bundled pack and can be configured in the resource-pack options.
| Effect | Examples |
|---|---|
| Animated item parts | Chest lids, pistons, vaults, redstone lamps, the enchanting-table book, sculk sensors, water buckets and extinguishing torches. |
| Item physics | Movement-driven motion for the mace, item frames, paintings and hanging signs, controlled by the pack physics options. |
| Particles and sounds | Enchanting-table glyphs, sculk activation bursts, note-block notes and the note-block interaction sounds. |
| Color and appearance | Biome-aware tinting for foliage, saplings and water, plus the enchanting-table book display option. |
| Other item effects | Totem motion, item-model variants and helper functions shared by the bundled scripts. |
The scripts live in assets/interactivestuff/scripts/ inside the bundled resource pack. You can inspect them as examples when creating your own Vyn resource pack.
InteractiveStuff has a built-in Minecraft-style settings screen; YACL is not required. Open it from InteractiveStuff in Mod Menu, from the Minecraft Options screen when Mod Menu is absent, or with the optional settings keybind.
Use the sidebar to switch categories, search to find a setting, and hover a control for its tooltip. Most changes are staged until you press Apply. Cancel discards the draft; reset and reload controls restore saved values. Hit-sound materials, excluded blocks and per-item pitch overrides use searchable inventory-style selectors.
Mod settings control the engine globally. Settings declared by a resource pack appear in the Packs area, grouped by pack and category, and are saved per pack. See Bundled resource-pack options.
These controls belong to the bundled resource pack, rather than the mod's global engine settings. Open Packs, expand the bundled pack, then choose a category. Values are saved per resource pack.
| Category | Options |
|---|---|
| Appearance | Block, sapling and water tinting; showing the enchanting-table book. |
| Physics | Master physics switch; separate item-physics switches for the mace, item frames, paintings and hanging signs. |
| Animations | Shake intensity; pistons, chests, vaults, redstone lamps, enchanting books, sculk sensors, water-bucket animation and torch extinguishing. |
| Particles | Separate emission switches for enchanting tables, sculk sensors and note blocks. |
| Sounds | Note-block sounds for crouching or swinging interactions. |
| Debug | Vyn debug text and particle counters. |
Pack authors can declare their own options with ConfigOption; see Declare resource-pack settings.
Interactive hit sounds play a configured sound when a supported held item is swung. Configure them in the mod settings screen.
Turning off Interactive hits disables the dependent hit-sound controls. Excluded blocks affect the sound response; they do not disable a resource pack's Vyn effects. The cooldown controls the ticks between hit sounds.
Create a normal Minecraft resource pack with a pack.mcmeta, then add a script under the InteractiveStuff namespace:
MyPack/
pack.mcmeta
assets/
interactivestuff/
scripts/
stick.vynA minimal script can target a held item and adjust its render model:
lock interactiveItems = ["minecraft:stick"]
task onItemUpdate takes itemRendered do
itemRendered.rotate(0, 0, 15)
endEnable the pack in Minecraft's Resource Packs screen. interactiveItems filters which held items receive onItemUpdate; other events require their own item checks. Continue with Vyn language essentials and Models, transforms & colors.
Vyn is the scripting language used by InteractiveStuff resource packs. Scripts are loaded from assets/interactivestuff/scripts/. Use make for a value that can be reassigned and lock for a value that should stay fixed. A task declares reusable code or an event callback.
lock interactiveItems = ["minecraft:stick"]
make tilt = 15
task onItemUpdate takes itemRendered do
check itemRendered.getCount() > 0 do
itemRendered.rotate(0, 0, tilt)
end
endUse check condition do ... end for a condition and otherwise for its alternate branch. Use reply value to return from a task. Lists and maps provide collections; new Type(...) constructs exposed Java-backed Vyn objects. importScript(packId, scriptName) loads a helper script from a resource pack. For the full language grammar and expressions, consult the Vyn documentation.
| Event task | When it runs | Common use |
|---|---|---|
task onTick do | Each active client game tick while the world is ready and unpaused. | Timers, state updates and checks that do not need to run every render. |
task onItemUpdate takes itemRendered do | For each matching held item render. | Transforms, replacement models and particle emitters. The argument is the current render model. |
task onSwingHand do | When the local hand-swing callback fires. | React to a swing; check the held item yourself when needed. |
task onPlaySound takes sound do | When the client observes a sound notification. | Inspect its ID, pitch, volume or position. Avoid recursively responding to a sound your script plays. |
task onKeyPress takes keyInput do | For a gameplay key press when no screen is open. | Compare the integer key code; this is not a text-character event. |
| Global | Purpose |
|---|---|
player | Local player state, held stacks, movement and block queries. |
world | World state, block and biome queries. |
config | Read-only access to mod configuration values. |
modLoader | Installed mod, selected resource-pack and game-version queries. |
particles | Session particle counts and particle clearing. |
key | Legacy translation helper; prefer translateText for displayed text. |
Use onTick for gameplay-tick state and onItemUpdate for render-local changes. Event tasks are callbacks, not ordinary functions you call manually. For particles, declare emitters once and bind them during the relevant render callback; see First-person particles.
itemRendered.setItemModel(id) replaces the appearance of the current rendered stack. new ItemModel(itemId) and itemRendered.copy() enqueue an additional model for that render; they are useful for lids, pages and overlays. Use the current model when you want replacement.
lock interactiveItems = ["minecraft:stick"]
task onItemUpdate takes itemRendered do
check player.getGamemode() == "spectator" do reply nothing end
itemRendered.rotateZ(12)
make ornament = new ItemModel("minecraft:diamond")
ornament.setParent(itemRendered)
ornament.translate(0, 0.25, 0)
ornament.scale(0.2, 0.2, 0.2)
endTranslations, pivots and particle anchors use render/model units, not screen pixels. Model JSON element coordinates are normally expressed on a 0–16 grid, while these render coordinates use unit-scale values; the first-person display transform also affects the final position. Rotations take degrees. Scaling multiplies the model’s scale; shear takes six cross-axis factors.
setPivot(x,y,z) controls the transform anchor. A parent supplies its transform and inherited light/glint where not overridden. Self-parenting and cycles are rejected. detach() removes the parent relationship. Use the pivot marker tools to place hinges in both physical hands.
lookAt(position) aims at a block center. The overload lookAt(position, group, speed, weight) smooths a shared group’s orientation; use the same group for cooperating parts. Speed and weight must be 0–1, and the group must be nonempty, at most 80 characters. setLookAtClearance(surface,minX,minY,minZ,maxX,maxY,maxZ) supplies a clearance plane and local bounds for that aiming path; it is not general collision physics.
| Function | Affects |
|---|---|
setTint(index, packedColor) | Only model faces with the requested tint index. Prefer this for grass, foliage and water masks. |
setTint(packedColor) | The fallback tint override, stored at index −1; it can recolor untinted faces as well. Use the indexed overload to preserve dirt or wood. |
setColor(r,g,b) | The model’s RGB multiplier. Use 0–255 channels. |
setQuadColor(packedColor) | A selection-color override applied through the selected quad path. |
setOpacity(value) | Opacity multiplier, clamped to 0–1. |
lock interactiveItems = ["minecraft:grass_block"]
task onItemUpdate takes itemRendered do
check player.getGamemode() == "spectator" do reply nothing end
make position = player.getSteppingBlock().getPosition()
itemRendered.setTint(0, world.getGrassColor(position))
endUse the right resolver: world.getGrassColor(position), getFoliageColor, getDryFoliageColor or getWaterColor. They return packed colors for setTint. The model must have suitable tintindex faces. For RGB/ARGB integers with no alpha bits, the tint setter supplies opaque alpha.
setQuads(start,end) sets the affected half-open range; unselected geometry remains visible unless exclusive selection is used. The end index is excluded; an end of 0 means the full layer. select(start,end) also enables exclusive selection. Quad ordering depends on the baked model and version, so a range is not a stable identifier for a named model part.
Legacy model routing and modern item-model definitions differ by Minecraft target. Inspect the bundled models and version adapters before distributing a cross-version pack; do not assume one modern item-definition JSON works on 1.20.1. Data-component operations also depend on each target’s supported component bridge.
Bundled chest parts now load Minecraft’s chest images through block-atlas sprite aliases, so active resource-pack replacements of minecraft:textures/entity/chest/*.png are used. Edited sapling masks, bucket water and extinguished-torch images remain pack assets because they are effect-specific.
A ParticleEmitter is a persistent Vyn object. Declare it once at script load, configure it, and attach it to the current model inside onItemUpdate. It owns separate channels for the two logical hands.
These are custom first-person billboards. They use vanilla particle appearances or custom PNGs, but they do not instantiate Minecraft’s native world-particle behaviors. Choosing minecraft:enchant, for example, chooses its textures; you still define its motion.
lock interactiveItems = ["minecraft:stick"]
make sparks = new ParticleEmitter("minecraft:end_rod")
sparks.setPosition(0.5, 0.9, 0.5)
sparks.setSpread(0.08, 0.02, 0.08)
sparks.setVelocity(0, 0.012, 0)
sparks.setVelocitySpread(0.003, 0.004, 0.003)
sparks.setRate(0.15)
sparks.setLifetime(30)
sparks.setSizeOverLife(0.05, 0, "easeOutQuad")
sparks.setOpacityOverLife(1, 0, "easeInQuad")
sparks.setSpace("world")
task onItemUpdate takes itemRendered do
check player.getGamemode() == "spectator" do reply nothing end
sparks.attach(itemRendered)
end| Space | After spawning | Use |
|---|---|---|
item | Positions continue to follow the attached model’s transform. | Glows or particles that move with the item. |
view | The spawn anchor is applied once; particles remain in view coordinates as the player moves/turns. This is the default. | Screen-relative first-person flourishes. |
world | The spawn anchor is converted to world coordinates once; camera motion changes their projection. | Particles that appear to remain behind when you walk or turn. |
setAttached(true) is the older shortcut for item space; setAttached(false) selects view space. Use setSpace("world") explicitly for world-relative behavior. In world space, callback positions and spawn positions are world coordinates; in item space they are local coordinates. Initial velocity is transformed by the spawn anchor in detached spaces.
0.05 is about one particle per second per hand at 20 TPS and 100% density.1 − drag, after gravity.Size, opacity, color and billboard rotation support start/end curves and extra keyframes. Progress is normalized from 0 to 1. A key’s easing controls the interval arriving at that key. Set the start/end curve before adding intermediate keys.
sparks.setSizeOverLife(0.04, 0, "easeOutCubic")
sparks.addSizeKeyframe(0.2, 0.12, "easeOutBack")
sparks.setOpacityOverLife(0, 0, "linear")
sparks.addOpacityKeyframe(0.1, 1, "easeOutQuad")
sparks.addOpacityKeyframe(0.7, 0.8, "linear")
sparks.setColorOverLife(80, 220, 255, 140, 90, 255, "easeInOutSine")
sparks.setRotationOverLife(0, 180, "linear")Supported families: linear, step, quad, cubic, quart, quint, sine, expo, circ, back, bounce and elastic. Use the in, out and inOut prefixes; an optional ease prefix and hyphens/underscores are accepted. For example, easeOutCubic starts fast and slows near the end.
A mathematical illustration of the easing curve, rather than a Minecraft rendering preview. Back easing can overshoot.
setType("minecraft:smoke") reads the active resource pack’s assets/minecraft/particles/smoke.json texture list. A custom type can supply the same JSON shape in its own namespace. Each texture entry resolves under textures/particle/.
{
"textures": [
"mypack:spark_0",
"mypack:spark_1",
"mypack:spark_2"
]
}Store those frames as assets/mypack/textures/particle/spark_0.png and so on. Then call setType("mypack:spark"). Or bypass the frame list with setTexture("mypack:textures/particle/spark.png") for one PNG. Calling setType again clears a direct-texture override.
| Animation mode | Behavior |
|---|---|
lifetime | Distribute the texture-list frames over the particle’s lifetime. Default mode. |
loop | Advance and loop using the specified frame duration in ticks. |
random | Choose one list entry for each particle and keep it. |
first | Always use the first list entry. |
Choose with setAnimation(mode, frameTicks). The duration must be 0.05–12000 ticks, even for modes that do not use it. A frame list may contain at most 256 textures. A missing type or list falls back to a generic appearance and logs a warning; direct textures should always point to an existing PNG.
Depth testing defaults on: setDepthTest(false) draws an effect without the normal depth test. setLight(-1) inherits item light; 0–15 forces brightness. World space does not add collision, world lighting simulation, multiplayer visibility or third-person rendering.
stop() stops new births and clears pending bursts; living particles finish naturally. clear() removes an emitter’s living particles and pending work without changing its enabled state. Item changes finish naturally by default; setClearOnItemChange(true) removes them immediately instead. Changing emitter properties affects newly born particles; an existing particle keeps its birth settings unless its callback changes it.
The engine permits up to 256 emitters per session, up to 128 queued burst births per hand, and up to 128 births per hand per tick. Emission rate is 0–64 per tick. Global density and the 0–4096 particle cap still apply to bursts. Use particles.getDroppedCount() to inspect births dropped at the active-particle cap.
Continuous emission defaults to zero. Keep the rate at zero and request a burst from an event, not every render frame. This example emits from a held stick on a swing.
lock interactiveItems = ["minecraft:stick"]
make puff = new ParticleEmitter("minecraft:smoke")
puff.setRate(0)
puff.setPosition(0.5, 1, 0.5)
puff.setSpread(0.12, 0.04, 0.12)
puff.setVelocity(0, 0.018, 0)
puff.setLifetime(24)
puff.setSizeOverLife(0.06, 0.14, "easeOutQuad")
puff.setOpacityOverLife(0.7, 0, "linear")
puff.setSpace("world")
task onItemUpdate takes itemRendered do
check player.getGamemode() == "spectator" do reply nothing end
puff.attach(itemRendered)
end
task onSwingHand do
check player.getGamemode() == "spectator" do reply nothing end
check player.isHoldingItem("minecraft:stick") do puff.burst(6) end
endburst(count) queues both channels; births require an attached, active held item. If both hands hold the filtered item, both can emit. Use burstForHand(true,count) for logical main hand or burstForHand(false,count) for off hand. emit() is a one-particle burst. A stopped emitter must be started before queued births can occur.
There is no setVelocityOverLife function. For an exact fast-to-slow rise, calculate a position curve from the particle’s progress. Put these tasks in the same script as the emitter.
~ Configure these after declaring puff, before the event tasks.
puff.setVelocity(0, 0, 0)
puff.setOnSpawn("chooseParticleColor")
puff.setOnUpdate("easeParticleRise")
task chooseParticleColor takes particle do
particle.setColor(80, 200, 255)
particle.setSize(0.14)
end
task easeParticleRise takes particle do
make remaining = 1 - particle.getProgress()
make eased = 1 - remaining * remaining * remaining
particle.setPosition(particle.getX(), particle.getSpawnY() + 0.5 * eased, particle.getZ())
endUse setOnSpawn("taskName"), setOnUpdate("taskName") and setOnDeath("taskName"). Each task receives a Particle. Update runs after the engine’s motion/lifetime step while the particle is alive. Death callbacks run for normal tick-driven removals; bulk clear(), reload and global disabling are cleanup operations and do not promise a death callback for every particle.
For pitch-based colors, calculate RGB in the spawn callback from the pitch used for that note. The bundled note_block.vyn includes an example using a normalized 0.5–2.0 pitch and three phase-shifted sine functions.
puff.setPosition(0.5, 1, 0.5)
puff.setSpread(0.15, 0, 0.15)
puff.setVelocitySpread(0.004, 0.002, 0.004)Each new particle receives a fresh X/Z offset around the center. Use a spawn callback with random() when you need a non-box distribution. setSeed(integer) makes an emitter’s random sequence repeatable for testing.
The bundled physics_lib.vyn is an importable spring simulation, rather than a rigid-body or collision engine. It produces angleX and angleZ for the calling script to apply to a model. Movement, changes in camera input and synthetic wind feed the springs.
importScript("interactivestuff:interactive_resourcepack", "physics_lib")
lock interactiveItems = ["minecraft:stick"]
task onItemUpdate takes itemRendered do
check player.getGamemode() == "spectator" do reply nothing end
runPhysicsEngine(0.01, 0.15, -1.0, 0.3, 0.5, 1.0, 45, 0.1)
itemRendered.setPivot(0.5, 0.2, 0.5)
itemRendered.rotate(angleX, 0, angleZ)
endrunPhysicsEngine(stiffness, damping, moveRes, lookRes, vertRes, inertial, maxAngle, windMult)| Parameter | Meaning |
|---|---|
stiffness | Restoring spring force. Increase it for a quicker return to rest. |
damping | Resistance to angular velocity. Increase it to settle oscillation sooner. |
moveRes | Response to changes in horizontal player velocity. A negative value reverses its direction. |
lookRes | Response to changes in the camera pitch/yaw input values. |
vertRes | Response to changes in vertical player velocity. |
inertial | Multiplies movement/look impulses and synthetic wind force. Larger values increase those forces; this is not a physical mass in kilograms. |
maxAngle | Clamp in degrees on both output axes; the boundary partially reflects angular velocity. |
windMult | Strength of time-varying synthetic wind. Zero disables it; it is not Minecraft weather. |
The example’s values are an illustrative starting point, not enforced ranges. The library steps at most once per render frame in each importing script environment. It resets after a rendering gap or significant time interruption and subdivides integration steps. If two items in the same script call it with different settings in one frame, the first call chooses that frame’s parameters.
The imported library declares its own physics_enabled pack option and resets when that value changes. resetPhysicsEngine() clears angles, velocities and timing state. Importing into separate scripts gives them separate state; the library does not automatically create an independent spring for every model part.
player.getVelocityX/Y/Z() return motion transformed into the player’s horizontal yaw frame and scaled by approximately one third. The Y getter removes a small resting gravity offset. Treat them as animation inputs, not unscaled world-space blocks per tick. In the library, the Z input is negated before calculating impulses.
The pack’s Shake intensity scales random jitter in totems, sculk, torches and maces. Physics switches control the spring behavior of frames, paintings, hanging signs and maces. Shake at 0% does not turn off all spring sway; the master physics switch does not suppress unrelated random jitter.
The bundled effect_helpers library also exposes createProgressState(), smoothItemProgress(state,item,target,speed), resetItemProgress(state,item), packToggle(id,category), packShakeOption(), hasMod(id) and isRedstonePowered(). These are pack library tasks, not built-in globals.
Create a ConfigOption at the top level of a script. The mod registers it under the real owning pack, displays it in Packs and stores the player’s value separately from your declaration. Read its value during callbacks to control an effect.
lock interactiveItems = ["minecraft:stick"]
make enabled = new ConfigOption("stick_sway", "toggle", true)
enabled.setLabel("My stick sway")
enabled.setTooltip("Tilt the held stick while crouching.")
enabled.setCategory("Movement")
enabled.setOnChange("onSwayChanged")
make strength = new ConfigOption("stick_angle", "number", 20)
strength.setLabel("Crouch angle")
strength.setCategory("Movement")
strength.setRange(0, 60, 1)
task onSwayChanged takes option, previous, value do
~ Reset your effect state here if it needs a fresh start.
end
task onItemUpdate takes itemRendered do
check !enabled.getBoolean() do reply nothing end
check player.getGamemode() == "spectator" do reply nothing end
check player.isSneaking() do itemRendered.rotateZ(strength.getNumber()) end
end| Type | Default value | Configuration | Reader |
|---|---|---|---|
toggle | true / false | Label, tooltip, category, callback | getBoolean() |
number | Finite number | setRange(min,max,step) | getNumber() |
dropdown | One of the choice strings | setChoices(["a","b"]) | getText() |
color | "#RRGGBB" | Six hexadecimal RGB digits | getColor() / getRed/Green/Blue() |
text | String | setMaxLength(length) | getText() |
make style = new ConfigOption("style", "dropdown", "Soft")
style.setLabel("Particle style")
style.setChoices(["Soft", "Sharp", "None"])
style.setCategory("Particles")
make color = new ConfigOption("color", "color", "#50C8FF")
color.setLabel("Particle color")
color.setCategory("Particles")
make caption = new ConfigOption("caption", "text", "Hello")
caption.setLabel("Debug caption")
caption.setMaxLength(80)
caption.setCategory("Debug")onTick, a particle callback or a render event.min < max and 0 < step ≤ max − min. Values snap to the step and clamp to the range. The default range is 0–1 with step 0.01, so set a range for values such as 20.setOnChange("taskName") registers a task called with (option, previous, value) when a committed value changes. Editing a draft or cancelling does not call it. Use callbacks to stop emitters or reset progress, while ordinary rendering callbacks read the current saved value.
Player values are saved globally per resource pack in config/interactivestuff.json. Reloading a pack rebuilds declarations without deliberately overwriting its saved choices. Renaming the pack’s actual folder/ZIP identity can give it a different saved-settings namespace.
Use a translation key in setLabel, setTooltip or setCategory, and provide that key in assets/<namespace>/lang/en_us.json. translateText is the preferred helper when you need the resolved string inside Vyn.
Enable Debug → Pivot markers and call setPivot in the script. Purple/violet diamonds identify main/off-hand pivots. Enable Emitter markers for green/orange crosses at emitter origins. The symbols distinguish them even when their colors are hard to tell apart.
Markers through items shows markers over the held model. Turn it off to test whether a point is actually hidden by the model’s surface. This is a diagnostic visibility option; it does not alter particle depth settings. Pivot markers do not require particles to be enabled.
The bundled pack supplies Vyn debug text and particle counters under its own Debug category. A custom pack can declare independent options and use the explicit visibility form:
make showDebug = new ConfigOption("debug_mode", "toggle", false)
showDebug.setLabel("Debug text")
showDebug.setCategory("Debug")
task onTick do
debugText("Particles: " + particles.getCount(), showDebug.getBoolean())
endinteractiveItems to avoid dispatching a script for irrelevant items.hasNearbyBlock and getNearestBlock cache queries by tick and player block position; nearest search accepts a radius up to 32.burst() each render frame for a one-shot event.Script failures include the owning pack/script and phase in logs/latest.log. Reload resources after correcting a failed script. An error can disable just the failing script, so a partly working pack can still have a load or callback failure.
Model rendering, stack information, transforms, tint, lighting, parts and targeting.
Use the render callback’s itemRendered, or create an extra model with new ItemModel(itemId).
61 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
new ItemModel(String itemId)ItemModel | Create and enqueue an additional render model from an item registry ID. Use in the render event. An invalid ID resolves to air. |
getName()String | Returns the registry name of the item. |
isDamaged()boolean | Returns whether the item is currently damaged. |
isDamageable()boolean | Returns whether the item can take damage. |
isEnchantable()boolean | Returns whether the item can be enchanted. |
isExclusive()boolean | Returns whether this model is in exclusive (quad-selection) mode. |
isStackable()boolean | Returns whether the item can stack. |
getCount()int | Returns the current stack count. |
getMaxCount()int | Returns the maximum stack size. |
getBobbingAnimationTime()int | Returns the bobbing animation time of the item. |
getLight()int | Read the packed light override, inherit it from a parent, or return −1 for the default. |
getGlint()int | Returns the current glint override value, or -1 if not set. Inherits from parent if unset. |
getRotationX()double | Read the quaternion’s X component, or 0 before rotation. This is not an Euler angle in degrees. |
getRotationY()double | Read the quaternion’s Y component, or 0 before rotation. This is not an Euler angle in degrees. |
getRotationZ()double | Read the quaternion’s Z component, or 0 before rotation. This is not an Euler angle in degrees. |
isMainHand()boolean | Whether this model’s render context is the logical main hand. |
isOffHand()boolean | Whether this model’s render context is the logical off hand. |
isLeftHand()boolean | Whether this model is rendered in the physical left hand, including left-handed player settings. |
isRightHand()boolean | Whether this model is rendered in the physical right hand. |
isFirstPerson()boolean | Whether the model display context is first-person left or right hand. |
getDisplayContextName()String | Read the Minecraft item display-context enum name. |
setItemModel(String model)nothing | Replace this rendered stack’s visual model through the version-specific item-model bridge. This does not change the inventory stack or enqueue a duplicate. |
setBobbingTime(int bobbingTime)nothing | Sets the bobbing animation time. |
setDataComponent(String key, Object value)nothing | Apply a component value through the target’s component bridge. On 1.20.1 only its mapped legacy keys or nbt:TagName are supported; unsupported modern components are rejected. |
getDataComponent(String key)String | Read a serialized data-component value through the target’s component/legacy bridge. |
hasDataComponent(String key)boolean | Returns whether the item has the specified data component. |
getDataComponentIds()List<String> | Returns a list of all data component keys on this item. |
getDataComponents()List<Map<String, String>> | Returns all data components as a list of key-value maps. |
removeDataComponent(String key)nothing | Removes a data component by key. |
setQuads(int start, int end)nothing | Set the affected half-open quad range [start,end). Unselected geometry remains visible unless exclusive selection is used. End 0 means the whole layer; negative bounds clamp to zero. |
setColor(int r, int g, int b)nothing | Set this model’s RGB multiplier using 0–255 channels. |
setOpacity(double opacity)nothing | Set model opacity, clamped to 0–1. |
setLight(int light)nothing | Force brightness 0–15, or −1 to inherit/default. The getter returns the packed light representation, not necessarily this original level. |
setGlint(int glint)nothing | Set glint override, clamped to −1..2: −1 default, 0 off, 1–2 renderer glint modes. |
setTint(int index, int color)nothing | Set a packed RGB/ARGB tint for one index; the one-argument overload sets the fallback index −1. The fallback index −1 can also affect untinted faces; a specific index preserves other faces. Alpha is made opaque when no alpha bits are supplied. |
setTint(int color)nothing | Set a packed RGB/ARGB tint for one index; the one-argument overload sets the fallback index −1. The fallback index −1 can also affect untinted faces; a specific index preserves other faces. Alpha is made opaque when no alpha bits are supplied. |
setQuadColor(int color)nothing | Set the selected-quad color override. An RGB value without alpha bits becomes opaque. |
translate(double dx, double dy, double dz)nothing | Moves the model by the given offset. |
translateX(double dx)nothing | Add a translation in render units on the indicated axis/axes. |
translateY(double dy)nothing | Add a translation in render units on the indicated axis/axes. |
translateZ(double dz)nothing | Add a translation in render units on the indicated axis/axes. |
rotateAxis(double angle, double axisX, double axisY, double axisZ)nothing | Rotates the model by angle degrees around an arbitrary axis vector. |
lookAt(Position position)nothing | Aim at the center of a block position. The grouped overload shares smoothed orientation for cooperating parts: nonblank group ≤80 characters; finite speed and weight 0–1. |
lookAt(Position position, String group, double speed, double weight)nothing | Aim at the center of a block position. The grouped overload shares smoothed orientation for cooperating parts: nonblank group ≤80 characters; finite speed and weight 0–1. |
setLookAtClearance(double surface, double minX, double minY, double minZ, double maxX, double maxY, double maxZ)nothing | Provide a surface height and local min/max bounds for clearance during model targeting. This does not enable world collision physics. |
rotate(double dx, double dy, double dz)nothing | Rotates the model around all three axes (in degrees). |
rotateX(double angle)nothing | Compose a rotation in degrees on the indicated axis/axes. Applied around the current pivot. |
rotateY(double angle)nothing | Compose a rotation in degrees on the indicated axis/axes. Applied around the current pivot. |
rotateZ(double angle)nothing | Compose a rotation in degrees on the indicated axis/axes. Applied around the current pivot. |
scale(double sx, double sy, double sz)nothing | Multiplies the model's scale on all axes. |
scaleX(double sx)nothing | Multiply scale on the indicated axis/axes. |
scaleY(double sy)nothing | Multiply scale on the indicated axis/axes. |
scaleZ(double sz)nothing | Multiply scale on the indicated axis/axes. |
shear(double xy, double xz, double yx, double yz, double zx, double zy)nothing | Applies a shear transformation using the six shear components. |
smooth(double current, double target, double speed)double | Return current + (target − current) × (1 − (1 − speed)^getDelta()). Use a speed in 0–1 for normal frame-independent interpolation; retain the result yourself. |
setPivot(double x, double y, double z)nothing | Set the local transform pivot in render units. Default is (0.5,0.5,0.5); diagnostic markers are recorded when enabled. |
setParent(ItemModel parent)nothing | Assign a parent transform; self-parenting and cycles are rejected. |
select(int quadStart, int quadEnd)nothing | Set the half-open quad range and enable exclusive selection. End 0 means the full layer. |
copy()ItemModel | Copy the current working model and transforms, preserve its hand/context and enqueue it as an additional render model. |
detach()nothing | Remove this model’s parent relationship. |
hasParent()boolean | Returns whether this model currently has a parent. |
Local player state, movement, held stacks, block queries and client-local sound.
Available globally as player. Nullable block/item results must be checked against nothing.
99 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
getSteppingBlock()Block | Returns the block the player is currently standing on. |
getNearbyBlocks(int blockRadius)List<Block> | Return a list of non-air blocks in a cubic radius around the player. This scans the cube; keep the radius small and avoid repeating it every frame. |
getTargetBlock()Block | Return the targeted block, or nothing when the crosshair is not targeting a block. Check before calling methods on it. |
getGamemode()String | Returns the player's current gamemode as a string. |
getPosition()Position | Return the player’s integer block position, or nothing without a player. Use eye-position getters for fractional eye coordinates. |
getWorld()World | Returns the current world the player is in. |
getActiveItem()ItemModel | Returns the item currently being used (e.g. while eating or drawing a bow). |
getMainHandItem()ItemModel | Returns the item in the player's main hand. |
getOffHandItem()ItemModel | Returns the item in the player's off hand. |
getBlockingItem()ItemModel | Return the version-adapted blocking item, or nothing if absent. It is not guaranteed to exist in every state. |
getWeaponItem()ItemModel | Return the version-adapted weapon item, or nothing without a living player. |
getPickBlockItem()ItemModel | Return the living entity’s pick-result item, not the item currently targeted by the crosshair. |
getHealth()double | Returns the player's current health. |
getFoodLevel()double | Returns the player's current food/hunger level (0–20). |
getSaturationLevel()double | Returns the player's current saturation level. |
getNauseaIntensity()float | Returns the current nausea effect intensity. |
getExperienceLevel()int | Returns the player's current experience level. |
getItemUseTime()int | Returns how many ticks the player has been using their current item. |
getItemUseTimeLeft()int | Returns how many ticks remain before the player finishes using their current item. |
getArmor()int | Returns the player's current total armor value. |
getEyePosX()double | Returns the X coordinate of the player's eye position. |
getEyePosY()double | Returns the Y coordinate of the player's eye position. |
getEyePosZ()double | Returns the Z coordinate of the player's eye position. |
getHeadYaw()double | Returns the player's current head yaw (horizontal rotation in degrees). |
getDamageTiltYaw()double | Returns the yaw direction of the most recent damage tilt effect. |
getStepHeight()double | Returns the player's step height (how tall a block they can step up without jumping). |
getExperienceProgress()double | Returns the player's progress toward the next experience level (0.0–1.0). |
getVelocityX()double | Return yaw-relative X motion scaled by 0.3333, suitable as an animation input. It is not raw world-axis velocity. |
getVelocityY()double | Return vertical motion scaled by 0.3333, with the small resting gravity offset suppressed. |
getVelocityZ()double | Return yaw-relative Z motion scaled by 0.3333. The physics library negates it before using it. |
hasNearbyBlock(String blockId, int radius)boolean | Test for a matching block in a cubic radius. Nonnegative radius; cached for the current tick and player block position. |
getNearestBlock(String blockId, int radius)Block | Return the nearest matching block center within a cubic radius 0–32, or nothing. Queries are cached for the current tick and player block position. |
getCameraPitchVelocity()float | Returns the rate of change of the camera's pitch (vertical look speed). |
getCameraYawVelocity()float | Returns the rate of change of the camera's yaw (horizontal look speed). |
isSwimming()boolean | Returns whether the player is swimming. |
isSprinting()boolean | Returns whether the player is sprinting. |
isInLava()boolean | Returns whether the player is in lava. |
isInFluid()boolean | Returns whether the player is in any fluid. |
isOnFire()boolean | Returns whether the player is on fire. |
isTouchingWater()boolean | Returns whether the player is touching water. |
isFlyingVehicle()boolean | Returns whether the player is in a flying vehicle. |
isClimbing()boolean | Returns whether the player is climbing (e.g. ladder or vine). |
isDescending()boolean | Returns whether the player is descending (e.g. on a ladder). |
isCrawling()boolean | Returns whether the player is crawling. |
isBlocking()boolean | Returns whether the player is blocking with a shield. |
isRiding()boolean | Returns whether the player is riding an entity. |
isPushable()boolean | Returns whether the player can be pushed by other entities. |
isPushedByFluids()boolean | Returns whether the player is pushed by fluid currents. |
isInvulnerable()boolean | Returns whether the player is currently invulnerable. |
isUsingItem()boolean | Returns whether the player is currently using an item. |
isUsingRiptide()boolean | Returns whether the player is currently using a riptide trident. |
isUsingSpyglass()boolean | Returns whether the player is currently using a spyglass. |
isFrozen()boolean | Returns whether the player is frozen (in powder snow). |
isGlowing()boolean | Returns whether the player has the glowing effect (server-side). |
isGlowingLocal()boolean | Returns whether the player is glowing locally (client-side). |
isAtCloudHeight()boolean | Returns whether the player is at cloud height. |
isAutoJumpEnabled()boolean | Returns whether auto-jump is enabled. |
isHoldingOntoLadder()boolean | Returns whether the player is holding onto a ladder. |
isLimitedCraftingEnabled()boolean | Returns whether limited crafting is enabled for this player. |
isInsideWall()boolean | Returns whether the player is clipping inside a block. |
isJumping()boolean | Returns whether the player is currently jumping. |
isOnRail()boolean | Returns whether the player is on a rail. |
isFireImmune()boolean | Returns whether the player is immune to fire damage. |
isFirstPerson()boolean | Returns whether the player is currently in first-person perspective. |
isSubmergedInWater()boolean | Returns whether the player is fully submerged in water. |
isSneaking()boolean | Returns whether the player is sneaking. |
isOnGround()boolean | Returns whether the player is on the ground. |
showsDeathScreen()boolean | Returns whether the player would show the death screen upon dying. |
isHorizontalCollision()boolean | Returns whether the player is colliding with a block horizontally. |
isInSneakingPose()boolean | Returns whether the player is in a sneaking pose (visual). |
shouldSlowDown()boolean | Returns whether the player's movement should be slowed (e.g. in a cobweb or powder snow). |
isRidingJumpable()boolean | Returns whether the player is riding a mount that can jump. |
getMountJumpStrength()float | Returns the jump strength of the player's current mount. |
isCamera()boolean | Returns whether the player is the current camera entity. |
getPermissionLevel()int | Returns the player's current operator permission level (0–4). |
isMainPlayer()boolean | Returns whether this is the main/local player. |
getMoodPercentage()float | Returns the player's current mood percentage (used for cave ambience sounds). |
canBreatheInWater()boolean | Returns whether the player can breathe underwater (e.g. via a helmet enchantment or effect). |
hasLandedInFluid()boolean | Returns whether the player has just landed in a fluid. |
isBaby()boolean | Returns whether the player is in baby form. |
getScaleFactor()float | Returns the player's scale factor (used for size-affecting effects). |
getScale()float | Returns the player's current scale. |
shouldSwimInFluids()boolean | Returns whether the player should swim when in fluids. |
canTakeDamage()boolean | Returns whether the player is currently able to take damage. |
isPartOfGame()boolean | Return the entity visibility-eligibility predicate used by this adapter (canBeSeenByAnyone), rather than a network connection check. |
isDead()boolean | Returns whether the player is dead. |
getLuck()float | Returns the player's current luck attribute value. |
getAbsorptionAmount()float | Returns the player's current absorption (bonus health) amount. |
getMaxAbsorption()float | Returns the player's maximum absorption amount. |
getStuckArrowCount()int | Returns the number of arrows currently stuck in the player. |
getStingerCount()int | Returns the number of bee stingers currently stuck in the player. |
hasNoDrag()boolean | Returns whether the player has no drag applied (no velocity dampening from fluids or air). |
isMainHand(ItemModel item)boolean | Check whether the supplied model wraps the exact source stack in the logical main hand. |
isOffHand(ItemModel item)boolean | Check whether the supplied model wraps the exact source stack in the logical off hand. |
isHoldingItem(String itemId)boolean | Test whether either hand holds the namespaced item ID. |
playSound(String soundId, double volume, double pitch)nothing | Play a local player sound from a registered sound ID and volume/pitch, or a Sound wrapper. Sound events are client-side. |
playSound(Sound sound)nothing | Play a local player sound from a registered sound ID and volume/pitch, or a Sound wrapper. Sound events are client-side. |
playSoundWorld(Position position, String soundId, double volume, double pitch)nothing | Play a local sound at an integer Position in the client world. This does not send a server/world sound event to other players. |
playSoundWorld(Position position, Sound sound)nothing | Play a local sound at an integer Position in the client world. This does not send a server/world sound event to other players. |
Blocks, biome colors, dimensions and world time.
Available globally as world, or through player.getWorld().
15 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
getBlock(int x, int y, int z)Block | Return a block wrapper at integer coordinates, or nothing when there is no world. |
getDimension()String | Return the dimension’s namespaced registry ID, or an empty string without a world. |
isDay()boolean | Returns whether it is currently daytime. |
getTimeOfDay()long | Returns the time of day in ticks (0–24000). |
getTime()long | Returns the total world time elapsed in ticks (ever-increasing). |
calculateDistanceBetweenPositions(Position pos1, Position pos2)long | Delegate to Position.getDistanceTo: Euclidean distance truncated to an integer. |
getBiomeAt(int x, int y, int z)String | Returns the biome ID at the given Position. |
getBiomeColorAt(int x, int y, int z)int | Compatibility alias for the foliage color resolver, not a universal color for every block type. |
getBiomeAt(Position position)String | Returns the biome ID at the given Position. |
getGrassColor(Position position)int | Resolve a packed grass color at the position. Use with tint-bearing grass faces. |
getDryFoliageColor(Position position)int | Resolve the target version’s adapted dry-foliage color at the position. |
getFoliageColor(Position position)int | Resolve a packed foliage color at the position. |
getWaterColor(Position position)int | Resolve a packed biome-water color at the position. |
getBiomeColorAt(Position position)int | Compatibility alias for the foliage color resolver, not a universal color for every block type. |
toString()String | Returns a string summary of the world state. |
Block registry ID, tags, position, instrument and state predicates.
Obtained from player/world queries; no Vyn constructor is exposed.
13 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
getName()String | Returns the item/block name as a string. |
hasBlockTag(String tagID)boolean | Matches block tag names using a case-insensitive substring test. Pass a full namespaced tag ID for a precise intended match. |
getPosition()Position | Returns the block's world position. |
getBlockLightLevel()int | Returns the block light level at this block's position (0–15). |
getSkyLightLevel()int | Returns the sky light level at this block's position (0–15). |
getInstrument()String | Returns the note block instrument sound ID associated with this block. |
isSolid()boolean | Reports whether the state acts as a redstone conductor at this position; it is not a general collision-shape test. |
isAir()boolean | Returns whether this block is air. |
isBurnable()boolean | Reports whether the state can be ignited by lava. |
isTransparent()boolean | Reports the target version’s skylight-propagation test. |
isOpaque()boolean | Reports whether the state can occlude other faces. |
isOpaqueFullCube()boolean | Reports the target version’s solid-render test. |
toString()String | Returns the full block state as a string, including block properties. |
Mutable integer positions and integer-truncated distance.
Construct with new Position(x,y,z). Coordinates are integer block coordinates.
10 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
new Position(int x, int y, int z)Position | Create a mutable integer block-position wrapper. Particle callback positions are separate double-valued coordinates. |
getDistanceTo(Position other)long | Compute Euclidean distance and truncate to a long/integer; this is not squared distance or a fractional result. |
getDistanceTo(int x, int y, int z)long | Compute Euclidean distance and truncate to a long/integer; this is not squared distance or a fractional result. |
getX()int | Returns the X coordinate. |
getY()int | Returns the Y coordinate. |
getZ()int | Returns the Z coordinate. |
setX(int x)nothing | Sets the X coordinate. |
setY(int y)nothing | Sets the Y coordinate. |
setZ(int z)nothing | Sets the Z coordinate. |
toString()String | Returns a string representation of this position. |
A sound-data wrapper. Changing the wrapper is not a documented cancellation/replacement of an already dispatched game sound.
Construct with new Sound(soundId,volume,pitch,position), or inspect onPlaySound’s argument.
10 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
new Sound(String soundId, double volume, double pitch, Position position)Sound | Creates a new Sound object. |
getPosition()Position | Returns the world position this sound is associated with. |
getName()String | Returns the namespaced sound ID. |
getVolume()double | Returns the volume of the sound. |
getPitch()double | Returns the pitch of the sound. |
setSoundId(String soundId)nothing | Sets the namespaced sound ID. |
setVolume(double volume)nothing | Sets the volume. |
setPitch(double pitch)nothing | Sets the pitch. |
setPosition(Position position)nothing | Sets the world position. |
toString()String | Returns a string representation of this sound. |
Persistent first-person emission with per-hand channels, motion and lifetime controls.
Construct once with new ParticleEmitter(typeId), then attach in onItemUpdate.
42 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
new ParticleEmitter(String type)ParticleEmitter | Create and register one persistent emitter from a namespaced particle-appearance ID. Declare once at script load. |
attach(ItemModel item)nothing | Bind to the current ItemModel’s final anchor and logical hand for the current rendering frame. Required for births. |
emit()nothing | Queue a burst of one for each hand channel; active attached channels can emit. |
burst(int count)nothing | Queue up to 128 pending births per hand. Global density and cap apply; a stopped emitter must be started. |
burstForHand(boolean mainHand, int count)nothing | Queue a burst for one logical hand: true main hand, false off hand. Pending count clamps to 128. |
start()nothing | Enable new emissions. Does not reset a rate or clear old particles. |
stop()nothing | Disable new emissions and clear pending bursts. Existing particles finish naturally. |
clear()nothing | Remove this emitter’s living particles and pending/fractional births. The enabled state remains unchanged. |
getCount()int | Count living particles in both hand channels of this emitter. |
setSeed(int seed)nothing | Seed this emitter’s pseudorandom generator using a Vyn-compatible integer. |
setType(String type)nothing | Set a namespaced appearance ID read from particles/<path>.json; clears a direct texture override. |
setTexture(String texture)nothing | Use a direct namespaced PNG path such as mypack:textures/particle/spark.png. |
setRate(double particlesPerTick)nothing | Set 0–64 particles per tick per active hand. Default 0; 0.05 is one per second at 20 TPS and full density. |
setLifetime(double ticks)nothing | Set lifetime 1–12000 ticks. Default 20. |
setLifetimeSpread(double ticks)nothing | Set uniform ± lifetime randomness, 0–12000 ticks. Resulting lifetime is at least one tick. Default 0. |
setPosition(double x, double y, double z)nothing | Set the local spawn center in render units. Default (0,0,0). |
setSpread(double x, double y, double z)nothing | Set fresh uniform ± birth-position randomness per axis, each 0–100. Default (0,0,0). |
setVelocity(double x, double y, double z)nothing | Set initial displacement per tick along each axis. Default (0,0,0). |
setVelocitySpread(double x, double y, double z)nothing | Set fresh uniform ± initial-velocity randomness per axis, each 0–100. Default zero. |
setGravity(double gravity)nothing | Set acceleration subtracted from Y velocity each tick. Negative values rise. Default 0. |
setDrag(double drag)nothing | Set velocity damping 0–1; each tick multiplies velocity by 1 − drag. Default 0. |
setAttached(boolean attached)nothing | Compatibility shortcut: true selects item space, false selects view space. Does not select world space. |
setSpace(String space)nothing | Choose exactly item, view or world. Default view. World coordinates still render only through the first-person pass. |
setDepthTest(boolean depth)nothing | Enable/disable particle depth testing. Default true. Separate from diagnostic-marker visibility. |
setClearOnItemChange(boolean clear)nothing | Choose immediate removal on item changes (true), or natural completion (false, default). |
setLight(int light)nothing | Set −1 to inherit item brightness (default), or a forced level 0–15. |
setAnimation(String mode, double frameTicks)nothing | Choose lifetime (default), loop, random or first. Frame duration must be 0.05–12000 ticks; default 1. |
setSize(double size)nothing | Set constant size 0–100. Default 0.06. |
setOpacity(double opacity)nothing | Set constant opacity 0–1. Default 1. |
setRotation(double degrees)nothing | Set constant billboard rotation in degrees. Default 0. |
setSizeOverLife(double start, double end, String easing)nothing | Set start/end size (0–100) with easing over normalized lifetime. |
setOpacityOverLife(double start, double end, String easing)nothing | Set start/end opacity (0–1) with easing over normalized lifetime. |
setRotationOverLife(double start, double end, String easing)nothing | Set start/end billboard rotation in degrees with easing over normalized lifetime. |
addSizeKeyframe(double progress, double size, String easing)nothing | Add/replace a size key at progress 0–1, size 0–100. Easing controls the interval arriving at this key. |
addOpacityKeyframe(double progress, double opacity, String easing)nothing | Add/replace an opacity key at progress 0–1, opacity 0–1. Easing controls the incoming interval. |
addRotationKeyframe(double progress, double degrees, String easing)nothing | Add/replace a degree-rotation key at progress 0–1. Easing controls the incoming interval. |
setColor(int red, int green, int blue)nothing | Set constant RGB channels, each integer 0–255. Default white. |
setColorOverLife(int r1, int g1, int b1, int r2, int g2, int b2, String easing)nothing | Interpolate start/end RGB channels 0–255 with the supplied easing. |
addColorKeyframe(double progress, int red, int green, int blue, String easing)nothing | Add/replace an RGB key at progress 0–1; channels 0–255. Easing controls the incoming interval. |
setOnSpawn(String task)nothing | Name a task receiving each newly born Particle; an empty string disables the callback. |
setOnUpdate(String task)nothing | Name a task receiving each live Particle after its tick motion step. |
setOnDeath(String task)nothing | Name a task for tick-driven particle removals. Bulk clear/reload cleanup does not promise individual death calls. |
Per-particle state and overrides, in the particle’s selected simulation space.
Received in emitter spawn/update/death callbacks. No Vyn constructor is exposed.
19 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
getAge()double | Return current age in ticks. |
getLifetime()double | Return this birth’s randomized lifetime in ticks. |
getProgress()double | Return age/lifetime capped at 1. |
getX()double | Read current X in this particle’s simulation space. |
getY()double | Read current Y in this particle’s simulation space. |
getZ()double | Read current Z in this particle’s simulation space. |
getSpawnX()double | Read birth X in simulation space; it remains unchanged after setPosition calls. |
getSpawnY()double | Read birth Y in simulation space; it remains unchanged after setPosition calls. |
getSpawnZ()double | Read birth Z in simulation space; it remains unchanged after setPosition calls. |
isAlive()boolean | Whether the particle has not been killed or expired. |
isMainHand()boolean | Whether this particle was born in the logical main-hand channel. |
isOffHand()boolean | Whether this particle was born in the logical off-hand channel. |
kill()nothing | Mark this particle dead for removal. |
setPosition(double x, double y, double z)nothing | Set current position in simulation space. Does not change recorded spawn coordinates. |
setVelocity(double x, double y, double z)nothing | Set per-tick motion for this particle only. |
setOpacity(double opacity)nothing | Replace this particle’s opacity curve with a constant, clamped to 0–1. |
setSize(double size)nothing | Replace this particle’s size curve with a nonnegative constant. |
setRotation(double degrees)nothing | Replace this particle’s billboard-rotation curve with constant degrees. |
setColor(int red, int green, int blue)nothing | Replace this particle’s color curves with constant RGB channels clamped to 0–255. |
Counts and clearing across this client session’s emitters.
Available globally as particles.
4 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
getCount()int | Return the number of living particles across all registered emitters and hands. |
getEmitterCount()int | Return the number of currently registered session emitters. |
getDroppedCount()long | Return cumulative births dropped by the active-particle cap during this session. Not a count of every disabled or rejected request. |
clear()nothing | Clear particles and queued work across all emitters. Emitter registrations and enabled states remain; session reset handles those separately. |
Pack-owned settings declarations and player-owned persisted values.
Construct and configure at script load. Read values during callbacks.
16 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
new ConfigOption(String id, String type, Object defaultValue)ConfigOption | Declare a player-facing setting while the script loads. Types: toggle, number, dropdown, color, text. The owning resource pack supplies the saved-value namespace. |
setLabel(String value)nothing | Set literal label text or a translation key, at most 160 characters. Loading only. |
setTooltip(String value)nothing | Set literal help text or a translation key, at most 1024 characters. Loading only. |
setCategory(String value)nothing | Group the option inside its pack. Literal text or translation key, at most 96 characters. Loading only. |
setOnChange(String task)nothing | Name a task receiving (option, previous, value) after a committed change; at most 160 characters. Loading only. |
setRange(double min, double max, double increment)nothing | For numbers, set finite min < max and 0 < increment ≤ max − min. Values snap to the increment and clamp. Default range 0–1, step 0.01. |
setChoices(List<String> values)nothing | Set 1–64 dropdown strings (each up to 160 characters); duplicates are removed. The default must be among the choices. |
setMaxLength(int length)nothing | Set text maximum to 1–4096 characters. Default 256. Loading only. |
getValue()Object | Read the current saved, normalized value using its declared type. |
getBoolean()boolean | Read a toggle. Use only with type toggle. |
getNumber()double | Read a numeric option. Use only with type number. |
getText()String | Read a text or dropdown string. |
getColor()String | Read a color string normalized to uppercase #RRGGBB. |
getRed()int | Read the red color channel, 0–255. |
getGreen()int | Read the green color channel, 0–255. |
getBlue()int | Read the blue color channel, 0–255. |
Global engine settings and legacy pack-accessor compatibility.
Available globally as config; use ConfigOption for new pack-specific settings.
14 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
isParticlesEnabled()boolean | Read the global particle permission. |
getParticleLimit()int | Read the global active-particle cap. |
getParticleDensity()int | Read the global emission percentage (normally 0–200). |
isParticleDebugCountersEnabled()boolean | Read the current calling pack’s debug_counters choice; this is not a global marker switch. |
isResourcePackDebugModeEnabled ()boolean | Read the current calling pack’s debug_mode choice; this controls the one-argument debugText helper. |
isInteractiveHitsEnabled()boolean | Returns whether the interactive hits feature is enabled. |
isSculkSensorFeatureEnabled()Legacy boolean | Legacy accessor for the calling pack’s animate_sculk_sensor setting, falling back to sculk_sensors. Prefer a ConfigOption. |
getHitCooldownTicks()int | Returns the cooldown duration (in ticks) between hits. |
isTextureChangesEnabled()Legacy boolean | Legacy accessor for the calling pack’s texture_changes flag. Prefer individual ConfigOption controls. |
isNoteBlockCrouchFeatureEnabled()Legacy boolean | Legacy accessor for the pack’s note_block_sounds setting, falling back to note_block_crouch. Prefer ConfigOption. |
getCooldownTicks()int | Alias of the global interactive-hit cooldown getter. |
isSpecializedNoteblockHitsEnabled()Legacy boolean | Legacy accessor for note_block_sounds, falling back to note_block_hits. Prefer ConfigOption. |
isResourcePackMatrixEditingEnabled()boolean | Returns whether resource pack matrix editing is enabled. |
isResourcePackColorChangingEnabled()boolean | Returns whether resource pack color changing is enabled. |
Installed mod IDs, selected resource-pack IDs and game-version string.
Available globally as modLoader.
3 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
isModLoaded(String modid)boolean | Check whether Fabric reports a mod ID installed. This does not tell you whether that mod’s in-game feature is currently enabled. |
isResourcePackLoaded(String packName)boolean | Compare an exact selected pack ID, case-insensitively. Use the real ID such as file/MyPack.zip, not only the display name. |
getRawGameVersion()String | Return the game-version string through the compatibility adapter. Despite the method name, this no longer requires Fabric Loader’s getRawGameVersion API. |
Legacy translation helper.
Available globally as key. Prefer translateText for new display text.
1 exposed signatures. Return types retain their source names: int/long/float/double are numeric values; void is shown as nothing.
| Signature / return | Behavior |
|---|---|
getTranslatedKey(String key)String | Legacy translation helper returning the component’s toString representation. Prefer the global translateText(key, ...arguments) for displayed text. |
Custom model IDs use interactivestuff:<name> in the bundled scripts. Models are baked resources: their first-person display transforms, tint indices and atlas sources matter as much as the script transforms.
interactivestuff:acacia_sapling_leaves, interactivestuff:acacia_sapling_wood, interactivestuff:book_left, interactivestuff:book_right, interactivestuff:bucket, interactivestuff:chest_base, interactivestuff:chest_top, interactivestuff:copper_chest_base, interactivestuff:copper_chest_top, interactivestuff:dark_oak_sapling_leaves, interactivestuff:dark_oak_sapling_wood, interactivestuff:ender_chest_base, interactivestuff:ender_chest_top, interactivestuff:exposed_copper_chest_base, interactivestuff:exposed_copper_chest_top, interactivestuff:jungle_sapling_leaves, interactivestuff:jungle_sapling_wood, interactivestuff:oak_sapling_leaves, interactivestuff:oak_sapling_wood, interactivestuff:oxidized_copper_chest_base, interactivestuff:oxidized_copper_chest_top, interactivestuff:piston_base, interactivestuff:piston_top, interactivestuff:redstone_torch_off, interactivestuff:spruce_sapling_leaves, interactivestuff:spruce_sapling_wood, interactivestuff:sticky_piston_top, interactivestuff:torch_off, interactivestuff:trapped_chest_base, interactivestuff:trapped_chest_top, interactivestuff:water_of_the_bucket, interactivestuff:weathered_copper_chest_base, interactivestuff:weathered_copper_chest_top
These are effect-specific layers rather than exact vanilla copies. An overriding pack can replace them in the interactivestuff namespace.
acacia_sapling_leaves.png, acacia_sapling_wood.png, bucket.png, dark_oak_sapling_leaves.png, dark_oak_sapling_wood.png, jungle_sapling_leaves.png, jungle_sapling_wood.png, oak_sapling_leaves.png, oak_sapling_wood.png, spruce_sapling_leaves.png, spruce_sapling_wood.png, torch_off.png, water_of_the_bucket.png
| Model sprite alias | Image supplied by Minecraft / active pack |
|---|---|
interactivestuff:vanilla/chest/normal | minecraft:textures/entity/chest/normal.png |
interactivestuff:vanilla/chest/trapped | minecraft:textures/entity/chest/trapped.png |
interactivestuff:vanilla/chest/ender | minecraft:textures/entity/chest/ender.png |
interactivestuff:vanilla/chest/copper | minecraft:textures/entity/chest/copper.png |
interactivestuff:vanilla/chest/copper_exposed | minecraft:textures/entity/chest/copper_exposed.png |
interactivestuff:vanilla/chest/copper_weathered | minecraft:textures/entity/chest/copper_weathered.png |
interactivestuff:vanilla/chest/copper_oxidized | minecraft:textures/entity/chest/copper_oxidized.png |
The aliases are registered by assets/minecraft/atlases/blocks.json. 1.20.1, 1.21.1 and 1.21.5 register only normal/trapped/ender aliases and give dormant copper part models a normal-chest fallback, because those releases have no native copper chest assets. There is no active Christmas chest model in the current pack.
These are the exact seventeen Vyn files bundled in the current shared source. Expand a file to read or copy it. They document real implementation details and are not seventeen independent templates to paste together. The two helper libraries are importable; files with event tasks are active scripts.
chests.vyn49 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make animationOption = packToggle("animate_chests", "animation")
animationOption.setOnChange("onAnimationChanged")
lock interactiveItems = ["minecraft:chest", "minecraft:ender_chest", "minecraft:trapped_chest", "minecraft:copper_chest", "minecraft:waxed_copper_chest", "minecraft:exposed_copper_chest", "minecraft:waxed_exposed_copper_chest", "minecraft:weathered_copper_chest", "minecraft:waxed_weathered_copper_chest", "minecraft:oxidized_copper_chest", "minecraft:waxed_oxidized_copper_chest"]
lock chestVariants = new Map
chestVariants.put("minecraft:chest", "chest")
chestVariants.put("minecraft:ender_chest", "ender_chest")
chestVariants.put("minecraft:trapped_chest", "trapped_chest")
chestVariants.put("minecraft:copper_chest", "copper_chest")
chestVariants.put("minecraft:waxed_copper_chest", "copper_chest")
chestVariants.put("minecraft:exposed_copper_chest", "exposed_copper_chest")
chestVariants.put("minecraft:waxed_exposed_copper_chest", "exposed_copper_chest")
chestVariants.put("minecraft:weathered_copper_chest", "weathered_copper_chest")
chestVariants.put("minecraft:waxed_weathered_copper_chest", "weathered_copper_chest")
chestVariants.put("minecraft:oxidized_copper_chest", "oxidized_copper_chest")
chestVariants.put("minecraft:waxed_oxidized_copper_chest", "oxidized_copper_chest")
make openingState = createProgressState()
task onAnimationChanged takes option, previous, value do
make openingState = createProgressState()
end
task onItemUpdate takes itemRendered do
check !animationOption.getBoolean() do reply nothing end
make variant = chestVariants.get(itemRendered.getName())
check variant == nothing do reply nothing end
itemRendered.setItemModel("interactivestuff:" + variant + "_base")
make chestTop = new ItemModel("minecraft:" + variant)
chestTop.setItemModel("interactivestuff:" + variant + "_top")
chestTop.setParent(itemRendered)
make openProgress = smoothItemProgress(openingState, itemRendered, getFallTarget(), 0.2)
check itemRendered.isRightHand() do
chestTop.setPivot(0.12, 0.17, -0.063)
chestTop.rotateAxis(-90 * (openProgress / 100), 1, 0, 1.25)
otherwise
chestTop.setPivot(-0.12, 0.17, -0.063)
chestTop.rotateAxis(-90 * (openProgress / 100), 1, 0, -1.25)
end
end
task getFallTarget do
reply max(-7, min(100, player.getVelocityY() * -100))
enddebug.vyn55 linesmake debugModeOption = new ConfigOption("debug_mode", "toggle", false)
debugModeOption.setLabel("interactive_stuff.config.menu.setting.debug")
debugModeOption.setCategory("interactive_stuff.config.menu.pack.category.debug")
debugModeOption.setTooltip("interactive_stuff.config.menu.setting.debug.tooltip")
make debugCounterOption = new ConfigOption("debug_counters", "toggle", false)
debugCounterOption.setLabel("interactive_stuff.config.menu.setting.counter")
debugCounterOption.setCategory("interactive_stuff.config.menu.pack.category.debug")
debugCounterOption.setTooltip("interactive_stuff.config.menu.setting.counter.tooltip")
task onTick do
check !debugModeOption.getBoolean() do
showParticleCounters()
reply nothing
end
debugText("§6Game version: " + modLoader.getRawGameVersion())
debugText("§aMain Hand Item: " + player.getMainHandItem().getName())
check player.getBlockingItem() != nothing do
debugText("§aBlocking Item: " + player.getBlockingItem().getName())
end
check player.getWeaponItem() != nothing do
debugText("§aWeapon Item: " + player.getWeaponItem().getName())
end
check player.getPickBlockItem() != nothing do
debugText("§aPick Block Item: " + player.getPickBlockItem().getName())
end
debugText("§cHealth: " + player.getHealth())
debugText("§aStepping Block: " + player.getSteppingBlock().getName())
check player.getTargetBlock() != nothing do
debugText("§aTarget Block: " + player.getTargetBlock().getName())
end
debugText("§2Gamemode: " + player.getGamemode())
debugText("§6Pos: " + player.getPosition().getX() + ", " + player.getPosition().getY() + ", " + player.getPosition().getZ())
debugText("§bDimension: " + player.getWorld().getDimension())
debugText("§eIs 1st Person?: " + player.isFirstPerson())
debugText("§eIs Sneaking?: " + player.isSneaking())
debugText("§eIs Swimming?: " + player.isSwimming())
debugText("§eIs Sprinting?: " + player.isSprinting())
debugText("§eOn Ground?: " + player.isOnGround())
debugText("§eIs Jumping?: " + player.isJumping())
debugText("§eIs Underwater?: " + player.isSubmergedInWater())
debugText("§eIs at cloud height?: " + player.isAtCloudHeight())
debugText("§bX Velocity: " + player.getVelocityX())
debugText("§bY Velocity: " + player.getVelocityY())
debugText("§bZ Velocity: " + player.getVelocityZ())
debugText("§bCamera Pitch: " + player.getCameraPitchVelocity())
debugText("§bCamera Yaw: " + player.getCameraYawVelocity())
showParticleCounters()
end
task showParticleCounters do
check debugCounterOption.getBoolean() do
debugText(translateText("interactivestuff.debug.particles", particles.getCount(), config.getParticleLimit(), particles.getEmitterCount(), particles.getDroppedCount()), true)
end
endeffect_helpers.vyn63 linestask packToggle takes id, category do
make option = new ConfigOption(id, "toggle", true)
option.setLabel("interactive_stuff.config.menu.pack." + id)
option.setTooltip("interactive_stuff.config.menu.pack." + id + ".tooltip")
option.setCategory("interactive_stuff.config.menu.pack.category." + category)
reply option
end
task packShakeOption do
make option = new ConfigOption("shake_intensity", "number", 100)
option.setLabel("interactive_stuff.config.menu.pack.shake_intensity")
option.setTooltip("interactive_stuff.config.menu.pack.shake_intensity.tooltip")
option.setCategory("interactive_stuff.config.menu.pack.category.animation")
option.setRange(0, 200, 5)
reply option
end
make compatibility = new Map
task hasMod takes id do
check !compatibility.containsKey(id) do
compatibility.put(id, modLoader.isModLoaded(id))
end
reply compatibility.get(id)
end
task createProgressState do
reply new Map
end
task smoothItemProgress takes state, item, target, speed do
make hand = "off"
check item.isMainHand() do make hand = "main" end
make frame = getFrameId()
make itemId = item.getName()
check !state.containsKey(hand + "Frame") do
state.put(hand + "Frame", -1)
state.put(hand + "Progress", 0)
state.put(hand + "Item", itemId)
end
check state.get(hand + "Item") != itemId || state.get(hand + "Frame") < (frame - 1) do
state.put(hand + "Progress", 0)
state.put(hand + "Item", itemId)
state.put(hand + "Frame", -1)
end
check state.get(hand + "Frame") != frame do
state.put(hand + "Progress", item.smooth(state.get(hand + "Progress"), target, speed))
state.put(hand + "Frame", frame)
end
reply state.get(hand + "Progress")
end
task resetItemProgress takes state, item do
make hand = "off"
check item.isMainHand() do make hand = "main" end
state.put(hand + "Progress", 0)
state.put(hand + "Frame", getFrameId())
state.put(hand + "Item", item.getName())
end
task isRedstonePowered do
reply player.isSneaking() && player.getSteppingBlock().getName() == "minecraft:redstone_block"
endenchanting_table.vyn135 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make particleOption = packToggle("particles_enchanting_table", "particles")
particleOption.setOnChange("onParticleOptionChanged")
make showBookOption = packToggle("show_enchanting_book", "appearance")
showBookOption.setOnChange("onBookOptionChanged")
make animateBookOption = packToggle("animate_enchanting_book", "animation")
animateBookOption.setOnChange("onBookOptionChanged")
lock interactiveItems = ["minecraft:enchanting_table"]
make openingState = createProgressState()
make openingProgress = 0
make bookshelfPosition = nothing
make glyphParticles = new ParticleEmitter("minecraft:enchant")
glyphParticles.setSpace("world")
glyphParticles.setPosition(0.5, 0.05, 0.69)
glyphParticles.setSpread(0.08, 0.04, 0.08)
glyphParticles.setLifetime(90)
glyphParticles.setSizeOverLife(0.055, 0.085, "easeOutSine")
glyphParticles.setOpacityOverLife(0, 0, "linear")
glyphParticles.addOpacityKeyframe(0.15, 0.85, "easeOutQuad")
glyphParticles.addOpacityKeyframe(0.7, 0.7, "linear")
glyphParticles.setColor(131, 131, 145)
glyphParticles.setAnimation("random", 1)
glyphParticles.setLight(15)
glyphParticles.setOnSpawn("drawGlyphFromBookshelf")
task drawGlyphFromBookshelf takes particle do
check bookshelfPosition == nothing do
particle.kill()
reply nothing
end
make targetX = particle.getX()
make targetY = particle.getY()
make targetZ = particle.getZ()
make centerX = bookshelfPosition.getX() + 0.5
make centerY = bookshelfPosition.getY() + 0.5
make centerZ = bookshelfPosition.getZ() + 0.5
make directionX = targetX - centerX
make directionY = targetY - centerY
make directionZ = targetZ - centerZ
make distanceX = max(directionX, -directionX)
make distanceY = max(directionY, -directionY)
make distanceZ = max(directionZ, -directionZ)
make sourceX = centerX + (random() - 0.5) * 0.7
make sourceY = centerY + (random() - 0.5) * 0.7
make sourceZ = centerZ + (random() - 0.5) * 0.7
check distanceX >= distanceY && distanceX >= distanceZ do
make sourceX = centerX + 0.51
check directionX < 0 do make sourceX = centerX - 0.51 end
otherwise
check distanceY >= distanceZ do
make sourceY = centerY + 0.51
check directionY < 0 do make sourceY = centerY - 0.51 end
otherwise
make sourceZ = centerZ + 0.51
check directionZ < 0 do make sourceZ = centerZ - 0.51 end
end
end
particle.setPosition(sourceX, sourceY, sourceZ)
make ticks = particle.getLifetime()
particle.setVelocity((targetX - sourceX) / ticks, (targetY - sourceY) / ticks, (targetZ - sourceZ) / ticks)
end
task syncParticleEmission do
check particleOption.getBoolean() && showBookOption.getBoolean() && animateBookOption.getBoolean() && bookshelfPosition != nothing && openingProgress > 0 do
glyphParticles.start()
otherwise
glyphParticles.stop()
end
end
task onParticleOptionChanged takes option, oldValue, newValue do
syncParticleEmission()
end
task onBookOptionChanged takes option, oldValue, newValue do
make openingState = createProgressState()
make openingProgress = 0
syncParticleEmission()
end
syncParticleEmission()
task onItemUpdate takes itemRendered do
check itemRendered.getName() != "minecraft:enchanting_table" do reply nothing end
check hasMod("punchy") do
itemRendered.translate(0, 0.2, 0)
itemRendered.scale(0.8, 0.8, 0.8)
end
make bookshelf = player.getNearestBlock("minecraft:bookshelf", 2)
make bookshelfPosition = nothing
make progress = 0
check bookshelf != nothing do
make bookshelfPosition = bookshelf.getPosition()
make progress = 100
end
check showBookOption.getBoolean() && animateBookOption.getBoolean() do
make openingProgress = smoothItemProgress(openingState, itemRendered, progress, 0.2)
otherwise
make openingProgress = 0
resetItemProgress(openingState, itemRendered)
end
glyphParticles.setRate(0.05 * (openingProgress / 100))
syncParticleEmission()
check !showBookOption.getBoolean() do
glyphParticles.attach(itemRendered)
reply nothing
end
make book_left = new ItemModel("minecraft:book")
make book_right = new ItemModel("minecraft:book")
setupBookHalf(book_left, itemRendered, "interactivestuff:book_left", 60)
setupBookHalf(book_right, itemRendered, "interactivestuff:book_right", -60)
glyphParticles.attach(book_left)
end
task setupBookHalf takes book, item, model, angle do
book.setParent(item)
make hingeX = -0.015625
check !item.isRightHand() do make hingeX = 0.015625 end
book.setPivot(hingeX, 0.13, 0)
make lookWeight = 0
check animateBookOption.getBoolean() do make lookWeight = 1 end
book.lookAt(bookshelfPosition, "enchanting_book", 0.16, lookWeight)
book.setLookAtClearance(0.125, -0.16, 0.09, -0.13, 0.16, 0.29, 0.13)
book.rotate(0, 0, angle * (openingProgress / 100))
book.setItemModel(model)
enditemframes.vyn62 linesimportScript("interactivestuff:interactive_resourcepack","physics_lib")
make framePhysicsOption = packToggle("physics_item_frames", "physics")
framePhysicsOption.setOnChange("onItemPhysicsChanged")
make paintingPhysicsOption = packToggle("physics_paintings", "physics")
paintingPhysicsOption.setOnChange("onItemPhysicsChanged")
make signPhysicsOption = packToggle("physics_hanging_signs", "physics")
signPhysicsOption.setOnChange("onItemPhysicsChanged")
task onItemPhysicsChanged takes option, previous, value do
resetPhysicsEngine()
end
lock interactiveItems = ["minecraft:item_frame", "minecraft:glow_item_frame", "minecraft:painting", "minecraft:oak_hanging_sign", "minecraft:spruce_hanging_sign", "minecraft:birch_hanging_sign", "minecraft:jungle_hanging_sign", "minecraft:acacia_hanging_sign", "minecraft:dark_oak_hanging_sign", "minecraft:crimson_hanging_sign", "minecraft:warped_hanging_sign", "minecraft:cherry_hanging_sign", "minecraft:mangrove_hanging_sign", "minecraft:pale_oak_hanging_sign", "minecraft:bamboo_hanging_sign"]
lock FRAME_ITEMS = new List
FRAME_ITEMS.add("minecraft:item_frame", "minecraft:glow_item_frame", "minecraft:painting", "minecraft:oak_hanging_sign", "minecraft:spruce_hanging_sign", "minecraft:birch_hanging_sign", "minecraft:jungle_hanging_sign", "minecraft:acacia_hanging_sign", "minecraft:dark_oak_hanging_sign", "minecraft:crimson_hanging_sign", "minecraft:warped_hanging_sign", "minecraft:cherry_hanging_sign", "minecraft:mangrove_hanging_sign", "minecraft:pale_oak_hanging_sign", "minecraft:bamboo_hanging_sign")
task onItemUpdate takes itemRendered do
check player.getGamemode() != "spectator" && isFrame(itemRendered) do
check !hasMod("holdmyitems") do
itemRendered.setPivot(0, 0.4, 0)
check isPhysicsEnabled(itemRendered) do
runPhysicsEngine(0.01, 0.1, 0.6, 0.3, 0.2, 0.8, 60, 0)
itemRendered.rotate(angleX, 0, -angleZ)
end
check itemRendered.isRightHand() do
check !hasMod("punchy") do
itemRendered.rotateY(65)
itemRendered.rotateX(25)
end
otherwise
check !hasMod("punchy") do
itemRendered.rotateY(-65)
itemRendered.rotateX(25)
end
end
check hasMod("punchy") do
itemRendered.translate(0,-0.6,0)
end
end
end
end
task isFrame takes item do
reply FRAME_ITEMS.contains(item.getName())
end
task isPhysicsEnabled takes item do
check !masterPhysicsOption.getBoolean() do reply false end
check item.getName() == "minecraft:item_frame" || item.getName() == "minecraft:glow_item_frame" do
reply framePhysicsOption.getBoolean()
end
check item.getName() == "minecraft:painting" do
reply paintingPhysicsOption.getBoolean()
end
reply signPhysicsOption.getBoolean()
endleaves.vyn23 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make effectOption = packToggle("tint_blocks", "appearance")
lock interactiveItems = ["minecraft:grass_block", "minecraft:oak_leaves", "minecraft:spruce_leaves", "minecraft:jungle_leaves", "minecraft:acacia_leaves", "minecraft:dark_oak_leaves"]
task onItemUpdate takes itemRendered do
check effectOption.getBoolean() && player.getGamemode() != "spectator" do
check isItemleaves(itemRendered) do
itemRendered.setItemModel(itemRendered.getName())
itemRendered.setTint(0,player.getWorld().getFoliageColor(player.getSteppingBlock().getPosition()))
end
check itemRendered.getName() == "minecraft:grass_block" do
itemRendered.setItemModel(itemRendered.getName())
itemRendered.setTint(0,player.getWorld().getGrassColor(player.getSteppingBlock().getPosition()))
end
end
end
task isItemleaves takes item do
reply item.getName() == "minecraft:oak_leaves" || item.getName() == "minecraft:spruce_leaves" || item.getName() == "minecraft:jungle_leaves" || item.getName() == "minecraft:acacia_leaves" || item.getName() == "minecraft:dark_oak_leaves"
endmace.vyn44 linesimportScript("interactivestuff:interactive_resourcepack","physics_lib")
make physicsOption = packToggle("physics_mace", "physics")
physicsOption.setOnChange("onMacePhysicsChanged")
masterPhysicsOption.setOnChange("onMacePhysicsChanged")
make shakeOption = packShakeOption()
lock interactiveItems = ["minecraft:mace"]
make smoothFallLean = 0
make fallLeanState = createProgressState()
task resetMacePhysics do
resetPhysicsEngine()
make smoothFallLean = 0
check fallLeanState.size() > 0 do make fallLeanState = createProgressState() end
end
task onMacePhysicsChanged takes option, previous, value do
resetMacePhysics()
end
task onItemUpdate takes itemRendered do
check !masterPhysicsOption.getBoolean() || !physicsOption.getBoolean() do
resetMacePhysics()
reply nothing
end
check player.getGamemode() != "spectator" && itemRendered.getName() == "minecraft:mace" && !hasMod("punchy") do
runPhysicsEngine(0.01, 0.2, 0.1, 0.2, 0.4, 1.0, 45, 0)
make targetLean = player.getVelocityY() * -20
make smoothFallLean = smoothItemProgress(fallLeanState, itemRendered, targetLean, 0.5)
itemRendered.setPivot(0, -0.4, 0)
itemRendered.rotateX(angleX + smoothFallLean)
itemRendered.rotateZ(angleZ)
itemRendered.translate(((random() - 0.5) * smoothFallLean / 5000 * shakeOption.getNumber() / 100), ((random() - 0.5) * smoothFallLean / 5000 * shakeOption.getNumber() / 100), 0)
end
endnote_block.vyn95 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make particleOption = packToggle("particles_note_block", "particles")
particleOption.setOnChange("onParticleOptionChanged")
make noteSoundOption = packToggle("note_block_sounds", "sounds")
lock interactiveItems = ["minecraft:note_block"]
make wasSneaking = false
make pitchIndex = -1
make notePitch = 0.5
lock NOTE_SPAWN_Y = 1.05
lock NOTE_RISE = 0.5
lock song_pattern = new List
song_pattern.add(0.5,0.5,0.5,0.5,0.75,0.6,0.6,0.6,0.75,0.6,0.8)
make noteParticle = new ParticleEmitter("minecraft:note")
noteParticle.setPosition(0.5, NOTE_SPAWN_Y, 0.5)
noteParticle.setSpread(0.15, 0, 0.15)
noteParticle.setLifetime(16)
noteParticle.setRate(0)
noteParticle.setSize(0.14)
noteParticle.setSpace("world")
noteParticle.setOnSpawn("colorNoteParticle")
noteParticle.setOnUpdate("riseNoteParticle")
task syncParticleEmission do
check particleOption.getBoolean() do
noteParticle.start()
otherwise
noteParticle.stop()
end
end
task onParticleOptionChanged takes option, oldValue, newValue do
syncParticleEmission()
end
syncParticleEmission()
task colorNoteParticle takes particle do
make normalizedPitch = max(0, min(1, (notePitch - 0.5) / 1.5))
make red = int(max(0, sin(normalizedPitch * 6.283185307) * 0.65 + 0.35) * 255)
make green = int(max(0, sin((normalizedPitch + 0.333333333) * 6.283185307) * 0.65 + 0.35) * 255)
make blue = int(max(0, sin((normalizedPitch + 0.666666667) * 6.283185307) * 0.65 + 0.35) * 255)
particle.setColor(red, green, blue)
end
task riseNoteParticle takes particle do
make remaining = 1 - particle.getProgress()
make eased = 1 - remaining * remaining * remaining
particle.setPosition(particle.getX(), particle.getSpawnY() + NOTE_RISE * eased, particle.getZ())
end
task onItemUpdate takes itemRendered do
syncParticleEmission()
noteParticle.attach(itemRendered)
end
task onTick do
check player.getWorld() == nothing do
reply nothing
end
check player.getGamemode() != "spectator" do
make isSneaking = player.isSneaking()
check player.getSteppingBlock().getName() == "minecraft:redstone_block" && player.isHoldingItem("minecraft:note_block") && isSneaking && !wasSneaking do
check pitchIndex < (song_pattern.size() - 1) do
make pitchIndex = pitchIndex + 1
otherwise
make pitchIndex = 0
end
make notePitch = song_pattern.get(pitchIndex)
check noteSoundOption.getBoolean() do
player.playSound("minecraft:block.note_block.harp", 0.5, notePitch)
end
check particleOption.getBoolean() do
noteParticle.burst(1)
end
end
make wasSneaking = isSneaking
end
end
task onSwingHand do
check noteSoundOption.getBoolean() do
check player.getGamemode() != "spectator" && player.getGamemode() != "adventure" && player.isHoldingItem("minecraft:note_block") && player.getTargetBlock() != nothing do
make targetBlock = player.getTargetBlock()
player.playSoundWorld(targetBlock.getPosition(), targetBlock.getInstrument(), 0.2, 1.0)
end
end
endphysics_lib.vyn119 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make masterPhysicsOption = packToggle("physics_enabled", "physics")
masterPhysicsOption.setOnChange("onMasterPhysicsChanged")
make angleX = 0
make angleZ = 0
make velX = 0
make velZ = 0
make prevCamPitch = 0
make prevCamYaw = 0
make prevMoveX = 0
make prevMoveY = 0
make prevMoveZ = 0
make isFirstFrame = 1
make lastUpdateFrame = -1
make lastUpdateTime = 0
task runPhysicsEngine takes stiffness, damping, moveRes, lookRes, vertRes, inertial, maxAngle, windMult do
check !masterPhysicsOption.getBoolean() do
resetPhysicsEngine()
reply 0
end
make now = getFrameId()
check lastUpdateFrame == now do
reply 0
end
make dt = getDelta()
make nowTime = time()
check (lastUpdateFrame >= 0 && (now - lastUpdateFrame) > 1) || (lastUpdateTime > 0 && ((nowTime - lastUpdateTime) > 250 || nowTime < lastUpdateTime)) do
resetPhysicsEngine()
end
make lastUpdateFrame = now
make lastUpdateTime = nowTime
check dt <= 0 do
make isFirstFrame = 1
reply 0
end
make currCamPitch = player.getCameraPitchVelocity()
make currCamYaw = player.getCameraYawVelocity()
make currMoveX = player.getVelocityX()
make currMoveY = player.getVelocityY()
make currMoveZ = -player.getVelocityZ()
check isFirstFrame == 1 do
make prevCamPitch = currCamPitch
make prevCamYaw = currCamYaw
make prevMoveX = currMoveX
make prevMoveY = currMoveY
make prevMoveZ = currMoveZ
make isFirstFrame = 0
end
make dYaw = currCamYaw - prevCamYaw
check dYaw > 180 do make dYaw = dYaw - 360 end
check dYaw < -180 do make dYaw = dYaw + 360 end
make dPitch = currCamPitch - prevCamPitch
make accX = (currMoveX - prevMoveX) * moveRes
make accZ = (currMoveZ - prevMoveZ) * moveRes
make accY = (currMoveY - prevMoveY) * vertRes
make windForceX = 0
make windForceZ = 0
check windMult != 0 do
make windVal = sin(nowTime * 0.0015)
make gustVal = sin(nowTime * 0.004)
make envVal = sin(nowTime * 0.0008) * 0.5 + 0.5
make envVal = envVal * envVal
make windForceX = (windVal * 0.02 + gustVal * 0.04 * envVal) * windMult * inertial
make windForceZ = (windVal * 0.02 * 0.6 - gustVal * 0.04 * envVal * 0.4) * windMult * inertial
end
make impulseX = ((dPitch * lookRes) + (accZ * 10.0) + (accY * 5.0)) * inertial
make impulseZ = ((dYaw * lookRes) + (accX * 10.0)) * inertial
make steps = int(dt)
check steps < dt do make steps = steps + 1 end
make stepDelta = dt / steps
cycle step from 1 to steps do
make springDampX = (0 - angleX * stiffness) - (velX * damping)
make springDampZ = (0 - angleZ * stiffness) - (velZ * damping)
make velX = velX + (springDampX + windForceX) * stepDelta
make velZ = velZ + (springDampZ + windForceZ) * stepDelta
check step == 1 do
make velX = velX + impulseX
make velZ = velZ + impulseZ
end
make angleX = angleX + velX * stepDelta
make angleZ = angleZ + velZ * stepDelta
check angleX > maxAngle do make angleX = maxAngle make velX = velX * -0.5 end
check angleX < -maxAngle do make angleX = -maxAngle make velX = velX * -0.5 end
check angleZ > maxAngle do make angleZ = maxAngle make velZ = velZ * -0.5 end
check angleZ < -maxAngle do make angleZ = -maxAngle make velZ = velZ * -0.5 end
end
make prevCamPitch = currCamPitch
make prevCamYaw = currCamYaw
make prevMoveX = currMoveX
make prevMoveY = currMoveY
make prevMoveZ = currMoveZ
end
task resetPhysicsEngine do
make angleX = 0
make angleZ = 0
make velX = 0
make velZ = 0
make isFirstFrame = 1
make lastUpdateFrame = -1
make lastUpdateTime = 0
end
task onMasterPhysicsChanged takes option, previous, value do
resetPhysicsEngine()
endpistons.vyn61 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make animationOption = packToggle("animate_pistons", "animation")
animationOption.setOnChange("onAnimationChanged")
lock interactiveItems = ["minecraft:piston", "minecraft:sticky_piston"]
lock pistonExtensions = new Map
pistonExtensions.put("minecraft:piston", 0.25)
pistonExtensions.put("minecraft:sticky_piston", 0.275)
make wasSneaking = false
make isSneaking = false
make wasOnRedstone = false
make isOnRedstone = false
make extensionState = createProgressState()
task onAnimationChanged takes option, previous, value do
make extensionState = createProgressState()
end
task onTick do
check !animationOption.getBoolean() do reply nothing end
check player.getWorld() == nothing do reply nothing end
make isSneaking = player.isSneaking()
make isOnRedstone = player.getSteppingBlock().getName() == "minecraft:redstone_block"
check (player.isHoldingItem("minecraft:piston") || player.isHoldingItem("minecraft:sticky_piston")) && player.isFirstPerson() do
check isOnRedstone && isSneaking && (!wasOnRedstone || !wasSneaking) do
player.playSound("minecraft:block.piston.extend", 0.5, 1)
end
check (isOnRedstone && !isSneaking && wasSneaking) || (!isOnRedstone && wasOnRedstone && wasSneaking) do
player.playSound("minecraft:block.piston.contract", 0.5, 1)
end
end
make wasSneaking = isSneaking
make wasOnRedstone = isOnRedstone
end
task onItemUpdate takes itemRendered do
check !animationOption.getBoolean() do reply nothing end
check !player.isFirstPerson() do reply nothing end
make itemId = itemRendered.getName()
make extension = pistonExtensions.get(itemId)
check extension == nothing do reply nothing end
check hasMod("punchy") do
itemRendered.translate(0, 0.18, 0)
itemRendered.scale(0.9, 0.9, 0.9)
end
itemRendered.setItemModel("interactivestuff:piston_base")
make pistonTop = new ItemModel(itemId)
pistonTop.setItemModel("interactivestuff:" + replace(itemId, "minecraft:", "") + "_top")
pistonTop.setParent(itemRendered)
make target = 0
make vy = player.getVelocityY()
check vy < -0.1 do make target = min(100, vy * -100) end
check isOnRedstone && isSneaking do make target = 100 end
make progress = smoothItemProgress(extensionState, itemRendered, target, 0.45)
pistonTop.translate(0, extension * (progress / 100), 0)
endredstone_items.vyn17 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make lampOption = packToggle("animate_redstone_lamp", "animation")
lock interactiveItems = ["minecraft:redstone_lamp", "minecraft:redstone_torch"]
task onItemUpdate takes itemRendered do
check player.getGamemode() != "spectator" do
check lampOption.getBoolean() && itemRendered.getName() == "minecraft:redstone_lamp" && isRedstonePowered() do
itemRendered.setItemModel("interactivestuff:redstone_lamp_on")
itemRendered.setLight(15)
end
check itemRendered.getName() == "minecraft:redstone_torch" && isRedstonePowered() do
itemRendered.setItemModel("interactivestuff:redstone_torch_off")
end
end
endsapling.vyn23 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make effectOption = packToggle("tint_saplings", "appearance")
lock interactiveItems = ["minecraft:oak_sapling", "minecraft:spruce_sapling", "minecraft:jungle_sapling", "minecraft:acacia_sapling", "minecraft:dark_oak_sapling"]
task onItemUpdate takes itemRendered do
check effectOption.getBoolean() && player.getGamemode() != "spectator" do
check isItemSapling(itemRendered) do
make name = replace(itemRendered.getName(),"minecraft:","")
itemRendered.setItemModel("interactivestuff:" + name + "_wood")
make saplingLeaves = new ItemModel("minecraft:oak_sapling")
saplingLeaves.setItemModel("interactivestuff:" + name + "_leaves")
saplingLeaves.setTint(0,player.getWorld().getFoliageColor(player.getSteppingBlock().getPosition()))
end
end
end
task isItemSapling takes item do
reply item.getName() == "minecraft:oak_sapling" || item.getName() == "minecraft:spruce_sapling" || item.getName() == "minecraft:jungle_sapling" || item.getName() == "minecraft:acacia_sapling" || item.getName() == "minecraft:dark_oak_sapling"
endsculk_sensors.vyn168 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make particleOption = packToggle("particles_sculk_sensor", "particles")
particleOption.setOnChange("onParticleOptionChanged")
make shakeOption = packShakeOption()
make sculkEnabledOption = packToggle("animate_sculk_sensor", "animation")
sculkEnabledOption.setOnChange("onSculkOptionChanged")
lock interactiveItems = ["minecraft:sculk_sensor", "minecraft:calibrated_sculk_sensor"]
lock RANGE_NORMAL = 8
lock RANGE_CALIBRATED = 16
lock COOLDOWN_NORMAL = 40
lock COOLDOWN_CALIBRATED = 20
lock IGNORED_SOUND_IDS = new List
IGNORED_SOUND_IDS.add("minecraft:block.sculk_sensor.clicking", "minecraft:block.sculk_sensor.clicking_stop", "minecraft:block.wool.fall", "minecraft:block.wool.break", "minecraft:block.wool.place", "minecraft:block.wool.step", "minecraft:block.wool.hit")
task createSensorState do
make state = new Map
state.put("item", "")
state.put("cooldown", 0)
state.put("pulse", 0)
reply state
end
make mainSensor = createSensorState()
make offSensor = createSensorState()
make wasOnGround = false
make sculkParticles = new ParticleEmitter("minecraft:smoke")
sculkParticles.setPosition(0.5, 0.7, 0.5)
sculkParticles.setSpread(0.28, 0.06, 0.28)
sculkParticles.setLifetime(16)
sculkParticles.setRate(0)
sculkParticles.setVelocity(0, 0.01, 0)
sculkParticles.setVelocitySpread(0.012, 0.004, 0.012)
sculkParticles.setSizeOverLife(0.025, 0.065, "easeOutCubic")
sculkParticles.setOpacityOverLife(0.9, 0, "easeInQuad")
sculkParticles.setLight(15)
sculkParticles.setSpace("world")
sculkParticles.setColor(27,111,117)
sculkParticles.setColorOverLife(27,111,117, 255, 0, 10, "easeInQuad")
task syncParticleEmission do
check particleOption.getBoolean() && sculkEnabledOption.getBoolean() do
sculkParticles.start()
otherwise
sculkParticles.stop()
end
end
task onParticleOptionChanged takes option, oldValue, newValue do
syncParticleEmission()
end
task resetSensor takes state do
check state.get("item") == "" do reply nothing end
state.put("item", "")
state.put("cooldown", 0)
state.put("pulse", 0)
end
task onSculkOptionChanged takes option, oldValue, newValue do
resetSensor(mainSensor)
resetSensor(offSensor)
syncParticleEmission()
end
task syncSensorItem takes state, itemId do
check state.get("item") != itemId do
state.put("item", itemId)
state.put("cooldown", 0)
state.put("pulse", 0)
end
end
task isHoldingSensor do
reply player.isHoldingItem("minecraft:sculk_sensor") || player.isHoldingItem("minecraft:calibrated_sculk_sensor")
end
task updateCooldown takes state do
state.put("pulse", max(0, state.get("pulse") - 1))
make cooldown = state.get("cooldown")
check cooldown <= 0 do reply false end
state.put("cooldown", cooldown - 1)
reply cooldown == 1
end
task onTick do
check !sculkEnabledOption.getBoolean() do reply nothing end
make isOnGround = player.isOnGround()
check player.getGamemode() == "spectator" || !player.isFirstPerson() || !isHoldingSensor() do
resetSensor(mainSensor)
resetSensor(offSensor)
make wasOnGround = isOnGround
reply nothing
end
syncSensorItem(mainSensor, player.getMainHandItem().getName())
syncSensorItem(offSensor, player.getOffHandItem().getName())
make mainEnded = updateCooldown(mainSensor)
make offEnded = updateCooldown(offSensor)
check mainEnded || offEnded do
player.playSound("minecraft:block.sculk_sensor.clicking_stop", 1.0, 1.0)
end
check !wasOnGround && isOnGround && !player.isSneaking() && !player.getSteppingBlock().hasBlockTag("wool") do
processVibration(player.getPosition())
end
make wasOnGround = isOnGround
end
task onPlaySound takes sound do
check !sculkEnabledOption.getBoolean() do reply nothing end
check player.getGamemode() == "spectator" || !player.isFirstPerson() || !isHoldingSensor() do reply nothing end
check !IGNORED_SOUND_IDS.contains(sound.getName()) do
processVibration(sound.getPosition())
end
end
task activateSensor takes state, mainHand, distance do
check state.get("cooldown") > 0 do reply false end
make itemId = state.get("item")
make range = RANGE_NORMAL
make cooldown = COOLDOWN_NORMAL
check itemId == "minecraft:calibrated_sculk_sensor" do
make range = RANGE_CALIBRATED
make cooldown = COOLDOWN_CALIBRATED
otherwise
check itemId != "minecraft:sculk_sensor" do reply false end
end
check distance > range do reply false end
state.put("cooldown", cooldown)
state.put("pulse", 5)
check particleOption.getBoolean() do sculkParticles.burstForHand(mainHand, 6) end
reply true
end
task processVibration takes position do
syncSensorItem(mainSensor, player.getMainHandItem().getName())
syncSensorItem(offSensor, player.getOffHandItem().getName())
make distance = player.getPosition().getDistanceTo(position)
make mainActivated = activateSensor(mainSensor, true, distance)
make offActivated = activateSensor(offSensor, false, distance)
check mainActivated || offActivated do
player.playSound("minecraft:block.sculk_sensor.clicking", 1.0, 1.0)
end
end
task onItemUpdate takes itemRendered do
check !sculkEnabledOption.getBoolean() || player.getGamemode() == "spectator" do reply nothing end
make state = offSensor
check itemRendered.isMainHand() do make state = mainSensor end
make itemId = itemRendered.getName()
syncSensorItem(state, itemId)
syncParticleEmission()
sculkParticles.attach(itemRendered)
check state.get("cooldown") > 0 do
check itemId == "minecraft:sculk_sensor" do
itemRendered.setItemModel("interactivestuff:sculk_sensor_active")
otherwise
itemRendered.setItemModel("interactivestuff:calibrated_sculk_sensor_active")
end
make intensity = 0
check state.get("pulse") > 0 do make intensity = 0.02 * shakeOption.getNumber() / 100 end
itemRendered.translate((random() - 0.5) * intensity, (random() - 0.5) * intensity, 0)
itemRendered.setLight(15)
end
end
syncParticleEmission()torches_and_more.vyn85 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make shakeOption = packShakeOption()
make effectOption = packToggle("torch_extinguish", "animation")
effectOption.setOnChange("onTorchOptionChanged")
lock interactiveItems = ["minecraft:campfire", "minecraft:torch", "minecraft:redstone_torch", "minecraft:soul_campfire", "minecraft:soul_torch", "minecraft:wall_torch", "minecraft:copper_torch"]
lock HOT_ITEMS = new List
HOT_ITEMS.add("minecraft:campfire", "minecraft:torch", "minecraft:redstone_torch", "minecraft:soul_campfire", "minecraft:soul_torch", "minecraft:wall_torch", "minecraft:copper_torch")
make wasSubmerged = false
make intensity = 0.0
task onTorchOptionChanged takes option, previous, value do
make wasSubmerged = nothing
make intensity = 0
end
task onTick do
check !effectOption.getBoolean() do reply nothing end
make isSubmerged = player.isSubmergedInWater()
check player.getGamemode() != "spectator" && player.isFirstPerson() && wasSubmerged != nothing && wasSubmerged != isSubmerged do
check isPlayerHoldingAnyHotItem() do
check isSubmerged do
player.playSound("minecraft:block.fire.extinguish", 0.6, 1.0)
make intensity = 0.015
otherwise
player.playSound("minecraft:item.flintandsteel.use", 0.6, 1.0)
end
end
end
make wasSubmerged = isSubmerged
make intensity = max(0, intensity - 0.001)
end
task onItemUpdate takes itemRendered do
check effectOption.getBoolean() && player.getGamemode() != "spectator" do
check player.isSubmergedInWater() do
make isTheItem = false
check isWaterTorch(itemRendered) && itemRendered.getName() != "minecraft:redstone_torch" do
itemRendered.setItemModel("interactivestuff:torch_off")
make isTheItem = true
end
check itemRendered.getName() == "minecraft:redstone_torch" do
itemRendered.setItemModel("interactivestuff:redstone_torch_off")
make isTheItem = true
end
check isWaterCampFire(itemRendered) do
itemRendered.setItemModel("interactivestuff:campfire_off")
make isTheItem = true
end
check isTheItem do
itemRendered.translate(((random() - 0.5) * intensity * shakeOption.getNumber() / 100), ((random() - 0.5) * intensity * shakeOption.getNumber() / 100), 0)
end
otherwise
check isHoldingHotItem(itemRendered) do
check itemRendered.getName() != "minecraft:redstone_torch" || !isRedstonePowered() do
itemRendered.setLight(15)
end
end
end
end
end
task isHoldingHotItem takes itemRendered do
reply HOT_ITEMS.contains(itemRendered.getName())
end
task isPlayerHoldingAnyHotItem do
reply HOT_ITEMS.contains(player.getMainHandItem().getName()) || HOT_ITEMS.contains(player.getOffHandItem().getName())
end
task isWaterTorch takes itemHeld do
make id = itemHeld.getName()
reply id == "minecraft:torch" || id == "minecraft:redstone_torch" || id == "minecraft:soul_torch" || id == "minecraft:copper_torch"
end
task isWaterCampFire takes itemHeld do
make id = itemHeld.getName()
reply id == "minecraft:campfire" || id == "minecraft:soul_campfire"
endtotem.vyn14 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make shakeOption = packShakeOption()
lock interactiveItems = ["minecraft:totem_of_undying"]
task onItemUpdate takes itemRendered do
check player.getGamemode() != "spectator" && itemRendered.getName() == "minecraft:totem_of_undying" do
make intensity = max(0, (20 - player.getHealth()) / 10)
itemRendered.translate(((random() - 0.5) * intensity / 250 * shakeOption.getNumber() / 100), ((random() - 0.5) * intensity / 250 * shakeOption.getNumber() / 100), 0)
itemRendered.rotateAxis(((random() - 0.5) * intensity / 250 * shakeOption.getNumber() / 100), 1,1,1)
end
endvault.vyn56 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make effectOption = packToggle("animate_vault", "animation")
lock interactiveItems = ["minecraft:vault"]
lock lootItems = new List
lootItems.add("minecraft:wind_charge","minecraft:emerald","minecraft:iron_ingot","minecraft:diamond","minecraft:ominous_bottle","minecraft:honey_bottle","minecraft:golden_apple","minecraft:golden_carrot","minecraft:enchanted_book")
lock cooldown = 2000
make lastChangeTime = 0
make currentLootItem = nothing
task getRandomItem do
reply lootItems.get(random(0, lootItems.size() - 1))
end
task onItemUpdate takes itemRendered do
check effectOption.getBoolean() && player.getGamemode() != "spectator" do
check itemRendered.getName() == "minecraft:vault" do
check hasMod("punchy") do
itemRendered.translate(0,0,0)
otherwise
itemRendered.translate(0, 0.2, 0)
end
make now = time()
check currentLootItem == nothing do
make currentLootItem = getRandomItem()
make lastChangeTime = now
end
check (now - lastChangeTime) >= cooldown do
make currentLootItem = getRandomItem()
make lastChangeTime = now
end
make lootModel = new ItemModel(currentLootItem)
check itemRendered.isRightHand() do
lootModel.setPivot(0.02, 0.05, 0.02)
lootModel.translate(-0.05, 0.15, 0)
otherwise
lootModel.setPivot(-0.02, 0.05, 0.02)
lootModel.translate(0.05, 0.15, 0)
end
check hasMod("punchy") do
lootModel.translate(0, -0.22, 0)
end
lootModel.scale(0.3, 0.3, 0.3)
lootModel.rotateAxis((now * 0.25) % 360, 0, 1, 0)
lootModel.rotateX(25)
end
end
endwater_bucket.vyn21 linesimportScript("interactivestuff:interactive_resourcepack", "effect_helpers")
make effectOption = packToggle("tint_water", "appearance")
make animationOption = packToggle("animate_water_bucket", "animation")
lock interactiveItems = ["minecraft:water_bucket"]
task onItemUpdate takes itemRendered do
check !effectOption.getBoolean() && !animationOption.getBoolean() do reply nothing end
check player.getGamemode() == "spectator" || itemRendered.getName() != "minecraft:water_bucket" do reply nothing end
check animationOption.getBoolean() && player.isSubmergedInWater() do
itemRendered.setItemModel("minecraft:bucket")
reply nothing
end
check !effectOption.getBoolean() do reply nothing end
itemRendered.setItemModel("interactivestuff:bucket")
make waterOfBucket = new ItemModel("minecraft:bucket")
waterOfBucket.setItemModel("interactivestuff:water_of_the_bucket")
waterOfBucket.setTint(0, player.getWorld().getWaterColor(player.getSteppingBlock().getPosition()))
endIf Mod Menu is installed, the separate Options entry is intentionally hidden. Open the mod’s Configure screen from Mod Menu, or assign the optional settings keybind.
Check the enabled pack, the exact assets/interactivestuff/scripts/ path, the .vyn extension and latest.log. Check interactiveItems against the actual held item ID. Reload with F3+T after changes.
Use the real pack ID, include file/ for local folder/ZIP packs, omit .vyn from the script name, and keep the providing pack enabled. Imported libraries must not define automatic event tasks.
Declare ConfigOption and call its schema setters at load time, not inside an event. Check for conflicting duplicate schemas, invalid defaults or a missing callback task. Then reload resources.
new ItemModel and copy enqueue additional models. To replace the current held appearance, call setItemModel on itemRendered in its render event.
Use setTint(0, world.getGrassColor(position)) on a model whose grass faces have tintindex 0. A whole-model RGB multiplier also colors the dirt.
Check the pack’s tint option, global Color changes, tint indices, and whether the script uses the foliage resolver. Confirm you are using the correct target JAR and active custom model. The global getBiomeColorAt alias means foliage, not all color types.
Use setSpace("world") if particles should stay where they were born. setAttached(false) selects view space instead.
Use setRate(0) plus a burst in the action event. A burst inside onItemUpdate will repeat every render frame. stop stops births; clear removes already living particles.
Check the global particle switch/density/cap, the pack emission switch, first-person view, emitter enabled state and per-frame attach. Confirm its item filter and texture path. The enchanting effect also needs a visible animated book and a nearby bookshelf.
Global density scales bursts too, the active cap can drop births, pending counts clamp to 128 per hand, and only attached active hands can spawn.
Store progress per logical hand and item, or guard simulation with getFrameId. Repeatedly updating one global number in both render calls advances it twice.
onKeyPress is for gameplay key input while no screen is open. Check the integer key code. It is not a GUI character-typing hook.
That target uses a limited legacy mapping. Unsupported modern component IDs are rejected; use a supported legacy key/nbt:TagName and test the target.
Some rendering mods bypass vanilla render paths, and bundled scripts also have explicit installed-mod checks. Partial visual overlap is not proof of full compatibility. Test the matching target and toggles; consult the scripts before combining effects.
The repository is an all-in-one Gradle project. Open its root in the IDE. Shared production code and resources live in src/main/; version-specific adapters live in versions/<profile>/src/. A version override with the same path wins over the inherited file, so a root edit reaches every target that does not override it.
The profile chain is defined in the version properties. The 26.1 patch modules reuse the 26.1.X profile with their own patch dependencies. Treat generated files in build/ as outputs; edit the source roots instead.
./gradlew commands
./gradlew prepareIde
./gradlew buildSelected
./gradlew runSelected -Ptarget_version=26.3
./gradlew buildAll
./gradlew checkAll
./gradlew releaseAll| Minecraft | Build | Run client | Generate IDE game sources |
|---|---|---|---|
| 1.20.1 | build1_20_1 | run1_20_1 | sources1_20_1 |
| 1.21.1 | build1_21_1 | run1_21_1 | sources1_21_1 |
| 1.21.5 | build1_21_5 | run1_21_5 | sources1_21_5 |
| 1.21.10 | build1_21_10 | run1_21_10 | sources1_21_10 |
| 1.21.11 | build1_21_11 | run1_21_11 | sources1_21_11 |
| 26.1 | build26_1 | run26_1 | sources26_1 |
| 26.1.1 | build26_1_1 | run26_1_1 | sources26_1_1 |
| 26.1.2 | build26_1_2 | run26_1_2 | sources26_1_2 |
| 26.2 | build26_2 | run26_2 | sources26_2 |
| 26.3 | build26_3 | run26_3 | sources26_3 |
Per-target tasks also work with qualified paths, such as ./gradlew :1.20.1:build. Windows users can use gradlew.bat in place of ./gradlew.
releaseAll collects the ten checked release JARs and checksums into build/dist/0.8.0/ and creates build/dist/InteractiveStuff-0.8.0-all-versions.zip. It does not publish. Local developer docs/tests are excluded from the mod JARs and release ZIP.
Where local client-test fixtures are present, testAll or a version task such as test26_3 runs graphical client checks sequentially and needs a display. Those fixtures were deliberately kept local and are not a promise that a fresh public checkout includes every local test source. Ordinary build/check tasks include the checks available to that checkout.
previewPublish prepares a dry-run plan. publishAll performs real uploads to configured Modrinth/CurseForge projects with credentials; run it only when you intend to release. It reads root changelog.md by default, or -Pchangelog_file=/path/to/notes.md. The full changelog goes on 26.3 by default; other uploads contain a short reference. -Pchangelog_target changes the full-notes target.
Publishing settings include release_type (release/beta/alpha), publish_platforms and publish_dry_run=true. Credentials use MODRINTH_TOKEN and CURSEFORGE_TOKEN from the environment or private Gradle properties. This documentation build performs no uploads.
Prepared for InteractiveStuff 0.8.0 from the local source on 30 October 2026. The original wiki provided the type-by-type organization; current annotations, implementations, settings schemas and bundled scripts determined the API and feature coverage.
This file embeds its styles, scripts, mod icon and reading fonts. No CDN, network fetch, account or installation is needed to read it. External source/download links naturally require a connection. You can print it or save it as PDF through your browser.
InteractiveStuff by OmarDotContent. Mod artwork is the project’s existing icon. Embedded Noto Sans / Noto Sans Display fonts are by the Noto project, licensed under the SIL Open Font License 1.1; the license is included in this file. Minecraft names describe integration with Minecraft Java Edition; this is community documentation.
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Noto Upstream-Contact: https://github.com/googlei18n/noto-fonts/issues http://groups.google.com/group/noto-font Source: https://github.com/googlei18n/noto-fonts Files: * Copyright: 2010,2012-2020, Google Inc. 2015-2020, Google LLC. License-Grant: This Font Software is licensed under the SIL Open Font License, Version 1.1. License: OFL-1.1 Files: debian/* Copyright: 2013-2020, Jonas Smedegaard <dr@jones.dk> 2020, Purism, SPC 2013, Vasudev Kamath <kamathvasudev@gmail.com> License-Grant: This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. License: GPL-3+ Files: debian/NotoMono/NotoMono-Regular.ttf Copyright: 2007, Google Inc. License-Grant: This Font Software is licensed under the SIL Open Font License, Version 1.1. License: OFL-1.1 License: OFL-1.1 PREAMBLE . The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. . The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. . DEFINITIONS . "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. . "Reserved Font Name" refers to any names specified as such after the copyright statement(s). . "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). . "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. . "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. . PERMISSION & CONDITIONS . Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: . 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. . 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. . 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. . 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. . 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. . TERMINATION . This license becomes null and void if any of the above conditions are not met. . DISCLAIMER . THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. License: GPL-3+ License-Reference: /usr/share/common-licenses/GPL-3