Skip to content

flurbudurbur/CowCannon

Repository files navigation

Built with devenv

CowCannon

User showing what the plugin does. A bow being repeatedly charged and shooting off cows instead of arrows.

A Bukkit/Spigot plugin that embeds JPHP (a PHP-to-JVM compiler), letting you write Minecraft plugin logic in PHP.

What this is, and what it isn't

TL;DR: Lower your expectations, shoot cows.

This project is really just an experiment born out of curiousity on whether I could implement the long-abandoned JPHP project and make it into a Bukkit plugin. As such, this is by no means a plugin you should go ahead and install on your server "just cuz". There will be bugs, as I didn't concern myself with the user experience, just whether I could do it or not. I did end up implementing various survival-friendly mechanics, like taking the enchantments on your bow into account and creating a crafting recipe for the arrows, but at the root of it all was just my curiousity.

What you need

This experiment runs on 1.20.4, that's all I tested it on. I used the Java version I had installed so as long as you have a JDK 17-compatible Minecraft server running, you should be good to go. I used the latest 1.20.4 Paper build (#499).

Building

Both methods require Java 17+.

Use the bundled Gradle wrapper. (Simple)

./gradlew shadowJar

Use DevEnv! (Overengineered)

You really should just use the Simple™️ method, this is just added cuz I really like DevEnv xd..

Anyway, install DevEnv.

Then, do the same thing as with the Simple Method, but longer:

devenv shell -- gradle shadowJar

DevEnv really only starts to shine if you want to manage dependencies in one place and develop your own projects.. on maybe multiple devices? Idk but it's cool tho!


Output: build/libs/cowcannon-<version number>.jar

Architecture

CowCannon bootstraps jphp inside CowCannonPlugin.onEnable(), registers a set of bukkit\* PHP wrapper classes, then executes php/main.php. Closures registered in that file are stored in-memory and dispatched by CowCannonEventListener when Bukkit events fire.

So basically, for every action/API you want to use which is native to Bukkit, you have to create a wrapper which exposes it so that PHP can use it.

Here's the main.php!

Testing

Tests are written in PHP and live in src/test/resources/php/. An "artisanal" TestRunner class (no PHPUnit cuz JPHP is a potato) collects pass/fail results. PhpTestHarness.java bootstraps a full JPHP environment with a mock Bukkit facade, loads the real main.php, then loads each test file. JUnit 5 surfaces each PHP test as a named dynamic test so results show up normally in your test runner.

Tests also always run when compiling the final jar, so either it works or it works.. Good luck!

./gradlew test

Am I crazy?

I couldn't believe that the tests I wrote actually all passed on the first try, so I made some which would deliberately fail as a check that my TestRunner class wasn't just hyping me up for nothing. I didn't want to remove them because they were a valuable learning experience, so I spent some time in the Gradle docs figuring out if and how I could add a custom argument so that the sanity checks could be triggered conditionally.

Here's how to trigger/verify your own sanity:

./gradlew test -PsanityTests

PHP API

Class Description
bukkit\Bukkit Static utility — register commands and event callbacks
bukkit\CommandSender Wraps CommandSender
bukkit\Player Wraps Player
bukkit\Entity Wraps Entity
bukkit\Location Wraps Location
bukkit\Vector Wraps Vector
bukkit\World Wraps World

About

Minecraft Java plugin made in PHP 7.4!?

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors