Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<img src="src/main/resources/assets/itemtweaks/icon.png" alt="Swing icon" width="128" height="128">
<img src="src/main/resources/assets/swing/icon.png" alt="Swing icon" width="128" height="128">
</p>

<h1 align="center">Swing</h1>
Expand All @@ -14,18 +14,31 @@
<a href="LICENSE"><img src="https://img.shields.io/badge/License-CC0%201.0-lightgrey?style=flat-square" alt="License CC0 1.0"></a>
</p>

Client-only Fabric mod for Minecraft 26.2. Scales down the item in your first-person hand and lets you slow the swing animation. Nothing on the server changes, so this is visual only.
Client-only Fabric mod for Minecraft 26.2. Tweaks your first-person viewmodel — item scale, swing speed, positional offsets, and tilt. Nothing server-side changes.

I made this because the usual "viewmodel" skyblock mods come packed with a pile of extra features I already get from other mods.

## Settings

In game, run `/swing`. That opens a dark settings panel with sliders and a number box for each value (0.10–1.00, step 0.01). Defaults are vanilla `1.00` / `1.00`. Values apply live, save to `config/swing.json` on Apply or Close, and reload next launch.
Run `/swing` in game. A scrollable dark settings panel opens with sliders and number boxes for every value. Changes apply live, save to `config/swing.json` on close, and reload on next launch. All defaults are vanilla.

- Held item scale: size of the first-person held item. `1.00` is vanilla.
- Swing speed: arm swing animation. `1.00` is vanilla; lower is slower.
### Swing speed
- **Swing speed** (`1.00` = vanilla, lower is slower) — visual only, no server-side combat change
- **Ignore Haste** toggle — when ON, the animation ignores haste / mining fatigue so swing speed stays constant across gear sets and islands

Scaling does not apply in third person / F5.
### Held item scale
- **Held item scale** (`1.00` = vanilla) — scales the first-person item model
- **Apply Hand Scale** toggle — when ON, also scales the bare arm mesh when holding nothing

### Item offsets & tilt
- **Item X / Y / Z** — positional offset for the held item model (`-1.00` to `1.00`)
- **Item Pitch / Roll** — X and Z rotation for the held item (`-90` to `90°`)

### Arm offsets & tilt (requires Apply Hand Scale ON)
- **Arm X / Y / Z** — positional offset for the bare arm (`-1.00` to `1.00`)
- **Arm Pitch / Roll** — X and Z rotation for the bare arm (`-90` to `90°`)

Scaling and offsets do not apply in third person / F5.

## Build

Expand All @@ -35,7 +48,7 @@ Needs JDK 25.
./gradlew build
```

Use `build/libs/fabric-swing-1.0.0.jar`. Skip the `-sources` jar.
Use `build/libs/fabric-swing-1.5.0.jar`. Skip the `-sources` jar.

Dev launch:

Expand Down
39 changes: 3 additions & 36 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
plugins {
id 'net.fabricmc.fabric-loom' version "${loom_version}"
id 'maven-publish'
}

repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
}

loom {
splitEnvironmentSourceSets()

mods {
"itemtweaks" {
"swing" {
sourceSet sourceSets.main
sourceSet sourceSets.client
}
}
}
Expand All @@ -26,8 +14,6 @@ dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
implementation "net.fabricmc:fabric-loader:${project.loader_version}"

// Fabric API. This is technically optional, but you probably want it anyway.
implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
}

Expand All @@ -45,9 +31,7 @@ tasks.withType(JavaCompile).configureEach {
}

java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
// Builds a sources jar alongside the mod jar — useful for local dev and publishing.
withSourcesJar()

sourceCompatibility = JavaVersion.VERSION_25
Expand All @@ -59,23 +43,6 @@ jar {
inputs.property "projectName", projectName

from("LICENSE") {
rename { "${it}_$projectName"}
}
}

// configure the maven publication
publishing {
publications {
create("mavenJava", MavenPublication) {
from components.java
}
}

// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
rename { "${it}_$projectName" }
}
}
12 changes: 4 additions & 8 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx2G
org.gradle.jvmargs=-Xmx4G
org.gradle.parallel=true
org.gradle.configuration-cache=true

# Fabric Properties (pinned to Spencer's setup: MC 26.2 + Loader 0.19.5; verified 2026-10-15)
# check these on https://fabricmc.net/develop
# NOTE: since MC 26.1 Minecraft ships unobfuscated, so there is no yarn/mappings line any more -
# Loom uses Mojang's official names directly.

minecraft_version=26.2
loader_version=0.19.5
loom_version=1.18.4

# Mod Properties
version=1.0.0
group=com.example.itemtweaks
version=1.5.0
group=com.flapjacck.swing

# Dependencies
fabric_api_version=0.161.0+26.2

This file was deleted.

15 changes: 0 additions & 15 deletions src/client/resources/swing.client.mixins.json

This file was deleted.

12 changes: 0 additions & 12 deletions src/main/java/com/example/itemtweaks/ItemTweaks.java

This file was deleted.

24 changes: 24 additions & 0 deletions src/main/java/com/flapjacck/swing/Swing.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.flapjacck.swing;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.flapjacck.swing.command.SwingCommandHandler;
import com.flapjacck.swing.config.SwingConfig;

import net.fabricmc.api.ClientModInitializer;

/** Client entrypoint — holds the mod ID, logger, and initialization. */
public final class Swing implements ClientModInitializer {
public static final String MOD_ID = "swing";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);

@Override
public void onInitializeClient() {
SwingConfig.load();
SwingCommandHandler.register();
LOGGER.info("Swing loaded (scale {}, swing x{})",
SwingConfig.HELD_ITEM_SCALE,
SwingConfig.SWING_SPEED_MULTIPLIER);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.example.itemtweaks.client;
package com.flapjacck.swing.command;

import static net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal;

import com.flapjacck.swing.screen.SwingSettingsScreen;

import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.minecraft.client.Minecraft;

/** {@code /swing} opens the in-game settings screen on the next client tick. */
/** {@code /swing} opens the settings screen on the next client tick. */
public final class SwingCommandHandler {
private SwingCommandHandler() {}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.example.itemtweaks;
package com.flapjacck.swing.config;

import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

Expand All @@ -16,7 +19,9 @@
* Live tweak values. Mixins read these every frame; GUI writes them in place.
* Persisted to {@code config/swing.json}.
*/
public final class ItemTweaksConfig {
public final class SwingConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(SwingConfig.class);

public static final float MIN = 0.1f;
public static final float MAX = 1.0f;
public static final float OFFSET_MIN = -1.0f;
Expand All @@ -39,7 +44,7 @@ public final class ItemTweaksConfig {
/**
* When true, the swing-duration mixin ignores haste / mining-fatigue and
* always starts from the vanilla base of 6 ticks before applying the
* multiplier. Keeps animation speed constant across islands and gear sets.
* multiplier. Keeps animation speed constant across islands and gear sets.
*/
public static boolean IGNORE_HASTE = DEFAULT_IGNORE_HASTE;

Expand Down Expand Up @@ -82,7 +87,7 @@ public final class ItemTweaksConfig {

private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();

private ItemTweaksConfig() {}
private SwingConfig() {}

public static float clamp(float value) {
return Math.round(Mth.clamp(value, MIN, MAX) * 100f) / 100f;
Expand Down Expand Up @@ -141,7 +146,7 @@ public static void load() {
ARM_TILT_PITCH = clampTilt(data.armTiltPitch);
ARM_TILT_ROLL = clampTilt(data.armTiltRoll);
} catch (Exception e) {
ItemTweaks.LOGGER.warn("Could not read {}, using vanilla defaults", file, e);
LOGGER.warn("Could not read {}, using vanilla defaults", file, e);
resetToVanilla();
}
}
Expand Down Expand Up @@ -169,7 +174,7 @@ public static void save() {
GSON.toJson(data, writer);
}
} catch (IOException e) {
ItemTweaks.LOGGER.warn("Could not write {}", file, e);
LOGGER.warn("Could not write {}", file, e);
}
}

Expand Down
Loading
Loading