Skip to content

Instantly share code, notes, and snippets.

@EntranceJew
Created September 10, 2015 00:45
Show Gist options
  • Save EntranceJew/54fd4ca1d01fe9f5ae9c to your computer and use it in GitHub Desktop.
Save EntranceJew/54fd4ca1d01fe9f5ae9c to your computer and use it in GitHub Desktop.
<?php
/*
* A utility file to update a minecraft server that gets its resources from a solder link.
* Requires solder to respect the /:slug/:build:/server api request.
* Can work without it, with some modifications.
*/
//$mcversion = "1.7.10";
//$forgeversion = "1.7.10-10.13.4.1492-1.7.10";
// wherever your solder exists
$endpoint = "http://solder.example.com/";
// modpack slug
$modpack = "best-mod-pack-ever";
// target latest? recommended? whatever comes back in the modpack json.
$target = "latest";
// where to install the files
$serverpath = "/path/to/install/server/files/to/";
// print status? a lot?
$verbosemode = true;
// data source strings
$mcservername = "minecraft_server.%s.jar";
$mcendpoint = "https://s3.amazonaws.com/Minecraft.Download/versions/%s/minecraft_server.%s.jar";
$forgeservername = "forge-%s-%s.jar";
$forgeendpoint = "http://files.minecraftforge.net/maven/net/minecraftforge/forge/%s/forge-%s-%s.jar";
$forgetarget = "installer";
function verbose_print($msg){
global $verbosemode;
if($verbosemode){
print($msg);
}
}
function verbose_print_r($msg){
global $verbosemode;
if($verbosemode){
print_r($msg);
}
}
function ensure_server_setup(){
global $serverpath;
if(!file_exists($serverpath."cache")){
mkdir($serverpath."cache");
}
}
function server_file_exists($path){
global $serverpath;
return file_exists($serverpath.$path);
}
function file_has_hash($file, $hash){
return md5_file($file) == $hash;
}
function server_file_has_hash($file, $hash){
global $serverpath;
return file_has_hash($serverpath.$file, $hash);
}
function get_data($url) {
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
function download_file($url, $output=""){
$parts = explode("/", $url);
$last = $parts[sizeof($parts)-1];
if($output==""){
$output = $last;
}
file_put_contents($output, fopen($url, 'r'));
return $output;
}
function move_file_to_server($file, $location=""){
global $serverpath;
return rename($file, $serverpath.$location.$file);
}
function download_minecraft($version){
global $mcendpoint, $mcservername;
$file_to_get = sprintf($mcendpoint, $version, $version);
$file_to_save = sprintf($mcservername, $version);
return download_file($file_to_get, $file_to_save);
}
function download_forge($version, $target){
global $forgeendpoint, $forgeservername;
$file_to_get = sprintf($forgeendpoint, $version, $version, $target);
$file_to_save = sprintf($forgeservername, $version, $target);
return download_file($file_to_get, $file_to_save);
}
function get_endpoint($method){
global $endpoint;
return json_decode(get_data($endpoint.$method), true);
}
function get_files_to_download($modpack, $target){
$data = get_endpoint("api/modpack/".$modpack);
verbose_print_r($data);
return get_endpoint("api/modpack/".$modpack."/".$data[$target]."/server");
}
function install_mod($modzip){
global $serverpath;
$zip = new ZipArchive;
$res = $zip->open($serverpath.$modzip);
if ($res === TRUE){
$zip->extractTo($serverpath);
$zip->close();
} else {
error_log("Couldn't install mod ".$modzip);
}
}
function finalize_modpack($modpack, $target){
global $serverpath;
copy($serverpath."bin/modpack.jar", $serverpath.$modpack."-".$target.".jar");
}
function agree_to_eula(){
global $serverpath;
file_put_contents($serverpath."eula.txt", "eula=true");
}
function disagree_to_eula(){
global $serverpath;
file_put_contents($serverpath."eula.txt", "eula=false");
}
function verify_minecraft($version){
global $mcservername;
$file_to_verify = sprintf($mcservername, $version);
if(!server_file_exists($file_to_verify)){
verbose_print("downloading minecraft ".$file_to_verify);
$server_file = download_minecraft($file_to_verify);
move_file_to_server($server_file);
}
}
function verify_forge($version){
global $forgeservername;
$file_to_verify = sprintf($forgeservername, $version, "installer");
if(!server_file_exists($file_to_verify)){
verbose_print("downloading minecraft ".$file_to_verify);
$server_file = download_forge($version, "installer");
move_file_to_server($server_file);
return true;
}
return false;
}
function verify_mods($mods){
foreach($mods as $mod){
$cachepath = "cache/".$mod["name"]."-".$mod["version"].".zip";
$file_exists = server_file_exists($cachepath);
$file_has_hash = false;
if($file_exists){
$file_has_hash = server_file_has_hash($cachepath, $mod["md5"]);
}
// download the mod if it don't exist / hashes are wrong
//@TODO: safely uninstall previous versions using previous version's zip structure
//@TODO: keep the previous version/json response somewhere to uninstall the right mods
if(!$file_exists || !$file_has_hash){
verbose_print("downloading ".$cachepath);
$modfile = download_file($mod["url"]);
if(file_has_hash($modfile, $mod["md5"])){
move_file_to_server($modfile, "cache/");
// install mods
install_mod($cachepath);
}else{
error_log("File ".$modfile." downloaded wrong.");
}
}
}
}
function install_forge_server($version){
global $serverpath, $forgeservername;
$forge_jar = $serverpath.sprintf($forgeservername, $version, "install");
exec("cd {$serverpath} && java -jar {$forge_jar} --installServer 2>&1", $results);
verbose_print_r($results);
}
function build_modpack($modpack, $target){
verbose_print("building ".$modpack." v".$target);
$to_download = get_files_to_download($modpack, $target);
// get the server jar & install it if it does not exist
//verify_minecraft($to_download["minecraft"]);
//if(verify_forge($to_download["forge"])){
// install_forge_server($to_download["forge"]);
//}
// get the mods
verify_mods($to_download['mods']);
// install forge to root of the server, presuming we got it from a modpack
finalize_modpack($modpack, $target);
}
// process
ensure_server_setup();
build_modpack($modpack, $target);
// nothing says consent like automation
agree_to_eula();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment