chore(ci): add pre-commit as well as split variables out

This commit is contained in:
Sekwah 2022-04-24 13:44:14 +01:00
parent 3aa1ad6140
commit c1ed93203c
No known key found for this signature in database
GPG Key ID: 9E0D654FC942286D
20 changed files with 736 additions and 654 deletions

View File

@ -1,40 +1,40 @@
name: Build Project
on:
push:
branches:
- '**'
tags:
- '*'
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 8
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '8.0'
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Build with Gradle
run: ./gradlew buildSubmodules build
- name: Upload to Discord (If pre-release tag)
if: "startsWith(github.ref, 'refs/tags/v') && contains(github.ref, '-')"
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
run: ./gradlew discordupload
- name: Publish to Curseforge (If release tag)
if: "startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-')"
env:
CURSE_API: ${{ secrets.CURSE_API }}
run: ./gradlew curseforge
name: Build Project
on:
push:
branches:
- '**'
tags:
- '*'
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 8
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: '8.0'
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Build with Gradle
run: ./gradlew buildSubmodules build
- name: Upload to Discord (If pre-release tag)
if: "startsWith(github.ref, 'refs/tags/v') && contains(github.ref, '-')"
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
run: ./gradlew discordupload
- name: Publish to Curseforge (If release tag)
if: "startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-')"
env:
CURSE_API: ${{ secrets.CURSE_API }}
run: ./gradlew curseforge

41
.github/workflows/pre-commit-check.yaml vendored Normal file
View File

@ -0,0 +1,41 @@
name: "Pre-commit consistency check"
on:
workflow_dispatch:
pull_request:
concurrency:
group: ${{ github.head_ref }}-precommit
cancel-in-progress: true
jobs:
pre-commit-check:
name: Run pre-commit checks
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: dorny/paths-filter@v2
id: filter
with:
list-files: shell
filters: |
addedOrModified:
- added|modified: '**'
# run only if changed files were detected
- name: Run against changes
uses: pre-commit/action@v2.0.3
if: steps.filter.outputs.addedOrModified == 'true'
with:
extra_args: --files ${{ steps.filter.outputs.addedOrModified_files }}
# run if no changed files were detected (e.g. workflow_dispatch on master branch)
- name: Run against all files
uses: pre-commit/action@v2.0.3
if: steps.filter.outputs.addedOrModified != 'true'
with:
extra_args: --all-files

17
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,17 @@
# See https://pre-commit.com for more information
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: fix-byte-order-marker
- id: mixed-line-ending
- id: check-merge-conflict
- id: check-case-conflict
- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.1.10
hooks:
- id: remove-crlf
- id: remove-tabs

View File

@ -1,65 +1,65 @@
let versionRegex = /(\nversion:\s)([0-9.-]+)/;
let velocityVersionRegex = /(\sversion\s=\s")([0-9.-]+)("\))/;
const ymlUpdater = {
updater: {
'readVersion': (contents) => {
return versionRegex.exec(contents)[2];
},
'writeVersion': (contents, version) => {
return contents.replace(versionRegex, `$1${version}`);
}
}
}
const bungee = {
filename: 'src/main/resources/bungee.yml',
...ymlUpdater,
}
const spigotPlugin = {
filename: 'spigot/src/main/resources/plugin.yml',
...ymlUpdater,
}
const gradleTracker = {
filename: 'gradle.properties',
updater: {
'readVersion': (contents) => {
return versionRegex.exec(contents)[2];
},
'writeVersion': (contents, version) => {
return contents.replace(versionRegex, `$1${version}`);
}
}
}
const velocity_plugin = {
filename: 'src/main/java/com/sekwah/advancedportals/velocity/AdvancedPortalsPlugin.java',
updater: {
'readVersion': (contents) => {
return velocityVersionRegex.exec(contents)[2];
},
'writeVersion': (contents, version) => {
return contents.replace(velocityVersionRegex, `$1${version}$3`);
}
}
}
const files = [gradleTracker] // spigotPlugin, velocity_plugin, bungee
module.exports = {
bumpFiles: files,
packageFiles: files,
// In case you need to force a version change (mostly due to change of scope of the update e.g. major now instead of patch)
//releaseAs: '1.0.0',
header:"# Changelog\n" +
"\n" +
"All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.\n" +
"\n" +
"For the release changelogs see [CHANGELOG.md](CHANGELOG.md) \n" +
"For the snapshot changelogs see [SNAPSHOT_CHANGELOG.md](SNAPSHOT_CHANGELOG.md)\n",
}
let versionRegex = /(\nversion:\s)([0-9.-]+)/;
let velocityVersionRegex = /(\sversion\s=\s")([0-9.-]+)("\))/;
const ymlUpdater = {
updater: {
'readVersion': (contents) => {
return versionRegex.exec(contents)[2];
},
'writeVersion': (contents, version) => {
return contents.replace(versionRegex, `$1${version}`);
}
}
}
const bungee = {
filename: 'src/main/resources/bungee.yml',
...ymlUpdater,
}
const spigotPlugin = {
filename: 'spigot/src/main/resources/plugin.yml',
...ymlUpdater,
}
const gradleTracker = {
filename: 'gradle.properties',
updater: {
'readVersion': (contents) => {
return versionRegex.exec(contents)[2];
},
'writeVersion': (contents, version) => {
return contents.replace(versionRegex, `$1${version}`);
}
}
}
const velocity_plugin = {
filename: 'src/main/java/com/sekwah/advancedportals/velocity/AdvancedPortalsPlugin.java',
updater: {
'readVersion': (contents) => {
return velocityVersionRegex.exec(contents)[2];
},
'writeVersion': (contents, version) => {
return contents.replace(velocityVersionRegex, `$1${version}$3`);
}
}
}
const files = [gradleTracker] // spigotPlugin, velocity_plugin, bungee
module.exports = {
bumpFiles: files,
packageFiles: files,
// In case you need to force a version change (mostly due to change of scope of the update e.g. major now instead of patch)
//releaseAs: '1.0.0',
header:"# Changelog\n" +
"\n" +
"All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.\n" +
"\n" +
"For the release changelogs see [CHANGELOG.md](CHANGELOG.md) \n" +
"For the snapshot changelogs see [SNAPSHOT_CHANGELOG.md](SNAPSHOT_CHANGELOG.md)\n",
}

View File

@ -4,4 +4,4 @@ REM Use this file for testing cases for different versions, just drag the versio
java -Xmx4096M -DIReallyKnowWhatIAmDoingISwear=true -jar %1
REM Could add a 32 bit test part but noone uses 32 bit anymore
GOTO A
PAUSE.
PAUSE.

18
TODO.md
View File

@ -1,18 +0,0 @@
TODO
================
Main Tasks (Generally should be done in order)
Tag registration system (Mostly done, just needs to be tested and implemented)
Portal trigger system
Configs for language files to allow all messages to change
Change item data from strings to an object with strings in maybe
Bungee Support Set Locations
Keept the data storage for destinations and portals generally the same
but modify it a little to be nicer for the tag registry.
Recode for spongepowered or find a way to make it work easier for them.

View File

@ -1,19 +1,3 @@
import org.apache.commons.codec.Charsets
import org.apache.http.HttpEntity
import org.apache.http.HttpResponse
import org.apache.http.client.HttpClient
import org.apache.http.client.config.CookieSpecs
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.impl.client.HttpClients
import org.apache.http.client.methods.HttpGet
import com.google.gson.Gson
allprojects {
apply plugin: 'java'
@ -46,16 +30,16 @@ buildscript {
}
}
apply from: 'env-variables.gradle'
archivesBaseName = "Advanced-Portals"
group = 'com.sekwah.advancedportals'
version = '1.0.0'
def versionString = (file('./version.txt').text + (isRelease ? "" : "-${snapshotName}${shaRef}")).replaceAll('\n', '')
setVersion(versionString)
println "Version: ${getVersion()}"
description = ""
def branch = System.getenv("GITHUB_REF");
def sha = System.getenv("GITHUB_SHA");
def isDevBranch = branch == null || !(branch.startsWith("refs/tags/") && !branch.contains("-"))
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
@ -81,6 +65,10 @@ dependencies {
includeLibs project(':velocity')
}
apply from: 'env-variables.gradle'
println "Branch ${ext.branch}${ext.shaRef} isRelease: '${ext.isRelease}'"
jar {
// Filters the files out that are in the build folders. Look to see if there is a better way to do this?
@ -91,189 +79,3 @@ jar {
it.isDirectory() ? it : zipTree(it)
}
}
/** For pre-releases and testers to be able to try the latest commits if they want.
* If the builds start exceeding 8MB then we may want to upload to s3 instead and periodically clear.
* TODO possibly add a task that announces when builds are made?
* Though add a note that it may take a while for Curse to approve the files.
*/
task discordupload {
dependsOn(jar)
doLast {
String discordWebhook = System.getenv("DISCORD_WEBHOOK")
if(discordWebhook != null) {
println("Logging Into Discord")
CloseableHttpClient httpClient = HttpClients.createDefault()
HttpPost uploadFile = new HttpPost(discordWebhook)
MultipartEntityBuilder builder = MultipartEntityBuilder.create()
builder.addTextBody("content", "New automated dev build\n\n" +
"Current Features: <${project.github}/blob/${sha}/docs/changelogs/SNAPSHOT_CHANGELOG.md>")
builder.addBinaryBody("file", file(jar.archiveFile).newInputStream(), ContentType.APPLICATION_OCTET_STREAM, jar.archiveName)
HttpEntity multipart = builder.build()
uploadFile.setEntity(multipart)
CloseableHttpResponse response = httpClient.execute(uploadFile)
response.getEntity()
println("Posted build")
} else {
println("Discord webhook unspecified")
}
}
}
static String getValueFromCurseAPI(apiKey, endpoint) {
String API_BASE_URL = 'https://minecraft.curseforge.com'
Gson gson = new Gson()
HttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
HttpGet get = new HttpGet(API_BASE_URL + endpoint)
get.setHeader('X-Api-Token', apiKey)
HttpResponse response = client.execute(get)
int statusCode = response.statusLine.statusCode
if (statusCode == 200) {
byte[] data = response.entity.content.bytes
return new String(data, Charsets.UTF_8)
} else {
if (response.getFirstHeader('content-type').value.contains('json')) {
InputStreamReader reader = new InputStreamReader(response.entity.content)
reader.close()
throw new RuntimeException("[CurseForge] Error")
} else {
throw new RuntimeException("[CurseForge] HTTP Error Code $response.statusLine.statusCode: $response.statusLine.reasonPhrase")
}
}
}
/**
* Upload a single file (in case you also want to upload the other files like source n stuff)
* @param json
* @param file
* @return
* @throws IOException
* @throws URISyntaxException
*/
UploadResponse uploadFile(Metadata metadata, File file, String apiKey, Gson gson) throws IOException, URISyntaxException {
String API_BASE_URL = 'https://minecraft.curseforge.com'
String UPLOAD_URL = "/api/projects/%s/upload-file"
// Upload
// Important info
String uploadUrl = String.format(API_BASE_URL + UPLOAD_URL, project.curse_project_id)
HttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
HttpPost post = new HttpPost(uploadUrl)
post.setHeader('X-Api-Token', apiKey)
// https://support.curseforge.com/en/support/solutions/articles/9000197321-curseforge-api
post.setEntity(MultipartEntityBuilder.create()
.addTextBody('metadata', gson.toJson(metadata), ContentType.APPLICATION_JSON)
.addBinaryBody('file', file)
.build())
HttpResponse response = client.execute(post)
InputStreamReader reader = new InputStreamReader(response.entity.content)
UploadResponse uploadResponse = gson.fromJson(reader, UploadResponse)
reader.close()
return uploadResponse
}
class GameVersion {
int id
int gameVersionTypeID
String name
String slug
}
/**
* As described here https://support.curseforge.com/en/support/solutions/articles/9000197321-curseforge-api
*/
class Metadata {
String changelog
String changelogType
int[] gameVersions
String releaseType
}
class UploadResponse {
int id;
}
// Based on https://github.com/matthewprenger/CurseGradle as it didnt support Bukkit uploads at the time.
task curseforge {
dependsOn(jar)
doLast {
String apiKey = null
if (System.getenv("CURSE_API") != null) {
apiKey = System.getenv("CURSE_API")
}
if(apiKey != null) {
Gson gson = new Gson()
//String VERSION_TYPES_URL = "/api/game/version-types"
int gameVersionTypeID = 1
String VERSION_URL = "/api/game/versions"
println("Uploading to CurseForge")
// Get game versions
String gameVersionsString = getValueFromCurseAPI(apiKey, VERSION_URL)
GameVersion[] gameVersions = gson.fromJson(gameVersionsString, GameVersion[].class)
def versions = gameVersions.findAll {it.gameVersionTypeID == gameVersionTypeID}
String[] supportedVersions = [
"1.16",
"1.15",
"1.14",
"1.13"
]
def supportedGameVersions = versions.findAll {supportedVersions.contains(it.name)}
int[] supportedGameVersionIds = supportedGameVersions.collect {it.id}.toArray()
println("Supported Version Id's ${supportedGameVersionIds}")
Metadata uploadMetadata = new Metadata();
uploadMetadata.changelog = "${project.github}/blob/${sha}/docs/changelogs/CHANGELOG.md"
uploadMetadata.changelogType = "markdown"
uploadMetadata.releaseType = isDevBranch ? "beta" : "release"
uploadMetadata.gameVersions = supportedGameVersionIds
def uploadId = uploadFile(uploadMetadata, file(jar.archiveFile), apiKey, gson)
println("Uploaded with ID: ${uploadId.id}")
println("Published build")
} else {
println("Discord webhook unspecified")
}
}
// id = project.curse_project_id
// // TODO add code to reference this but also cut the latest change logs in for the files
// changelog = "${project.github}/blob/${sha}/CHANGELOG.md"
// changelogType = 'markdown'
// releaseType = 'release'
}

View File

@ -1,27 +1,27 @@
package com.sekwah.advancedportals.core;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.sekwah.advancedportals.core.config.CoreModule;
public class AdvancedPortalsCore {
/**
* https://github.com/google/guice/wiki/GettingStarted
*
*/
private Injector injector = Guice.createInjector(new CoreModule(this));
/**
* For some platforms we could do this on construction but this just allows for a bit more control
*/
public void onEnable() {
AdvancedPortalsModule module = new AdvancedPortalsModule(this);
injector = module.getInjector();
}
public void onDisable() {
}
}
package com.sekwah.advancedportals.core;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.sekwah.advancedportals.core.config.CoreModule;
public class AdvancedPortalsCore {
/**
* https://github.com/google/guice/wiki/GettingStarted
*
*/
private Injector injector = Guice.createInjector(new CoreModule(this));
/**
* For some platforms we could do this on construction but this just allows for a bit more control
*/
public void onEnable() {
AdvancedPortalsModule module = new AdvancedPortalsModule(this);
injector = module.getInjector();
}
public void onDisable() {
}
}

View File

@ -1,38 +1,38 @@
package com.sekwah.advancedportals.core;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.sekwah.advancedportals.core.config.Config;
import com.sekwah.advancedportals.core.config.ConfigHandler;
import javax.annotation.Nonnull;
public class AdvancedPortalsModule extends AbstractModule {
private Injector injector;
private AdvancedPortalsCore advancedPortalsCore;
public AdvancedPortalsModule(AdvancedPortalsCore advancedPortalsCore) {
this.advancedPortalsCore = advancedPortalsCore;
}
@Override
protected void configure() {
// Instances
bind(AdvancedPortalsCore.class).toInstance(advancedPortalsCore);
// Providers
bind(Config.class).toProvider(ConfigHandler.class);
}
public Injector createInjector() {
return Guice.createInjector(this);
}
@Nonnull
public Injector getInjector() {
return injector;
}
}
package com.sekwah.advancedportals.core;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.sekwah.advancedportals.core.config.Config;
import com.sekwah.advancedportals.core.config.ConfigHandler;
import javax.annotation.Nonnull;
public class AdvancedPortalsModule extends AbstractModule {
private Injector injector;
private AdvancedPortalsCore advancedPortalsCore;
public AdvancedPortalsModule(AdvancedPortalsCore advancedPortalsCore) {
this.advancedPortalsCore = advancedPortalsCore;
}
@Override
protected void configure() {
// Instances
bind(AdvancedPortalsCore.class).toInstance(advancedPortalsCore);
// Providers
bind(Config.class).toProvider(ConfigHandler.class);
}
public Injector createInjector() {
return Guice.createInjector(this);
}
@Nonnull
public Injector getInjector() {
return injector;
}
}

View File

@ -1,10 +1,10 @@
package com.sekwah.advancedportals.core.config;
import com.google.inject.Provider;
public class ConfigHandler implements Provider<Config> {
@Override
public Config get() {
return null;
}
}
package com.sekwah.advancedportals.core.config;
import com.google.inject.Provider;
public class ConfigHandler implements Provider<Config> {
@Override
public Config get() {
return null;
}
}

View File

@ -1,149 +1,149 @@
package com.sekwah.advancedportals.core.data;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.inject.Inject;
import com.sekwah.advancedportals.core.AdvancedPortalsCore;
import com.sekwah.advancedportals.util.InfoLogger;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
public class DataStorage {
private Gson gson = new GsonBuilder().setPrettyPrinting().create();
private File dataFolder;
@Inject
private AdvancedPortalsCore portalsCore;
@Inject
private InfoLogger infoLogger;
public DataStorage(File dataStorageLoc) {
this.dataFolder = dataStorageLoc;
}
/**
* Copies the default file, defaults to true to keep true to the name
*
* @param fileLoc
* @return
*/
public boolean copyDefaultFile(String fileLoc) {
return this.copyDefaultFile(fileLoc, true);
}
public void copyDefaultFiles(boolean override, String... fileLocs) {
for (String fileLoc : fileLocs) {
this.copyDefaultFile(fileLoc, override);
}
}
public <T> T loadJson(Type dataHolder, String location) {
InputStream jsonResource = this.loadResource(location);
if(jsonResource == null) {
return null;
}
BufferedReader bufReader = new BufferedReader(new InputStreamReader(jsonResource));
T object = gson.fromJson(bufReader, dataHolder);
return object;
}
public <T> T loadJson(Class<T> dataHolder, String location) {
InputStream jsonResource = this.loadResource(location);
if(jsonResource == null) {
try {
return dataHolder.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
BufferedReader bufReader = new BufferedReader(new InputStreamReader(jsonResource));
return gson.fromJson(bufReader, dataHolder);
}
public void storeJson(Object dataHolder, String location) {
String json = gson.toJson(dataHolder);
try {
FileWriter fileWriter = new FileWriter(new File(this.dataFolder, location));
fileWriter.write(json);
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Copies the specified file out of the plugin and into the plugins folder.
*
* @param fileLoc
* @return if the file is copied, will be false if override is false and the file already existed.
*/
public boolean copyDefaultFile(String fileLoc, boolean overwrite) {
File outFile = new File(this.dataFolder, fileLoc);
if (!outFile.exists()) {
outFile.getParentFile().mkdirs();
}
if (!outFile.exists() || overwrite) {
try {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileLoc);
if(inputStream == null) {
return false;
}
FileOutputStream outStream = new FileOutputStream(outFile);
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
inputStream.close();
outStream.close();
} catch (NullPointerException e) {
e.printStackTrace();
this.infoLogger.logWarning("Could not load " + fileLoc + ". The file does" +
"not exist or there has been an error reading the file.");
return false;
} catch (FileNotFoundException e) {
e.printStackTrace();
this.infoLogger.logWarning("Could not create " + fileLoc);
} catch (IOException e) {
e.printStackTrace();
this.infoLogger.logWarning("File error reading " + fileLoc);
}
}
return true;
}
/**
* A method to try to grab the files from the plugin and if its in the plugin folder load from there instead.
* <p>
* @param location
* @return
*/
public InputStream loadResource(String location) {
File inFile = new File(dataFolder, location);
if (inFile.exists() && !inFile.isDirectory()) {
try {
return new FileInputStream(inFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
} else {
try {
copyDefaultFile(location, false);
return this.getClass().getClassLoader().getResourceAsStream(location);
} catch (NullPointerException e) {
e.printStackTrace();
this.infoLogger.logWarning("Could not load " + location + ". The file does" +
"not exist or there has been an error reading the file.");
return null;
}
}
}
}
package com.sekwah.advancedportals.core.data;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.inject.Inject;
import com.sekwah.advancedportals.core.AdvancedPortalsCore;
import com.sekwah.advancedportals.util.InfoLogger;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
public class DataStorage {
private Gson gson = new GsonBuilder().setPrettyPrinting().create();
private File dataFolder;
@Inject
private AdvancedPortalsCore portalsCore;
@Inject
private InfoLogger infoLogger;
public DataStorage(File dataStorageLoc) {
this.dataFolder = dataStorageLoc;
}
/**
* Copies the default file, defaults to true to keep true to the name
*
* @param fileLoc
* @return
*/
public boolean copyDefaultFile(String fileLoc) {
return this.copyDefaultFile(fileLoc, true);
}
public void copyDefaultFiles(boolean override, String... fileLocs) {
for (String fileLoc : fileLocs) {
this.copyDefaultFile(fileLoc, override);
}
}
public <T> T loadJson(Type dataHolder, String location) {
InputStream jsonResource = this.loadResource(location);
if(jsonResource == null) {
return null;
}
BufferedReader bufReader = new BufferedReader(new InputStreamReader(jsonResource));
T object = gson.fromJson(bufReader, dataHolder);
return object;
}
public <T> T loadJson(Class<T> dataHolder, String location) {
InputStream jsonResource = this.loadResource(location);
if(jsonResource == null) {
try {
return dataHolder.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
BufferedReader bufReader = new BufferedReader(new InputStreamReader(jsonResource));
return gson.fromJson(bufReader, dataHolder);
}
public void storeJson(Object dataHolder, String location) {
String json = gson.toJson(dataHolder);
try {
FileWriter fileWriter = new FileWriter(new File(this.dataFolder, location));
fileWriter.write(json);
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Copies the specified file out of the plugin and into the plugins folder.
*
* @param fileLoc
* @return if the file is copied, will be false if override is false and the file already existed.
*/
public boolean copyDefaultFile(String fileLoc, boolean overwrite) {
File outFile = new File(this.dataFolder, fileLoc);
if (!outFile.exists()) {
outFile.getParentFile().mkdirs();
}
if (!outFile.exists() || overwrite) {
try {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileLoc);
if(inputStream == null) {
return false;
}
FileOutputStream outStream = new FileOutputStream(outFile);
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
inputStream.close();
outStream.close();
} catch (NullPointerException e) {
e.printStackTrace();
this.infoLogger.logWarning("Could not load " + fileLoc + ". The file does" +
"not exist or there has been an error reading the file.");
return false;
} catch (FileNotFoundException e) {
e.printStackTrace();
this.infoLogger.logWarning("Could not create " + fileLoc);
} catch (IOException e) {
e.printStackTrace();
this.infoLogger.logWarning("File error reading " + fileLoc);
}
}
return true;
}
/**
* A method to try to grab the files from the plugin and if its in the plugin folder load from there instead.
* <p>
* @param location
* @return
*/
public InputStream loadResource(String location) {
File inFile = new File(dataFolder, location);
if (inFile.exists() && !inFile.isDirectory()) {
try {
return new FileInputStream(inFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
} else {
try {
copyDefaultFile(location, false);
return this.getClass().getClassLoader().getResourceAsStream(location);
} catch (NullPointerException e) {
e.printStackTrace();
this.infoLogger.logWarning("Could not load " + location + ". The file does" +
"not exist or there has been an error reading the file.");
return null;
}
}
}
}

172
curse.gradle Normal file
View File

@ -0,0 +1,172 @@
import org.apache.commons.codec.Charsets
import org.apache.http.HttpResponse
import org.apache.http.client.HttpClient
import org.apache.http.client.config.CookieSpecs
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.client.methods.HttpGet
import com.google.gson.Gson
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.apache.httpcomponents:httpmime:4.5.13"
classpath "com.google.code.gson:gson:2.8.6"
classpath "org.apache.httpcomponents:httpclient:4.5.13"
}
}
apply from: 'env-variables.gradle'
static String getValueFromCurseAPI(apiKey, endpoint) {
String API_BASE_URL = 'https://minecraft.curseforge.com'
HttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
HttpGet get = new HttpGet(API_BASE_URL + endpoint)
get.setHeader('X-Api-Token', apiKey)
HttpResponse response = client.execute(get)
int statusCode = response.statusLine.statusCode
if (statusCode == 200) {
byte[] data = response.entity.content.bytes
return new String(data, Charsets.UTF_8)
} else {
if (response.getFirstHeader('content-type').value.contains('json')) {
InputStreamReader reader = new InputStreamReader(response.entity.content)
reader.close()
throw new RuntimeException("[CurseForge] Error")
} else {
throw new RuntimeException("[CurseForge] HTTP Error Code $response.statusLine.statusCode: $response.statusLine.reasonPhrase")
}
}
}
/**
* Upload a single file (in case you also want to upload the other files like source n stuff)
* @param json
* @param file
* @return
* @throws IOException
* @throws URISyntaxException
*/
UploadResponse uploadFile(Metadata metadata, File file, String apiKey, Gson gson) throws IOException, URISyntaxException {
String API_BASE_URL = 'https://minecraft.curseforge.com'
String UPLOAD_URL = "/api/projects/%s/upload-file"
// Upload
// Important info
String uploadUrl = String.format(API_BASE_URL + UPLOAD_URL, project.curse_project_id)
HttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build()
HttpPost post = new HttpPost(uploadUrl)
post.setHeader('X-Api-Token', apiKey)
// https://support.curseforge.com/en/support/solutions/articles/9000197321-curseforge-api
post.setEntity(MultipartEntityBuilder.create()
.addTextBody('metadata', gson.toJson(metadata), ContentType.APPLICATION_JSON)
.addBinaryBody('file', file)
.build())
HttpResponse response = client.execute(post)
InputStreamReader reader = new InputStreamReader(response.entity.content)
UploadResponse uploadResponse = gson.fromJson(reader, UploadResponse)
reader.close()
return uploadResponse
}
class GameVersion {
int id
int gameVersionTypeID
String name
String slug
}
/**
* As described here https://support.curseforge.com/en/support/solutions/articles/9000197321-curseforge-api
*/
class Metadata {
String changelog
String changelogType
int[] gameVersions
String releaseType
}
class UploadResponse {
int id
}
// Based on https://github.com/matthewprenger/CurseGradle as it didnt support Bukkit uploads at the time.
task curseforge {
dependsOn(jar)
doLast {
String apiKey = null
if (System.getenv("CURSE_API") != null) {
apiKey = System.getenv("CURSE_API")
}
if(apiKey != null) {
Gson gson = new Gson()
//String VERSION_TYPES_URL = "/api/game/version-types"
int gameVersionTypeID = 1
String VERSION_URL = "/api/game/versions"
println("Uploading to CurseForge")
// Get game versions
String gameVersionsString = getValueFromCurseAPI(apiKey, VERSION_URL)
GameVersion[] gameVersions = gson.fromJson(gameVersionsString, GameVersion[].class)
def versions = gameVersions.findAll {it.gameVersionTypeID == gameVersionTypeID}
String[] supportedVersions = [
"1.18",
"1.17",
"1.16",
"1.15",
"1.14",
"1.13"
]
def supportedGameVersions = versions.findAll {supportedVersions.contains(it.name)}
int[] supportedGameVersionIds = supportedGameVersions.collect {it.id}.toArray()
println("Supported Version Id's ${supportedGameVersionIds}")
Metadata uploadMetadata = new Metadata()
uploadMetadata.changelog = "${project.github}/blob/${ext.githubSha}/docs/changelogs/CHANGELOG.md"
uploadMetadata.changelogType = "markdown"
uploadMetadata.releaseType = ext.isDevBranch ? "beta" : "release"
uploadMetadata.gameVersions = supportedGameVersionIds
def uploadId = uploadFile(uploadMetadata, file(jar.archiveFile), apiKey, gson)
println("Uploaded with ID: ${uploadId.id}")
println("Published build")
} else {
println("Curse token unspecified")
}
}
// id = project.curse_project_id
// // TODO add code to reference this but also cut the latest change logs in for the files
// changelog = "${project.github}/blob/${sha}/CHANGELOG.md"
// changelogType = 'markdown'
// releaseType = 'release'
}

54
discord.gradle Normal file
View File

@ -0,0 +1,54 @@
import org.apache.http.HttpEntity
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.apache.httpcomponents:httpmime:4.5.13"
}
}
apply from: 'env-variables.gradle'
/** For pre-releases and testers to be able to try the latest commits if they want.
* If the builds start exceeding 8MB then we may want to upload to s3 instead and periodically clear.
* TODO possibly add a task that announces when builds are made?
* Though add a note that it may take a while for Curse to approve the files.
*/
task discordupload {
dependsOn(jar)
doLast {
String discordWebhook = System.getenv("DISCORD_WEBHOOK")
if(discordWebhook != null) {
println("Logging Into Discord")
CloseableHttpClient httpClient = HttpClients.createDefault()
HttpPost uploadFile = new HttpPost(discordWebhook)
MultipartEntityBuilder builder = MultipartEntityBuilder.create()
builder.addTextBody("content", "New automated dev build\n\n" +
"Current Features: <${project.github}/blob/${ext.githubSha}/docs/changelogs/SNAPSHOT_CHANGELOG.md>")
builder.addBinaryBody("file", file(jar.archiveFile).newInputStream(), ContentType.APPLICATION_OCTET_STREAM, jar.archiveName)
HttpEntity multipart = builder.build()
uploadFile.setEntity(multipart)
CloseableHttpResponse response = httpClient.execute(uploadFile)
response.getEntity()
println("Posted build")
} else {
println("Discord webhook unspecified ${sha}")
}
}
}

16
env-variables.gradle Normal file
View File

@ -0,0 +1,16 @@
def branch = System.getenv("GITHUB_REF")
if(branch != null) {
branch = branch.replace('refs/heads/', '')
}
def isRelease = System.getenv("IS_RELEASE") == "true"
def snapshotName = (branch == null || branch.startsWith("release-please")) ? "SNAPSHOT" : branch
def githubSha = System.getenv("GITHUB_SHA")
def shaRef = githubSha != null ? "-${githubSha.substring(0, 8)}" : ""
ext.branch = branch
ext.snapshotName = snapshotName
ext.githubSha = githubSha
ext.shaRef = shaRef
ext.isRelease = isRelease

168
gradlew.bat vendored
View File

@ -1,84 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -1,3 +1 @@
// Check the root build.gradle under allprojects for common settings

View File

@ -86,4 +86,3 @@ command.trans.help=Copy translation new default translation file
command.version.help=Returns the current version of the plugin
command.subcommand.nopermission= Sorry but you don't have permission for that, please use \u00A7e/%1$s help \u00A7cif you would like a list of possible sub commands.

View File

@ -43,7 +43,7 @@ command.create.complete= Le portail a bien été créé.
command.createdesti.help=Crée une destination
command.createdesti.error= Une erreur est survenue en créant la destination:
command.createdesti.console= Vous ne pouvez pas créer une destination en utilisant la console.
command.createdesti.detailedhelp=Le format est /desti create (name) [tag:tagvalue]
command.createdesti.detailedhelp=Le format est /desti create (name) [tag:tagvalue]
command.createdesti.complete= La destination a bien été créée.
command.create.tags=\u00A7aTags:

View File

@ -1,11 +1,11 @@
rootProject.name = "advanced-portals"
// Core modules
include 'core'
include 'lang'
// Implementations
include 'spigot'
// Proxies
include 'velocity'
include 'bungee'
rootProject.name = "advanced-portals"
// Core modules
include 'core'
include 'lang'
// Implementations
include 'spigot'
// Proxies
include 'velocity'
include 'bungee'

1
version.txt Normal file
View File

@ -0,0 +1 @@
0.9.2