Minestom 2026 · Java 25 · Active Dev

MineGun

A firearms library built on Minestom. Raycasted hitscan weapons, custom health & shield management, and a clean event-driven API — all in pure Java.

GitHub ↗
2
Weapons
25ms
Fire Cooldown
100
Range (blocks)
Java 25
Target
What's Included
🎯
Raycasted Hitscan
Step-based raycast at 0.5 block increments, 100 block range. Sneak-aware hitbox detection (1.8 / 1.5 height).
Health + Shield System
Custom 100HP / 100SP using Minestom Tags. Boss bar HUD, kill tracking, death title + respawn.
🔫
Rifle
WOODEN_HOE item. 25ms cooldown. CRIT particles. 25 custom damage. Server-wide kill broadcast.
🚀
Rocket Launcher
WOODEN_AXE item. FLAME particles. Terrain explosion (radius 10) on block impact.
📋
minegunLogger
ANSI-coloured INFO / WARN / ERROR / OK console logger with ASCII art startup banner.
🎮
Demo Server
Flat stone arena, /give command, zombie test dummy, and F3+F4 gamemode support. Online-mode auth.

Architecture

MineGun is split into two concerns: the library core (com.minegun) which is what you integrate, and the demo (com.minegun.demo) which is a runnable reference you don't need in production.

Package Tree
com.minegun
├── HealthManagement.java    ← Custom HP/shield system
├── minegunLogger.java       ← ANSI console logger
└── Weapons/
    ├── weapons.java         ← Shared raycast hitbox utility
    ├── Rifle.java           ← Hitscan rifle implementation
    └── RocketLauncher.java  ← Explosive launcher implementation

com.minegun.demo             ← Example only (delete in prod)
├── Main.java
├── giveCommand.java
└── TestDummy.java
Library vs Demo: For production, only include com.minegun and com.minegun.Weapons. The demo package has a hardcoded arena and is purely for reference.

How Hitscan Works

When a player right-clicks a weapon item, the server casts a ray from their eye position in their look direction:

  1. Eye position = player.getPosition().add(0, eyeHeight, 0)
  2. Steps at 0.5 block increments along the look vector
  3. At each point: checks for a solid block (stops / explodes on hit)
  4. Calls weapons.isPlayerAtPosition() to check for player hitbox overlap
  5. On player hit: applies damage, sounds, kill detection
  6. On miss: spawns a particle at the step point

Installation

MineGun is a source library — clone the repo and copy the core files into your project, or build a JAR via the included Gradle wrapper.

Requirements

DependencyVersionNotes
Java25+Required by the project
Minestom2026.03.03-1.21.11Maven Central
AdventurebundledShips with Minestom

Clone

bash
git clone https://github.com/VardinsDev/minegun.git
cd minegun

Gradle Dependency (build.gradle.kts)

kotlin
repositories {
    mavenCentral()
}
dependencies {
    implementation("net.minestom:minestom:2026.03.03-1.21.11")
}

Copy Source Files Into Your Project

Copy these files from src/main/java/ into your own source root:

  • com/minegun/HealthManagement.java
  • com/minegun/minegunLogger.java
  • com/minegun/Weapons/weapons.java
  • com/minegun/Weapons/Rifle.java
  • com/minegun/Weapons/RocketLauncher.java
Skip the demo package. Do not copy com/minegun/demo/ — it depends on a specific hardcoded world setup and is not reusable as-is.

Build & Run the Demo

bash
# Build
./gradlew shadowJar

# Run (online-mode, port 25565)
java -jar build/libs/minegun-all.jar

Quick Start

Minimum code to get the Rifle and health system working inside an existing Minestom server.

1. Register Weapons

java
import com.minegun.Weapons.Rifle;
import com.minegun.Weapons.RocketLauncher;

GlobalEventHandler geh = MinecraftServer.getGlobalEventHandler();
InstanceContainer ic = instanceManager.createInstanceContainer();

Rifle.register(geh, ic);
RocketLauncher.register(geh, ic);

2. Set Up Health Management

Both methods must be called. bossBarMaker listens for PlayerLoadedEvent to init bars, tickUpdate handles the display loop and death/respawn.

java
HealthManagement hm = new HealthManagement();
hm.bossBarMaker(geh);
hm.tickUpdate(geh);

3. Give a Weapon to a Player

java
geh.addListener(AsyncPlayerConfigurationEvent.class, event -> {
    event.setSpawningInstance(ic);
    event.getPlayer().setRespawnPoint(new Pos(0, 42, 0));
    Rifle.givePlayer(event.getPlayer());
});

Full Minimal Example

java
public class MyServer {
    public static void main(String[] args) {
        MinecraftServer server = MinecraftServer.init();

        InstanceContainer ic = MinecraftServer.getInstanceManager()
            .createInstanceContainer();
        ic.setGenerator(unit ->
            unit.modifier().fillHeight(39, 40, Block.STONE));
        ic.setChunkSupplier(LightingChunk::new);

        GlobalEventHandler geh = MinecraftServer.getGlobalEventHandler();
        Rifle.register(geh, ic);
        RocketLauncher.register(geh, ic);

        HealthManagement hm = new HealthManagement();
        hm.bossBarMaker(geh);
        hm.tickUpdate(geh);

        geh.addListener(AsyncPlayerConfigurationEvent.class, e -> {
            e.setSpawningInstance(ic);
            e.getPlayer().setRespawnPoint(new Pos(0, 42, 0));
            Rifle.givePlayer(e.getPlayer());
        });

        server.start("0.0.0.0", 25565);
    }
}
Tip: demo/Main.java is a working version of this pattern with the /give command and F3+F4 gamemode support already wired in.
com.minegun.Weapons
weapons
Shared utility class. Provides the player hitbox detection used inside every weapon's raycast loop.
Javacom.minegun.Weapons

Methods

public static Player isPlayerAtPosition(InstanceContainer instance, Pos targetPos, Player shooter)

Scans all players in the instance. For each player, samples their hitbox in 0.3 block increments from feet up to standing (1.8) or sneaking (1.5) height. Returns the first player whose hitbox contains targetPos within a 0.5 block radius. Returns shooter as a sentinel if no hit.

instanceInstanceContainerThe instance to search for players.
targetPosPosThe point along the ray to check.
shooterPlayerThe firing player — excluded from the scan and returned on miss.

Returns: Hit Player, or shooter if no hit (sentinel pattern).

Hitbox Detail

java — hitbox loop
double height = player.isSneaking() ? 1.5 : 1.8;
double y = 0.0;
while (y <= height) {
    Pos checkPos = feetPos.add(0.0, y, 0.0);
    if (targetPos.distanceSquared(checkPos) <= 0.25) return player;
    y += 0.3;
}
Sentinel pattern: Callers check if (hit != shooter) — not if (hit != null). The method never returns null.
com.minegun
HealthManagement
Custom health and shield system independent of Minecraft's native HP. Each player gets 100 HP and 100 Shield stored as Minestom Tags, displayed via two boss bars. Handles damage routing, kill tracking, death events, and respawn.
Javacom.minegunMinestom Tags

Damage Routing

flow
damage(player, hitDamage)
  ├─ shield >= hitDamage  →  shield -= hitDamage   (health unchanged)
  ├─ shield == hitDamage  →  shield = 0            (health unchanged)
  └─ shield < hitDamage   →  overflow = shield - hitDamage  (negative)
                              shield = 0
                              health += overflow   (subtracts from health)
Known quirk: The overShield variable is computed as shield - hitDamage (a negative number) then added to health, correctly reducing it. The variable name is misleadingly positive — this is a cosmetic code issue, the maths is correct.

Methods

publicvoid bossBarMaker(GlobalEventHandler eventHandler)

Registers PlayerLoadedEvent. Creates green Health bar + blue Shield bar for each player, adds them to the HUD, and sets both tags to 100.0.

publicvoid damage(Player player, double hitDamage)

Applies damage routing through shield first, then health. Updates both tags on the player.

playerPlayerThe player receiving damage.
hitDamagedoubleRaw damage amount.
publicvoid tickUpdate(GlobalEventHandler eventHandler)

Registers PlayerTickEvent. Updates boss bar progress each tick. On health ≤ 0: teleports to respawn point, shows death title, applies blindness, resets HP+SP to 100.

publicdouble getHealth(Player player)

Returns current health value (0–100) from healthTag.

publicdouble getShield(Player player)

Returns current shield value (0–100) from shieldTag.

publicvoid setKilledBy(Player killed, Player killer)

Records who killed whom. Stored in a HashMap<UUID, Player>.

publicPlayer getKilledBy(Player player)

Returns the player who last killed this player, or null if no kill recorded.

Kill Detection Example

java
HealthManagement hm = new HealthManagement();
hm.damage(target, 25);
if (hm.getHealth(target) <= 0) {
    hm.setKilledBy(target, shooter);
    String msg = target.getUsername() + " was shot by "
                + hm.getKilledBy(target).getUsername();
    // Broadcast msg to all online players...
}
com.minegun
minegunLogger
Static ANSI-coloured console logger. All methods are static — no instantiation needed. Prints timestamped, prefixed log lines in four severity levels plus an ASCII art banner.
Javacom.minegun

Log Levels

MethodColourLabelUse For
info(msg)Cyan[INFO]Startup / lifecycle events
warn(msg)Yellow[WARN]Non-fatal unexpected states
error(msg)Red[ERROR]Failures, invalid usage
success(msg)Green[OK]Successful operations

Output Format

console
[HH:mm:ss] [Minegun] [LEVEL] message

Methods

publicstaticvoid info(String message)

Cyan [INFO] message. Used throughout the demo for all startup lifecycle events.

publicstaticvoid warn(String message)

Yellow [WARN] message for non-critical anomalies.

publicstaticvoid error(String message)

Red [ERROR] message. Called in giveCommand when console tries to give itself a weapon.

publicstaticvoid success(String message)

Green [OK] message. Used when a weapon is given to a player or the demo server finishes starting.

publicstaticvoid printBanner()

Prints the purple/pink MineGun ASCII art banner to stdout. Called once at the very start of Main.java.

Usage

java
minegunLogger.printBanner();
minegunLogger.info("Server starting...");
minegunLogger.success(player.getUsername() + " received a Rifle");
minegunLogger.warn("Cooldown map may be growing");
minegunLogger.error("Console cannot use /give");
com.minegun.Weapons
Rifle
Hitscan rifle. Right-click fires a step-based ray. Deals 25 custom damage via HealthManagement, spawns CRIT particles along the beam, plays sound effects, and broadcasts kill messages to all online players.
Javacom.minegun.WeaponsMinestom

Item Properties

PropertyValue
MaterialWOODEN_HOE
Display NameRifle — NamedTextColor.YELLOW
Lore"Custom Made Weapon" / "By: VardinsDev"

Stats

StatValue
Fire cooldown25 ms
Max range100 blocks
Step size0.5 blocks
Custom damage25 (via HealthManagement)
Vanilla damage12f DamageType.ARROW — immediately healed
Trail particleCRIT
Fire soundENTITY_FIREWORK_ROCKET_BLAST (vol 0.25)
Hit confirmENTITY_EXPERIENCE_ORB_PICKUP on shooter (3 tick delay)
Hit soundENTITY_GENERIC_HURT on victim (3 tick delay)

Methods

publicstaticvoid givePlayer(Player player)

Builds and gives a WOODEN_HOE with custom name/lore. Logs a success message.

publicstaticvoid register(GlobalEventHandler eventHandler, InstanceContainer instanceContainer)

Registers PlayerUseItemEvent filtered to WOODEN_HOE. Manages per-player cooldown internally via a static UUID-keyed HashMap.

eventHandlerGlobalEventHandlerServer global event handler.
instanceContainerInstanceContainerUsed for block collision and particle broadcast.

Fire Sequence

flow
Right-click (WOODEN_HOE)
  └─ 25ms cooldown gate
       └─ Raycast (0.5 step, 100 block max)
            ├─ Solid block hit → stop
            ├─ Player hit
            │    ├─ FIREWORK_ROCKET_BLAST on victim
            │    ├─ DamageType.ARROW 12f + instant heal
            │    ├─ HealthManagement.damage(victim, 25)
            │    ├─ health ≤ 0?
            │    │    ├─ setKilledBy, log kill
            │    │    └─ Broadcast kill message (yellow, all players)
            │    └─ +3 ticks: ORB_PICKUP → shooter, GENERIC_HURT → victim
            └─ Miss → CRIT particle at step point
  └─ FIREWORK_ROCKET_BLAST on shooter
com.minegun.Weapons
RocketLauncher
Explosive launcher. Same raycast pattern as the Rifle, but produces FLAME particles and detonates a terrain explosion (radius 10) when the ray strikes a solid block. Direct player hits play sound effects only — HealthManagement damage is not yet wired in.
Javacom.minegun.WeaponsMinestom

Item Properties

PropertyValue
MaterialWOODEN_AXE
Display NameRocket Launcher — NamedTextColor.YELLOW
Lore"Custom Made Weapon" / "By: VardinsDev"

Stats

StatValue
Fire cooldown25 ms
Max range100 blocks
Step size0.5 blocks
Block hitinstanceContainer.explode(x, y, z, 10f)
Direct hit damageSounds only (WIP — no HP damage yet)
Trail particleFLAME
Fire soundENTITY_FIREWORK_ROCKET_BLAST (vol 0.25)
WIP: Direct player hits currently play sounds but do not call HealthManagement.damage(). To add HP damage, mirror the Rifle's hit block after the sound calls.

Methods

publicstaticvoid givePlayer(Player player)

Builds and gives a WOODEN_AXE with custom name/lore. Logs a success message.

publicstaticvoid register(GlobalEventHandler eventHandler, InstanceContainer instanceContainer)

Registers PlayerUseItemEvent filtered to WOODEN_AXE. On block hit calls instanceContainer.explode() with radius 10.

Fire Sequence

flow
Right-click (WOODEN_AXE)
  └─ 25ms cooldown gate
       └─ Raycast (0.5 step, 100 block max)
            ├─ Solid block hit
            │    └─ instanceContainer.explode(x, y, z, 10) → stop
            ├─ Player hit
            │    ├─ FIREWORK_ROCKET_BLAST on victim
            │    └─ +3 ticks: ORB_PICKUP → shooter, GENERIC_HURT → victim
            └─ Miss → FLAME particle at step point
  └─ FIREWORK_ROCKET_BLAST on shooter
com.minegun.demo
Main
Complete demo server entry point. Wires together all MineGun systems in a flat stone arena with a zombie test dummy. Reference only — not for production.
Javacom.minegun.demo
Entry point bug: The method signature is static void main() — it's missing public and the String[] args parameter, so the JVM won't find it automatically. Fix to public static void main(String[] args) before running.

Startup Sequence

  1. minegunLogger.printBanner()
  2. Init server with Auth.Online() (real Mojang auth)
  3. Create instance, fill Y 39–40 with Stone, enable LightingChunk
  4. Register Rifle and RocketLauncher
  5. Register /give command
  6. On AsyncPlayerConfigurationEvent: set instance, respawn Pos(0,42,0), permission 4, give Rifle
  7. On PlayerGameModeRequestEvent: allow F3+F4 for perm ≥ 2
  8. Register HealthManagement boss bars + tick update
  9. Start server on 0.0.0.0:25565
  10. Spawn zombie dummy at Pos(1,42,1)
com.minegun.demo
giveCommand
In-game /give command. Gives the executing player a weapon. Requires permission level ≥ 2. Tab-completes weapon names.
Javacom.minegun.demo

Usage

in-game
/give Rifle
/give RocketLauncher

Behaviour

  • Player-only — console triggers minegunLogger.error()
  • Requires permission level ≥ 2
  • Auto-complete via ArgumentType.Word(...).from("RocketLauncher","Rifle")
  • Case-insensitive weapon matching

Registration

java
MinecraftServer.getCommandManager().register(new giveCommand());
com.minegun.demo
TestDummy
Spawns a stationary zombie for weapon testing. No AI goals — stands still as a target dummy.
Javacom.minegun.demo

Method

publicstaticvoid createDummy(InstanceContainer instanceContainer)

Creates an EntityCreature(EntityType.ZOMBIE) and spawns it at Pos(1, 42, 1). The zombie has no AI so it stands still.

Note: The hitscan system only detects players, not entities. The zombie is a visual target — shooting it won't register as a hit via weapons.isPlayerAtPosition.
java
EntityCreature zombie = new EntityCreature(EntityType.ZOMBIE);
zombie.setInstance(instanceContainer, new Pos(1, 42, 1));
zombie.spawn();