CodeGolf 4,000 Characters or Less Coding Challenge

Greetings folks,

As a game of what can be done and fun with development…I present the 4,000 Characters or Less Coding for plugins! Just paste a code tag with your plugin that is functional. Here are the rules:

  • Must be 4,000 Characters or Less
  • Must maintain Sponge coding standards

Let’s see what folks can come up with

3 Likes

EnderBlock 0.2

package org.spongepowered.enderblock;

import org.spongepowered.api.entity.living.monster.Enderman;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.block.ChangeBlockEvent;
import org.spongepowered.api.plugin.Plugin;

@Plugin(id = "enderblock", name = "EnderBlock", version = "0.2")
public class EnderBlock {
    @Listener
    public void onBreakBlock(ChangeBlockEvent.Break event) {
        if (event.getCause().first(Enderman.class).isPresent()) {
            event.setCancelled(true);
        }
    }
}
2 Likes
  • Do empty lines count too?

:wink:

My head hurts after staring at the code for too long, brunch time!
I could use wildcards in imports and combine the annotation with the methods and make if statements without the curly brackets. But that would break the Sponge coding guidelines.
Edit: Oops! I thought that I had to make your code smaller!

I think so yes because if you remove the empty lines you are not following the:

Oh sounds like fun, how about VoxelSniper in 50 lines.

Supports balls, discs and voxels, sizes can be floating point numbers.

Your brush/size/material is set by the command ‘/brush (ball|disc|voxel):size:material’.
For example ‘/brush ball:25:dirt’ will place down balls of dirt with a radius of 25 blocks whereever you click.

As an aside: something funky is up with one of EyeLocationData or BlockRay.from(Entity), as far as I can tell the eye location is supposted to be the entity location + the eye offset, but I was always just getting the offset when using the BlockRay. So a minor fix is needed there for this to work. I changed BlockRay:501 to

position = location.getPosition().add(data.get().eyeLocation().get());

But I’m pretty sure the eye location is supposed to be the correct location so some investigation is needed for that. Otherwise enjoy, although I do think this would be more fun as a code golf-styled challenge with a character limit rather than a line limit.

package com.thevoxelbox.voxelsniperlite;
import org.spongepowered.api.block.*;
import org.spongepowered.api.text.Texts;
import org.spongepowered.api.util.blockray.*;
import org.spongepowered.api.util.command.*;
import org.spongepowered.api.util.command.args.*;
import org.spongepowered.api.util.command.spec.*;

@org.spongepowered.api.plugin.Plugin(id = "vs-lite", name = "VoxelSniper-Lite", version = "0.0.1")
public class VoxelSniperLite {
    @com.google.inject.Inject private org.spongepowered.api.Game game;
    private final java.util.Map<java.util.UUID, String> brushes = com.google.common.collect.Maps.newHashMap();

    @org.spongepowered.api.event.Listener
    public void onStart(org.spongepowered.api.event.game.state.GameInitializationEvent event) {
        event.getGame().getCommandDispatcher().register(this, CommandSpec.builder().arguments(GenericArguments.string(Texts.of("brush")))
                .executor(new CommandExecutor() {
                    public CommandResult execute(CommandSource src, CommandContext args) throws CommandException {
                        if (!java.util.regex.Pattern.matches("(ball|voxel|disc):[\\d]+(\\.[\\d]+)?:[a-z]+", args.getOne("brush").get().toString())) {
                            src.sendMessage(Texts.of("Invalid brush, must match (ball|voxel|disc):size:material"));
                            return CommandResult.empty();
                        }
                        brushes.put(((org.spongepowered.api.entity.living.player.Player) src).getUniqueId(), args.getOne("brush").get().toString());
                        src.sendMessage(Texts.of("Brush has been set to " + args.getOne("brush").get().toString()));
                        return CommandResult.success();
                    }
                }).build(), "brush");
    }

    @org.spongepowered.api.event.Listener
    public void onInteract(org.spongepowered.api.event.action.InteractEvent e) {
        org.spongepowered.api.entity.living.player.Player p = e.getCause().first(org.spongepowered.api.entity.living.player.Player.class).orNull();
        if (p != null && p.getItemInHand().isPresent() && p.getItemInHand().get().getItem().equals(org.spongepowered.api.item.ItemTypes.ARROW)) {
            String brush = brushes.get(p.getUniqueId());
            if (brush == null || !java.util.regex.Pattern.matches("(ball|voxel|disc):[\\d]+(:?\\.[\\d]+)?:[a-z]+", brush)) brush = "ball:1:stone";
            BlockRayHit<org.spongepowered.api.world.World> target = BlockRay.from(p).filter(BlockRay.onlyAirFilter()).end().get();
            double size = Double.parseDouble(brush.split(":")[1]) - 0.5;
            BlockState mat = game.getRegistry().getType(BlockType.class, brush.split(":")[2]).or(BlockTypes.STONE).getDefaultState();
            for (int x = com.flowpowered.math.GenericMath.floor(-size); x < size; x++) {
                for (int z = com.flowpowered.math.GenericMath.floor(-size); z < size; z++) {
                    for (int y = com.flowpowered.math.GenericMath.floor(-size); y < size; y++) {
                        if (brush.startsWith("disc") && y != 0) continue;
                        if (brush.startsWith("voxel") || x * x + y * y + z * z < size * size)
                            p.getWorld().setBlock(target.getBlockX() + x, target.getBlockY() + y, target.getBlockZ() + z, mat);
                    }
                }
            }
        }
    }
}

Exactly 50 lines, and yes the maximum line length is 150.

1 Like

Iirc Sponge follows Googles Java Style, so no wildcard imports allowed.

EDIT: Is Voxelsniper available for Sponge?

Yes VoxelSniper/src/main/java/com/voxelplugineering/voxelsniper/sponge at master · TVPT/VoxelSniper · GitHub

Yes I had to take that liberty because otherwise the imports were 34 lines long (If I remove the fully qualified classes as well).

EnderBlock 3 (under new rules!)

package org.spongepowered.enderblock;

@org.spongepowered.api.plugin.Plugin(id = "eb", name = "EB", version = "3")
public class EB {
    @org.spongepowered.api.event.Listener
    public void onBreakBlock(org.spongepowered.api.event.block.ChangeBlockEvent.Break e) {
        if (e.getCause().first(org.spongepowered.api.entity.living.monster.Enderman.class).isPresent()) {
            e.setCancelled(true);
        }
    }
}

Another entry of my EnderBlock. Can’t really lessen it’s characters without sacrificing the plugin’s name

package org.spongepowered.enderblock;

@org.spongepowered.api.plugin.Plugin(id = "eb", name = "EB")
public class EB {
    @org.spongepowered.api.event.Listener
    public void b(org.spongepowered.api.event.block.ChangeBlockEvent.Break e) {
        if (e.getCause().first(org.spongepowered.api.entity.living.monster.Enderman.class).isPresent()) {
            e.setCancelled(true);
        }
    }
}

Final entry using new any of Cause I just pushed (not just for golf >.>)

package org.inspirenxe.eb;

@org.spongepowered.api.plugin.Plugin(id = "eb", name = "EB")
public class EB {
    @org.spongepowered.api.event.Listener
    public void b(org.spongepowered.api.event.block.ChangeBlockEvent.Break e) {
        if (e.getCause().any(org.spongepowered.api.entity.living.monster.Enderman.class)) {
            e.setCancelled(true);
        }
    }
}

Excellent, I love code golfing! I can remove the star imports then and fully conform to the code style. I also added the voxeldisc brush and reduced my entry from 3900 characters to 2852 characters.

package com.thevoxelbox.voxelsniperlite;

import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.text.Texts;
import org.spongepowered.api.util.blockray.BlockRay;
import org.spongepowered.api.util.command.CommandResult;
import org.spongepowered.api.util.command.args.CommandContext;
import org.spongepowered.api.util.command.args.GenericArguments;
import org.spongepowered.api.util.command.spec.CommandExecutor;
import org.spongepowered.api.util.command.spec.CommandSpec;

@org.spongepowered.api.plugin.Plugin(id = "vs", name = "VS")
public class VoxelSniperLite {
    private org.spongepowered.api.Game g;
    private final java.util.Map<Player, String> c = new java.util.WeakHashMap();

    @Listener
    public void s(org.spongepowered.api.event.game.state.GameInitializationEvent e) {
        g = e.getGame();
        e.getGame().getCommandDispatcher().register(this, CommandSpec.builder()
                .arguments(GenericArguments.string(Texts.of("b"))).executor(new CommandExecutor() {
            public CommandResult execute(org.spongepowered.api.util.command.CommandSource s, CommandContext a) {
                if (!java.util.regex.Pattern.matches("(ball|voxel|(voxel)?disc):[\\d]+:[a-z]+", a.getOne("b").get().toString())) {
                    s.sendMessage(Texts.of("Invalid brush"));
                } else {
                    c.put((Player) s, a.getOne("b").get().toString());
                    s.sendMessage(Texts.of("Brush set to "+a.getOne("b").get()));
                }
                return CommandResult.success();
            }
        }).build(), "b");
    }

    @Listener
    public void i(org.spongepowered.api.event.action.InteractEvent e) {
        Player p = (Player) e.getCause().root().get();
        if (p==null || !p.getItemInHand().isPresent() || !p.getItemInHand().get().getItem().equals(org.spongepowered.api.item.ItemTypes.ARROW)) {
            return;
        }
        String b = c.get(p);
        org.spongepowered.api.util.blockray.BlockRayHit t = BlockRay.from(p).filter(BlockRay.onlyAirFilter()).end().get();
        if (b==null) {
            b = "ball:3:stone";
        }
        String[] v = b.split(":");
        int s = Integer.parseInt(v[1]);
        for (int x=-s; x<s; x++) {
            for (int z=-s; z<s; z++) {
                for (int y=-s; y<s; y++) {
                    if (v[0].endsWith("disc") && y!=0 || !v[0].startsWith("voxel") && x*x+y*y+z*z>s*s-s) {
                        continue;
                    }
                    p.getWorld().setBlockType(t.getBlockX()+x, t.getBlockY()+y, t.getBlockZ()+z,
                        g.getRegistry().getType(org.spongepowered.api.block.BlockType.class, v[2]).or(org.spongepowered.api.block.BlockTypes.STONE));
                }
            }
        }
    }
}
1 Like

Ignite - If an ignitable Entity is set on fire (vanilla: creeper and TNT minecart), it will ignite.

637 characters.

package jbyoshi.sponge.test;

import org.spongepowered.api.entity.Entity;
import org.spongepowered.api.entity.explosive.IgnitableExplosive;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.entity.IgniteEntityEvent;
import org.spongepowered.api.plugin.Plugin;

@Plugin(id = "ignite", name = "Ignite")
public final class Ignite {

    @Listener
    public void handle(IgniteEntityEvent e) {
        Entity target = e.getTargetEntity();
        if (target instanceof IgnitableExplosive) {
            ((IgnitableExplosive) target).ignite();
            e.setCancelled(true);
        }
    }
}