architectury

This commit is contained in:
Flemmli97 2021-06-11 20:33:10 +02:00
parent cabe87aaf3
commit 0b9365a955
94 changed files with 1401 additions and 258 deletions

View File

@ -1,122 +1,55 @@
buildscript {
dependencies {
classpath group: 'com.diluv.schoomp', name: 'Schoomp', version: '1.1.0'
}
}
plugins {
id 'fabric-loom' version '0.4-SNAPSHOT'
id 'maven-publish'
id 'com.matthewprenger.cursegradle' version '1.4.0'
id "architectury-plugin" version "3.1-SNAPSHOT"
id "dev.architectury.loom" version "0.7.2-SNAPSHOT" apply false
}
import com.diluv.schoomp.Webhook
import com.diluv.schoomp.message.Message
import com.diluv.schoomp.message.embed.Embed
architectury {
minecraft = rootProject.minecraft_version
}
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
subprojects {
apply plugin: "dev.architectury.loom"
archivesBaseName = project.archives_base_name
version = project.minecraft_version + "-" + project.mod_version
group = project.maven_group
repositories {
mavenCentral()
jcenter()
maven {
name = 'Fabric-Permission-API'
url 'https://oss.sonatype.org/content/repositories/snapshots'
loom {
silentMojangMappingsLicense()
useFabricMixin = true
}
maven {
name = "Gunpowder"
url = "https://maven.martmists.com/releases"
}
maven {
name = 'Ladysnake Mods'
url = 'https://ladysnake.jfrog.io/artifactory/mods'
content {
includeGroup 'io.github.ladysnake'
includeGroupByRegex 'io\\.github\\.onyxstudios.*'
}
dependencies {
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
}
}
dependencies {
//to change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
allprojects {
apply plugin: "java"
apply plugin: "architectury-plugin"
apply plugin: "maven-publish"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
archivesBaseName = rootProject.archives_base_name
version = project.minecraft_version + "-"+ rootProject.mod_version
group = rootProject.maven_group
compile group: 'org.yaml', name: 'snakeyaml', version: '1.25'
include group: 'org.yaml', name: 'snakeyaml', version: '1.25'
configurations {
modOptional
modCompileOnly.extendsFrom(modOptional)
modRuntime.extendsFrom(modOptional)
modImplementation "me.lucko:fabric-permissions-api:${project.fabric_permissions_api}"
modCompileOnly "io.github.gunpowder:gunpowder-api:${gunpowder_version}+1.16.2"
modImplementation "io.github.ladysnake:PlayerAbilityLib:${project.player_ability_lib}"
}
processResources {
inputs.property "version", project.version
from(sourceSets.main.resources.srcDirs) {
include "fabric.mod.json"
expand "version": project.version
optional
compileOnly.extendsFrom(optional)
runtime.extendsFrom(optional)
}
from(sourceSets.main.resources.srcDirs) {
exclude "fabric.mod.json"
}
}
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this task, sources will not be generated.
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = "sources"
from sourceSets.main.allSource
}
jar {
from "LICENSE"
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
artifactId project.archives_base_name
version project.version
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
def targetVersion = 8
if (JavaVersion.current().isJava9Compatible()) {
options.release = targetVersion
}
}
repositories {
maven {
url "https://gitlab.com/api/v4/projects/21830712/packages/maven"
//url "https://maven.pkg.github.com/flemmli97/RuneCraftory"
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("GPR_USER")
password = project.findProperty("gpr.gitlab.token") ?: System.getenv("GPR_GITLAB_TOKEN")
//password = project.findProperty("gpr.github.token") ?: System.getenv("GPR_TOKEN")
}
}
java {
withSourcesJar()
}
}
@ -157,65 +90,4 @@ def discordChangelog() {
}
res.add(temp)
return res
}
curseforge {
apiKey = findProperty('curseApiToken') ?: 0
project {
id = "${curse_id}"
"${project.curse_versions}".split(', ').each {
addGameVersion "${it}"
}
mainArtifact(remapJar) {
changelog = changelog(3).replace("\n-", "\n\n- ")
changelogType = "markdown"
releaseType = 'release'
}
relations {
"${project.curse_dep}".split(', ').each {
requiredDependency "${it}"
}
}
}
}
tasks.getByName("curseforge").doLast {
try {
def newFileId = tasks.getByName("curseforge${project.curse_id}").property('mainArtifact').fileID
def webhook = new Webhook(findProperty('discordHook'), "${project.project_name} Upload")
def message = new Message()
def version = project.curse_versions.split(', ')[0]
message.setUsername("Release")
message.setContent("<@&852113509243682817> ${project.project_name} ${project.mod_version} for Minecraft ${version} has been released!")
def embed = new Embed()
embed.addField('Get it here (When it is accepted)', "${project.findProperty('curse_page')}/files/${newFileId}", false)
def changelog = discordChangelog()
if (changelog.size() == 1)
embed.addField('Change Log', "```md\n${changelog.get(0) ?: 'Unavailable :('}```", false)
else
changelog.forEach {
embed.addField("Change Log", "```md\n${it}```", false)
}
embed.setColor(0xFF8000)
message.addEmbed(embed)
webhook.sendMessage(message)
}
catch (IOException e) {
println 'Failed to push to the Discord webhook.'
}
}
task buildUploadAll(group: "publishing") {
dependsOn clean, build, publish, tasks.getByName("curseforge")
build.mustRunAfter clean
tasks.findByName("curseforge").mustRunAfter publish
}
tasks.getByName("curseforge").dependsOn build
publish.dependsOn build
}

15
common/build.gradle Normal file
View File

@ -0,0 +1,15 @@
dependencies {
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
// Do NOT use other classes from fabric loader
modImplementation "net.fabricmc:fabric-loader:${rootProject.loader_version}"
implementation group: 'org.yaml', name: 'snakeyaml', version: '1.25'
include group: 'org.yaml', name: 'snakeyaml', version: '1.25'
}
architectury {
common()
}
java {
withSourcesJar()
}

View File

@ -0,0 +1,28 @@
package io.github.flemmli97.flan;
import io.github.flemmli97.flan.api.PermissionRegistry;
import io.github.flemmli97.flan.config.ConfigHandler;
import net.minecraft.server.MinecraftServer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Flan {
public static final Logger logger = LogManager.getLogger("flan");
public static boolean permissionAPI, gunpowder, playerAbilityLib;
public static void lockRegistry(MinecraftServer server) {
PermissionRegistry.lock();
}
public static void log(String msg, Object... o) {
if (ConfigHandler.config.log)
Flan.logger.info(msg, o);
}
public static void debug(String msg, Object... o) {
if (ConfigHandler.config.log)
Flan.logger.debug(msg, o);
}
}

View File

@ -0,0 +1,14 @@
package io.github.flemmli97.flan.api;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos;
public class ClaimPermissionEvent {
@ExpectPlatform
public static ActionResult check(ServerPlayerEntity player, ClaimPermission permission, BlockPos pos) {
throw new AssertionError();
}
}

View File

@ -198,7 +198,7 @@ public class Claim implements IPermissionContainer {
@Override
public boolean canInteract(ServerPlayerEntity player, ClaimPermission perm, BlockPos pos, boolean message) {
ActionResult res = ClaimPermissionEvent.CHECK.invoker().check(player, perm, pos);
ActionResult res = ClaimPermissionEvent.check(player, perm, pos);
if (res != ActionResult.PASS)
return res != ActionResult.FAIL;
if (perm != null) {

View File

@ -29,7 +29,7 @@ public class LangCommands {
map.put("reload", new String[]{"reload", "Reloads the config ingame."});
map.put("adminMode", new String[]{"adminMode", "Switches to admin mode ignoring all claims."});
map.put("readGriefPrevention", new String[]{"readGriefPreventionData", "Parses data from the GriefPrevention plugin to Flan."});
map.put("readGriefPrevention", new String[]{"readGriefPreventionData", "Parses data from the GriefPrevention plugin to io.github.flemmli97.flan.Flan."});
map.put("setAdminClaim", new String[]{"setAdminClaim", "Sets a claim to an admin claim."});
map.put("listAdminClaims", new String[]{"listAdminClaim", "Lists all admin claims in the current world."});
map.put("adminDelete", new String[]{"adminDelete [all <player>]", "Force deletes the current claim or deletes all claims from the specified player."});

View File

@ -0,0 +1,19 @@
package io.github.flemmli97.flan.integration.gunpowder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import net.minecraft.server.command.ServerCommandSource;
public class CommandCurrency {
@ExpectPlatform
public static int sellClaimBlocks(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
throw new AssertionError();
}
@ExpectPlatform
public static int buyClaimBlocks(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
throw new AssertionError();
}
}

View File

@ -1,8 +1,6 @@
package io.github.flemmli97.flan.integration.permissionapi;
import io.github.flemmli97.flan.Flan;
import io.github.flemmli97.flan.config.ConfigHandler;
import me.lucko.fabric.api.permissions.v0.Permissions;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import net.minecraft.server.command.CommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
@ -47,19 +45,13 @@ public class CommandPermission {
return perm(src, perm, false);
}
@ExpectPlatform
public static boolean perm(CommandSource src, String perm, boolean adminCmd) {
if (!Flan.permissionAPI)
return !adminCmd || src.hasPermissionLevel(ConfigHandler.config.permissionLevel);
if (adminCmd)
return Permissions.check(src, perm, ConfigHandler.config.permissionLevel);
return Permissions.check(src, perm, true);
throw new AssertionError();
}
@ExpectPlatform
public static boolean perm(ServerPlayerEntity src, String perm, boolean adminCmd) {
if (!Flan.permissionAPI)
return !adminCmd || src.hasPermissionLevel(ConfigHandler.config.permissionLevel);
if (adminCmd)
return Permissions.check(src, perm, ConfigHandler.config.permissionLevel);
return Permissions.check(src, perm, true);
throw new AssertionError();
}
}

View File

@ -22,14 +22,14 @@ public class ItemEntityMixin implements IOwnedItem {
@Inject(method = "readCustomDataFromTag", at = @At("RETURN"))
private void readData(CompoundTag tag, CallbackInfo info) {
if (tag.contains("Flan:PlayerOrigin"))
this.playerOrigin = tag.getUuid("Flan:PlayerOrigin");
if (tag.contains("io.github.flemmli97.flan.Flan:PlayerOrigin"))
this.playerOrigin = tag.getUuid("io.github.flemmli97.flan.Flan:PlayerOrigin");
}
@Inject(method = "writeCustomDataToTag", at = @At("RETURN"))
private void writeData(CompoundTag tag, CallbackInfo info) {
if (this.playerOrigin != null)
tag.putUuid("Flan:PlayerOrigin", this.playerOrigin);
tag.putUuid("io.github.flemmli97.flan.Flan:PlayerOrigin", this.playerOrigin);
}
@Override

187
fabric/build.gradle Normal file
View File

@ -0,0 +1,187 @@
buildscript {
dependencies {
classpath group: 'com.diluv.schoomp', name: 'Schoomp', version: '1.1.0'
}
}
plugins {
id 'com.matthewprenger.cursegradle' version '1.4.0'
id "com.github.johnrengelman.shadow" version "5.0.0"
}
import com.diluv.schoomp.Webhook
import com.diluv.schoomp.message.Message
import com.diluv.schoomp.message.embed.Embed
configurations {
shadowCommon // Don't use shadow from the shadow plugin because we don't want IDEA to index this.
}
architectury {
platformSetupLoomIde()
fabric()
}
repositories {
mavenCentral()
maven {
name = 'Fabric-Permission-API'
url 'https://oss.sonatype.org/content/repositories/snapshots'
}
maven {
name = "Gunpowder"
url = "https://maven.martmists.com/releases"
}
maven {
name = 'Ladysnake Mods'
url = 'https://ladysnake.jfrog.io/artifactory/mods'
content {
includeGroup 'io.github.ladysnake'
includeGroupByRegex 'io\\.github\\.onyxstudios.*'
}
}
}
dependencies {
modImplementation "net.fabricmc:fabric-loader:${rootProject.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_version}"
modImplementation "me.lucko:fabric-permissions-api:${rootProject.fabric_permissions_api}"
modCompileOnly "io.github.gunpowder:gunpowder-api:${rootProject.gunpowder_version}+1.16.2"
modImplementation "io.github.ladysnake:PlayerAbilityLib:${rootProject.player_ability_lib}"
implementation(project(path: ":common")) {
transitive = false
}
developmentFabric(project(path: ":common")) {
transitive = false
}
shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) {
transitive = false
}
}
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
shadowJar {
configurations = [project.configurations.shadowCommon]
classifier "dev-shadow"
}
remapJar {
input.set shadowJar.archiveFile
dependsOn shadowJar
classifier "fabric"
}
jar {
classifier "dev"
}
java {
withSourcesJar()
}
sourcesJar {
def commonSources = project(":common").sourcesJar
dependsOn commonSources
from commonSources.archiveFile.map { zipTree(it) }
}
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
artifactId project.archives_base_name
version project.version
}
}
repositories {
maven {
url "https://gitlab.com/api/v4/projects/21830712/packages/maven"
//url "https://maven.pkg.github.com/flemmli97/<>"
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("GPR_USER")
password = project.findProperty("gpr.gitlab.token") ?: System.getenv("GPR_GITLAB_TOKEN")
//password = project.findProperty("gpr.github.token") ?: System.getenv("GPR_TOKEN")
}
}
}
}
curseforge {
apiKey = findProperty('curseApiToken') ?: 0
project {
id = "${curse_id_fabric}"
"${project.curse_versions}".split(', ').each {
addGameVersion "${it}"
}
addGameVersion "Fabric"
mainArtifact(remapJar) {
changelog = changelog(3).replace("\n-", "\n\n- ")
changelogType = "markdown"
releaseType = 'release'
}
relations {
"${project.curse_dep_fabric}".split(', ').each {
requiredDependency "${it}"
}
}
}
}
tasks.getByName("curseforge").doLast {
try {
def fileID = tasks.getByName("curseforge${project.curse_id_fabric}").property('mainArtifact').fileID
def webhook = new Webhook(findProperty('discordHook'), "${project.project_name} Upload")
def message = new Message()
def version = project.curse_versions.split(', ')[0]
message.setUsername("Release")
message.setContent("<@&852113509243682817> ${project.project_name} ${project.mod_version} for Minecraft ${version} has been released!")
def embed = new Embed()
embed.addField('Get it here (When it is accepted)', "${project.findProperty('curse_page_fabric')}/files/${fileID}", false)
def changelog = discordChangelog()
if (changelog.size() == 1)
embed.addField('Change Log', "```md\n${changelog.get(0) ?: 'Unavailable :('}```", false)
else
changelog.forEach {
embed.addField("Change Log", "```md\n${it}```", false)
}
embed.setColor(0xFF8000)
message.addEmbed(embed)
webhook.sendMessage(message)
}
catch (IOException e) {
println 'Failed to push to the Discord webhook.'
}
}
task buildUploadAll(group: "publishing") {
dependsOn clean, build, publish, tasks.getByName("curseforge")
build.mustRunAfter clean
tasks.findByName("curseforge").mustRunAfter publish
}
tasks.getByName("curseforge").dependsOn build
publish.dependsOn build

View File

@ -1,6 +1,5 @@
package io.github.flemmli97.flan;
import io.github.flemmli97.flan.api.PermissionRegistry;
import io.github.flemmli97.flan.claim.ObjectToPermissionMap;
import io.github.flemmli97.flan.commands.CommandClaim;
import io.github.flemmli97.flan.config.ConfigHandler;
@ -17,15 +16,8 @@ import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.server.MinecraftServer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Flan implements ModInitializer {
public static final Logger logger = LogManager.getLogger("flan");
public static boolean permissionAPI, gunpowder, playerAbilityLib;
public class FlanFabric implements ModInitializer {
@Override
public void onInitialize() {
@ -36,28 +28,14 @@ public class Flan implements ModInitializer {
UseItemCallback.EVENT.register(ItemInteractEvents::useItem);
ServerLifecycleEvents.SERVER_STARTING.register(ConfigHandler::serverLoad);
ServerLifecycleEvents.SERVER_STARTING.register(ObjectToPermissionMap::reload);
ServerLifecycleEvents.SERVER_STARTING.register(this::lockRegistry);
ServerLifecycleEvents.SERVER_STARTING.register(Flan::lockRegistry);
CommandRegistrationCallback.EVENT.register(CommandClaim::register);
permissionAPI = FabricLoader.getInstance().isModLoaded("fabric-permissions-api-v0");
gunpowder = FabricLoader.getInstance().isModLoaded("gunpowder-currency");
playerAbilityLib = FabricLoader.getInstance().isModLoaded("playerabilitylib");
if (playerAbilityLib)
Flan.permissionAPI = FabricLoader.getInstance().isModLoaded("fabric-permissions-api-v0");
Flan.gunpowder = FabricLoader.getInstance().isModLoaded("gunpowder-currency");
Flan.playerAbilityLib = FabricLoader.getInstance().isModLoaded("playerabilitylib");
if (Flan.playerAbilityLib)
PlayerAbilityEvents.register();
}
public void lockRegistry(MinecraftServer server) {
PermissionRegistry.lock();
}
public static void log(String msg, Object... o) {
if (ConfigHandler.config.log)
logger.info(msg, o);
}
public static void debug(String msg, Object... o) {
if (ConfigHandler.config.log)
logger.debug(msg, o);
}
}

View File

@ -0,0 +1,43 @@
package io.github.flemmli97.flan.api.fabric;
import io.github.flemmli97.flan.api.ClaimPermission;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos;
public class ClaimPermissionEventImpl {
public interface PermissionCheck {
/**
* Callback for when permissions are checked
*
* @param player The corresponding player. Can be null if the check is e.g. caused by tnt explosions
* @param permission The permission to check
* @param pos The block pos where the action is occuring
* @return ActionResult#PASS to do nothing. ActionResult#FAIL to prevent the action. Else to allow the action
*/
ActionResult check(ServerPlayerEntity player, ClaimPermission permission, BlockPos pos);
}
public static Event<PermissionCheck> CHECK = EventFactory.createArrayBacked(PermissionCheck.class,
(listeners) -> (player, permission, pos) -> {
for (PermissionCheck event : listeners) {
ActionResult result = event.check(player, permission, pos);
if (result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
}
);
public static ActionResult check(ServerPlayerEntity player, ClaimPermission permission, BlockPos pos) {
return CHECK.invoker().check(player, permission, pos);
}
}

View File

@ -1,4 +1,4 @@
package io.github.flemmli97.flan.integration.gunpowder;
package io.github.flemmli97.flan.integration.gunpowder.fabric;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.IntegerArgumentType;
@ -16,7 +16,7 @@ import net.minecraft.util.Formatting;
import java.math.BigDecimal;
public class CommandCurrency {
public class CommandCurrencyImpl {
public static int sellClaimBlocks(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
if (!Flan.gunpowder) {

View File

@ -0,0 +1,26 @@
package io.github.flemmli97.flan.integration.permissionapi.fabric;
import io.github.flemmli97.flan.Flan;
import io.github.flemmli97.flan.config.ConfigHandler;
import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.server.command.CommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
public class CommandPermissionImpl {
public static boolean perm(CommandSource src, String perm, boolean adminCmd) {
if (!Flan.permissionAPI)
return !adminCmd || src.hasPermissionLevel(ConfigHandler.config.permissionLevel);
if (adminCmd)
return Permissions.check(src, perm, ConfigHandler.config.permissionLevel);
return Permissions.check(src, perm, true);
}
public static boolean perm(ServerPlayerEntity src, String perm, boolean adminCmd) {
if (!Flan.permissionAPI)
return !adminCmd || src.hasPermissionLevel(ConfigHandler.config.permissionLevel);
if (adminCmd)
return Permissions.check(src, perm, ConfigHandler.config.permissionLevel);
return Permissions.check(src, perm, true);
}
}

View File

@ -16,7 +16,7 @@
"environment": "*",
"entrypoints": {
"main": [
"io.github.flemmli97.flan.Flan"
"io.github.flemmli97.flan.FlanFabric"
]
},
"mixins": [

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

168
forge/build.gradle Normal file
View File

@ -0,0 +1,168 @@
buildscript {
dependencies {
classpath group: 'com.diluv.schoomp', name: 'Schoomp', version: '1.1.0'
}
}
plugins {
id 'com.matthewprenger.cursegradle' version '1.4.0'
id "com.github.johnrengelman.shadow" version "5.0.0"
}
import com.diluv.schoomp.Webhook
import com.diluv.schoomp.message.Message
import com.diluv.schoomp.message.embed.Embed
configurations {
shadowCommon // Don't use shadow from the shadow plugin because we don't want IDEA to index this.
}
architectury {
platformSetupLoomIde()
forge()
}
loom {
//mixinConfigs = ["flan.mixins.json"]
useFabricMixin = true
}
dependencies {
forge "net.minecraftforge:forge:${rootProject.minecraft_version}-${rootProject.forge_version}"
implementation(project(path: ":common")) {
transitive = false
}
developmentForge(project(path: ":common")) {
transitive = false
}
shadowCommon(project(path: ":common", configuration: "transformProductionForge")) {
transitive = false
}
}
processResources {
inputs.property "version", project.version
filesMatching("META-INF/mods.toml") {
expand "version": project.version
}
}
shadowJar {
exclude "fabric.mod.json"
configurations = [project.configurations.shadowCommon]
classifier "dev-shadow"
}
remapJar {
input.set shadowJar.archiveFile
dependsOn shadowJar
classifier "forge"
}
jar {
classifier "dev"
}
java {
withSourcesJar()
}
sourcesJar {
def commonSources = project(":common").sourcesJar
dependsOn commonSources
from commonSources.archiveFile.map { zipTree(it) }
}
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
artifactId project.archives_base_name
version project.version
}
}
repositories {
maven {
url "https://gitlab.com/api/v4/projects/21830712/packages/maven"
//url "https://maven.pkg.github.com/flemmli97/<>"
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("GPR_USER")
password = project.findProperty("gpr.gitlab.token") ?: System.getenv("GPR_GITLAB_TOKEN")
//password = project.findProperty("gpr.github.token") ?: System.getenv("GPR_TOKEN")
}
}
}
}
curseforge {
apiKey = findProperty('curseApiToken') ?: 0
project {
id = "${curse_id_forge}"
"${project.curse_versions}".split(', ').each {
addGameVersion "${it}"
}
addGameVersion "Fabric"
mainArtifact(remapJar) {
changelog = changelog(3).replace("\n-", "\n\n- ")
changelogType = "markdown"
releaseType = 'release'
}
/*relations {
"${project.curse_dep_forge}".split(', ').each {
requiredDependency "${it}"
}
}*/
}
}
tasks.getByName("curseforge").doLast {
try {
def fileID = tasks.getByName("curseforge${project.curse_id_forge}").property('mainArtifact').fileID
def webhook = new Webhook(findProperty('discordHook'), "${project.project_name} Upload")
def message = new Message()
def version = project.curse_versions.split(', ')[0]
message.setUsername("Release")
message.setContent("<@&852113509243682817> ${project.project_name} (Forge) ${project.mod_version} for Minecraft ${version} has been released!")
def embed = new Embed()
embed.addField('Get it here (When it is accepted)', "${project.findProperty('curse_page_forge')}/files/${fileID}", false)
def changelog = discordChangelog()
if (changelog.size() == 1)
embed.addField('Change Log', "```md\n${changelog.get(0) ?: 'Unavailable :('}```", false)
else
changelog.forEach {
embed.addField("Change Log", "```md\n${it}```", false)
}
embed.setColor(0xFF8000)
message.addEmbed(embed)
webhook.sendMessage(message)
}
catch (IOException e) {
println 'Failed to push to the Discord webhook.'
}
}
task buildUploadAll(group: "publishing") {
dependsOn clean, build, publish, tasks.getByName("curseforge")
build.mustRunAfter clean
tasks.findByName("curseforge").mustRunAfter publish
}
tasks.getByName("curseforge").dependsOn build
publish.dependsOn build

1
forge/gradle.properties Normal file
View File

@ -0,0 +1 @@
loom.platform=forge

View File

@ -0,0 +1,22 @@
package io.github.flemmli97.flan;
import io.github.flemmli97.flan.forgeevent.WorldEventsForge;
import net.minecraft.world.explosion.Explosion;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.common.Mod;
@Mod(FlanForge.MODID)
public class FlanForge {
public static final String MODID = "flan";
public FlanForge() {
IEventBus forge = MinecraftForge.EVENT_BUS;
forge.addListener(WorldEventsForge::modifyExplosion);
forge.addListener(WorldEventsForge::pistonCanPush);
forge.addListener(WorldEventsForge::preventMobSpawn);
}
}

View File

@ -0,0 +1,16 @@
package io.github.flemmli97.flan.api.forge;
import io.github.flemmli97.flan.api.ClaimPermission;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.MinecraftForge;
public class ClaimPermissionEventImpl {
public static ActionResult check(ServerPlayerEntity player, ClaimPermission permission, BlockPos pos) {
PermissionCheckEvent event = new PermissionCheckEvent(player, permission, pos);
MinecraftForge.EVENT_BUS.post(event);
return event.getActionResult();
}
}

View File

@ -0,0 +1,29 @@
package io.github.flemmli97.flan.api.forge;
import io.github.flemmli97.flan.api.ClaimPermission;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.eventbus.api.Event;
public class PermissionCheckEvent extends Event {
public final ServerPlayerEntity player;
public final ClaimPermission permission;
public final BlockPos pos;
private ActionResult result = ActionResult.PASS;
public PermissionCheckEvent(ServerPlayerEntity player, ClaimPermission permission, BlockPos pos) {
this.player = player;
this.permission = permission;
this.pos = pos;
}
public ActionResult getActionResult() {
return this.result;
}
public void setResult(ActionResult result) {
this.result = result;
}
}

View File

@ -0,0 +1,214 @@
package io.github.flemmli97.flan.forgeevent;
import io.github.flemmli97.flan.api.ClaimPermission;
import io.github.flemmli97.flan.api.PermissionRegistry;
import io.github.flemmli97.flan.claim.ClaimStorage;
import io.github.flemmli97.flan.claim.IPermissionContainer;
import io.github.flemmli97.flan.claim.ObjectToPermissionMap;
import io.github.flemmli97.flan.config.ConfigHandler;
import io.github.flemmli97.flan.gui.LockedLecternScreenHandler;
import io.github.flemmli97.flan.player.EnumDisplayType;
import io.github.flemmli97.flan.player.PlayerClaimData;
import net.minecraft.block.BlockState;
import net.minecraft.block.DoorBlock;
import net.minecraft.block.InventoryProvider;
import net.minecraft.block.LecternBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.LecternBlockEntity;
import net.minecraft.block.enums.DoubleBlockHalf;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
public class BlockInteractEvents {
public static boolean breakBlocks(World world, PlayerEntity p, BlockPos pos, BlockState state, BlockEntity tile) {
if (world.isClient || p.isSpectator())
return true;
ServerPlayerEntity player = (ServerPlayerEntity) p;
ClaimStorage storage = ClaimStorage.get((ServerWorld) world);
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim != null) {
Identifier id = Registry.BLOCK.getId(state.getBlock());
if (alwaysAllowBlock(id, world.getBlockEntity(pos)))
return true;
if (!claim.canInteract(player, PermissionRegistry.BREAK, pos, true)) {
PlayerClaimData.get(player).addDisplayClaim(claim, EnumDisplayType.MAIN, player.getBlockPos().getY());
return false;
}
}
return true;
}
//Right click block
public static ActionResult useBlocks(PlayerEntity p, World world, Hand hand, BlockHitResult hitResult) {
if (world.isClient)
return ActionResult.PASS;
ServerPlayerEntity player = (ServerPlayerEntity) p;
ItemStack stack = player.getStackInHand(hand);
if (stack.getItem() == ConfigHandler.config.claimingItem) {
ItemInteractEventsForge.claimLandHandling(player, hitResult.getBlockPos());
return ActionResult.SUCCESS;
}
if (stack.getItem() == ConfigHandler.config.inspectionItem) {
ItemInteractEventsForge.inspect(player, hitResult.getBlockPos());
return ActionResult.SUCCESS;
}
ClaimStorage storage = ClaimStorage.get((ServerWorld) world);
IPermissionContainer claim = storage.getForPermissionCheck(hitResult.getBlockPos());
if (claim != null) {
boolean emptyHand = !player.getMainHandStack().isEmpty() || !player.getOffHandStack().isEmpty();
boolean cancelBlockInteract = player.shouldCancelInteraction() && emptyHand;
if (!cancelBlockInteract) {
BlockState state = world.getBlockState(hitResult.getBlockPos());
Identifier id = Registry.BLOCK.getId(state.getBlock());
BlockEntity blockEntity = world.getBlockEntity(hitResult.getBlockPos());
if (alwaysAllowBlock(id, blockEntity))
return ActionResult.PASS;
ClaimPermission perm = ObjectToPermissionMap.getFromBlock(state.getBlock());
if (perm == PermissionRegistry.PROJECTILES)
perm = PermissionRegistry.OPENCONTAINER;
//Pressureplate handled elsewhere
if (perm != null && perm != PermissionRegistry.PRESSUREPLATE) {
if (claim.canInteract(player, perm, hitResult.getBlockPos(), true))
return ActionResult.PASS;
if (state.getBlock() instanceof DoorBlock) {
DoubleBlockHalf half = state.get(DoorBlock.HALF);
if (half == DoubleBlockHalf.LOWER) {
BlockState other = world.getBlockState(hitResult.getBlockPos().up());
player.networkHandler.sendPacket(new BlockUpdateS2CPacket(hitResult.getBlockPos().up(), other));
} else {
BlockState other = world.getBlockState(hitResult.getBlockPos().down());
player.networkHandler.sendPacket(new BlockUpdateS2CPacket(hitResult.getBlockPos().down(), other));
}
}
PlayerClaimData.get(player).addDisplayClaim(claim, EnumDisplayType.MAIN, player.getBlockPos().getY());
return ActionResult.FAIL;
}
if (blockEntity != null) {
if (blockEntity instanceof LecternBlockEntity) {
if (claim.canInteract(player, PermissionRegistry.LECTERNTAKE, hitResult.getBlockPos(), false))
return ActionResult.PASS;
if (state.get(LecternBlock.HAS_BOOK))
LockedLecternScreenHandler.create(player, (LecternBlockEntity) blockEntity);
return ActionResult.FAIL;
}
if (!ConfigHandler.config.lenientBlockEntityCheck || blockEntity instanceof Inventory || blockEntity instanceof InventoryProvider) {
if (claim.canInteract(player, PermissionRegistry.OPENCONTAINER, hitResult.getBlockPos(), true))
return ActionResult.PASS;
PlayerClaimData.get(player).addDisplayClaim(claim, EnumDisplayType.MAIN, player.getBlockPos().getY());
return ActionResult.FAIL;
}
}
}
}
return ActionResult.PASS;
}
public static boolean alwaysAllowBlock(Identifier id, BlockEntity blockEntity) {
return ConfigHandler.config.ignoredBlocks.contains(id.toString())
|| (blockEntity != null
&& ConfigHandler.config.blockEntityTagIgnore.stream().anyMatch(blockEntity.toTag(new CompoundTag())::contains));
}
public static boolean cancelEntityBlockCollision(BlockState state, World world, BlockPos pos, Entity entity) {
if (world.isClient)
return false;
ServerPlayerEntity player = null;
if (entity instanceof ServerPlayerEntity)
player = (ServerPlayerEntity) entity;
else if (entity instanceof ProjectileEntity) {
Entity owner = ((ProjectileEntity) entity).getOwner();
if (owner instanceof ServerPlayerEntity)
player = (ServerPlayerEntity) owner;
} else if (entity instanceof ItemEntity) {
Entity owner = ((ServerWorld) world).getEntity(((ItemEntity) entity).getThrower());
if (owner instanceof ServerPlayerEntity)
player = (ServerPlayerEntity) owner;
}
if (player == null)
return false;
ClaimPermission perm = ObjectToPermissionMap.getFromBlock(state.getBlock());
if (perm == null)
return false;
if (perm != PermissionRegistry.PRESSUREPLATE && perm != PermissionRegistry.PORTAL)
return false;
ClaimStorage storage = ClaimStorage.get((ServerWorld) world);
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim != null)
return !claim.canInteract(player, perm, pos, false);
return false;
}
public static boolean preventFallOn(Entity entity, double heightDifference, boolean onGround, BlockState landedState, BlockPos landedPosition) {
if (entity.world.isClient)
return false;
if (entity instanceof ServerPlayerEntity) {
ClaimPermission perm = ObjectToPermissionMap.getFromBlock(landedState.getBlock());
if (perm != PermissionRegistry.TRAMPLE)
return false;
ClaimStorage storage = ClaimStorage.get((ServerWorld) entity.world);
IPermissionContainer claim = storage.getForPermissionCheck(landedPosition);
if (claim == null)
return false;
return !claim.canInteract((ServerPlayerEntity) entity, perm, landedPosition, true);
} else if (entity instanceof ProjectileEntity) {
Entity owner = ((ProjectileEntity) entity).getOwner();
if (owner instanceof ServerPlayerEntity) {
ClaimPermission perm = ObjectToPermissionMap.getFromBlock(landedState.getBlock());
if (perm != PermissionRegistry.TRAMPLE)
return false;
ClaimStorage storage = ClaimStorage.get((ServerWorld) entity.world);
IPermissionContainer claim = storage.getForPermissionCheck(landedPosition);
return !claim.canInteract((ServerPlayerEntity) owner, perm, landedPosition, true);
}
}
return false;
}
public static boolean canBreakTurtleEgg(World world, BlockPos pos, Entity entity) {
if (world.isClient)
return false;
ServerWorld serverWorld = (ServerWorld) world;
if (entity instanceof ServerPlayerEntity) {
ClaimStorage storage = ClaimStorage.get(serverWorld);
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim == null)
return false;
return !claim.canInteract((ServerPlayerEntity) entity, PermissionRegistry.TRAMPLE, pos, true);
} else if (entity instanceof ProjectileEntity) {
Entity owner = ((ProjectileEntity) entity).getOwner();
if (owner instanceof ServerPlayerEntity) {
ClaimStorage storage = ClaimStorage.get(serverWorld);
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim == null)
return false;
return !claim.canInteract((ServerPlayerEntity) owner, PermissionRegistry.TRAMPLE, pos, true);
}
} else if (entity instanceof ItemEntity) {
Entity owner = serverWorld.getEntity(((ItemEntity) entity).getThrower());
if (owner instanceof ServerPlayerEntity) {
ClaimStorage storage = ClaimStorage.get(serverWorld);
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim == null)
return false;
return !claim.canInteract((ServerPlayerEntity) owner, PermissionRegistry.TRAMPLE, pos, true);
}
}
return false;
}
}

View File

@ -0,0 +1,330 @@
package io.github.flemmli97.flan.forgeevent;
import io.github.flemmli97.flan.api.ClaimPermission;
import io.github.flemmli97.flan.api.PermissionRegistry;
import io.github.flemmli97.flan.claim.Claim;
import io.github.flemmli97.flan.claim.ClaimStorage;
import io.github.flemmli97.flan.claim.IPermissionContainer;
import io.github.flemmli97.flan.claim.ObjectToPermissionMap;
import io.github.flemmli97.flan.config.ConfigHandler;
import io.github.flemmli97.flan.mixin.IPersistentProjectileVars;
import io.github.flemmli97.flan.player.IOwnedItem;
import io.github.flemmli97.flan.player.PlayerClaimData;
import io.github.flemmli97.flan.player.TeleportUtils;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.boss.WitherEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.entity.decoration.ItemFrameEntity;
import net.minecraft.entity.mob.EndermanEntity;
import net.minecraft.entity.mob.Monster;
import net.minecraft.entity.passive.SnowGolemEntity;
import net.minecraft.entity.passive.TameableEntity;
import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.entity.projectile.thrown.EggEntity;
import net.minecraft.entity.projectile.thrown.EnderPearlEntity;
import net.minecraft.entity.projectile.thrown.PotionEntity;
import net.minecraft.entity.vehicle.AbstractMinecartEntity;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.entity.vehicle.StorageMinecartEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.s2c.play.InventoryS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerAbilitiesS2CPacket;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import java.util.function.Consumer;
public class EntityInteractEvents {
public static ActionResult attackEntity(PlayerEntity player, World world, Hand hand, Entity entity, EntityHitResult hitResult) {
return attackSimple(player, entity, true);
}
public static ActionResult useAtEntity(PlayerEntity player, World world, Hand hand, Entity entity, /* Nullable */ EntityHitResult hitResult) {
if (player.world.isClient || player.isSpectator() || canInteract(entity))
return ActionResult.PASS;
ClaimStorage storage = ClaimStorage.get((ServerWorld) world);
BlockPos pos = entity.getBlockPos();
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim != null) {
if (entity instanceof ArmorStandEntity) {
if (!claim.canInteract((ServerPlayerEntity) player, PermissionRegistry.ARMORSTAND, pos, true))
return ActionResult.FAIL;
}
}
return ActionResult.PASS;
}
public static ActionResult useEntity(PlayerEntity p, World world, Hand hand, Entity entity) {
if (p.world.isClient || p.isSpectator() || canInteract(entity))
return ActionResult.PASS;
ServerPlayerEntity player = (ServerPlayerEntity) p;
ClaimStorage storage = ClaimStorage.get((ServerWorld) world);
BlockPos pos = entity.getBlockPos();
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim != null) {
if (entity instanceof BoatEntity)
return claim.canInteract(player, PermissionRegistry.BOAT, pos, true) ? ActionResult.PASS : ActionResult.FAIL;
if (entity instanceof AbstractMinecartEntity) {
if (entity instanceof StorageMinecartEntity)
return claim.canInteract(player, PermissionRegistry.OPENCONTAINER, pos, true) ? ActionResult.PASS : ActionResult.FAIL;
return claim.canInteract(player, PermissionRegistry.MINECART, pos, true) ? ActionResult.PASS : ActionResult.FAIL;
}
if (entity instanceof VillagerEntity)
return claim.canInteract(player, PermissionRegistry.TRADING, pos, true) ? ActionResult.PASS : ActionResult.FAIL;
if (entity instanceof ItemFrameEntity)
return claim.canInteract(player, PermissionRegistry.ITEMFRAMEROTATE, pos, true) ? ActionResult.PASS : ActionResult.FAIL;
if (entity instanceof TameableEntity) {
TameableEntity tame = (TameableEntity) entity;
if (tame.isOwner(player))
return ActionResult.PASS;
}
return claim.canInteract(player, PermissionRegistry.ANIMALINTERACT, pos, true) ? ActionResult.PASS : ActionResult.FAIL;
}
return ActionResult.PASS;
}
public static boolean canInteract(Entity entity) {
return entity.getScoreboardTags().stream().anyMatch(ConfigHandler.config.entityTagIgnore::contains);
}
public static boolean projectileHit(ProjectileEntity proj, HitResult res) {
if (proj.world.isClient)
return false;
Entity owner = proj.getOwner();
if (owner instanceof ServerPlayerEntity) {
ServerPlayerEntity player = (ServerPlayerEntity) owner;
if (res.getType() == HitResult.Type.BLOCK) {
BlockHitResult blockRes = (BlockHitResult) res;
BlockPos pos = blockRes.getBlockPos();
BlockState state = proj.world.getBlockState(pos);
ClaimPermission perm;
if (proj instanceof EnderPearlEntity)
perm = PermissionRegistry.ENDERPEARL;
else if (proj instanceof EggEntity || proj instanceof PotionEntity)
perm = PermissionRegistry.PROJECTILES;
else
perm = ObjectToPermissionMap.getFromBlock(state.getBlock());
if (perm != PermissionRegistry.ENDERPEARL && perm != PermissionRegistry.TARGETBLOCK && perm != PermissionRegistry.PROJECTILES)
return false;
ClaimStorage storage = ClaimStorage.get((ServerWorld) proj.world);
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim == null)
return false;
boolean flag = !claim.canInteract(player, perm, pos, true);
if (flag) {
if (proj instanceof PersistentProjectileEntity) {
PersistentProjectileEntity pers = (PersistentProjectileEntity) proj;
((IPersistentProjectileVars) pers).setInBlockState(pers.world.getBlockState(pos));
Vec3d vec3d = blockRes.getPos().subtract(pers.getX(), pers.getY(), pers.getZ());
pers.setVelocity(vec3d);
Vec3d vec3d2 = vec3d.normalize().multiply(0.05000000074505806D);
pers.setPos(pers.getX() - vec3d2.x, pers.getY() - vec3d2.y, pers.getZ() - vec3d2.z);
pers.playSound(((IPersistentProjectileVars) pers).getSoundEvent(), 1.0F, 1.2F / (pers.world.random.nextFloat() * 0.2F + 0.9F));
((IPersistentProjectileVars) pers).setInGround(true);
pers.shake = 7;
pers.setCritical(false);
pers.setPierceLevel((byte) 0);
pers.setSound(SoundEvents.ENTITY_ARROW_HIT);
pers.setShotFromCrossbow(false);
((IPersistentProjectileVars) pers).resetPiercingStatus();
}
//TODO: find a way to properly update chorus fruit break on hit
//player.getServer().send(new ServerTask(player.getServer().getTicks()+2, ()->player.world.updateListeners(pos, state, state, 2)));
}
return flag;
} else if (res.getType() == HitResult.Type.ENTITY) {
if (proj instanceof EnderPearlEntity) {
ClaimStorage storage = ClaimStorage.get((ServerWorld) proj.world);
IPermissionContainer claim = storage.getForPermissionCheck(proj.getBlockPos());
return claim.canInteract(player, PermissionRegistry.ENDERPEARL, proj.getBlockPos(), true);
}
Entity hit = ((EntityHitResult) res).getEntity();
boolean fail = attackSimple(player, hit, true) != ActionResult.PASS;
if (fail && proj instanceof PersistentProjectileEntity && ((PersistentProjectileEntity) proj).getPierceLevel() > 0) {
PersistentProjectileEntity pers = (PersistentProjectileEntity) proj;
IntOpenHashSet pierced = ((IPersistentProjectileVars) pers).getPiercedEntities();
if (pierced == null)
pierced = new IntOpenHashSet(5);
pierced.add(hit.getEntityId());
((IPersistentProjectileVars) pers).setPiercedEntities(pierced);
pers.setPierceLevel((byte) (pers.getPierceLevel() + 1));
}
return fail;
}
}
return false;
}
public static boolean preventDamage(Entity entity, DamageSource source) {
if (source.getAttacker() instanceof ServerPlayerEntity)
return attackSimple((ServerPlayerEntity) source.getAttacker(), entity, true) != ActionResult.PASS;
else if (source.isExplosive() && !entity.world.isClient) {
IPermissionContainer claim = ClaimStorage.get((ServerWorld) entity.world).getForPermissionCheck(entity.getBlockPos());
return claim != null && !claim.canInteract(null, PermissionRegistry.EXPLOSIONS, entity.getBlockPos());
}
return false;
}
public static ActionResult attackSimple(PlayerEntity p, Entity entity, boolean message) {
if (p.world.isClient || p.isSpectator() || canInteract(entity))
return ActionResult.PASS;
if (entity instanceof Monster)
return ActionResult.PASS;
ServerPlayerEntity player = (ServerPlayerEntity) p;
ClaimStorage storage = ClaimStorage.get(player.getServerWorld());
BlockPos pos = entity.getBlockPos();
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim != null) {
if (!(entity instanceof LivingEntity))
return claim.canInteract(player, PermissionRegistry.BREAKNONLIVING, pos, message) ? ActionResult.PASS : ActionResult.FAIL;
if (entity instanceof PlayerEntity)
return claim.canInteract(player, PermissionRegistry.HURTPLAYER, pos, message) ? ActionResult.PASS : ActionResult.FAIL;
return claim.canInteract(player, PermissionRegistry.HURTANIMAL, pos, message) ? ActionResult.PASS : ActionResult.FAIL;
}
return ActionResult.PASS;
}
public static boolean xpAbsorb(PlayerEntity player) {
if (player instanceof ServerPlayerEntity) {
ClaimStorage storage = ClaimStorage.get((ServerWorld) player.world);
BlockPos pos = player.getBlockPos();
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim != null)
return !claim.canInteract((ServerPlayerEntity) player, PermissionRegistry.XP, pos, false);
}
return false;
}
public static boolean canCollideWith(PlayerEntity player, Entity entity) {
if (player instanceof ServerPlayerEntity) {
ServerPlayerEntity sPlayer = (ServerPlayerEntity) player;
if (entity instanceof ItemEntity) {
IOwnedItem ownedItem = (IOwnedItem) entity;
if (ownedItem.getDeathPlayer() != null && ConfigHandler.config.lockDrops) {
ServerPlayerEntity other = sPlayer.getServer().getPlayerManager().getPlayer(ownedItem.getDeathPlayer());
if (other == null)
return false;
return ownedItem.getDeathPlayer().equals(player.getUuid()) || PlayerClaimData.get(other).deathItemsUnlocked();
}
if (sPlayer.getUuid().equals(ownedItem.getPlayerOrigin()))
return true;
ClaimStorage storage = ClaimStorage.get(sPlayer.getServerWorld());
BlockPos pos = sPlayer.getBlockPos();
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim != null)
return claim.canInteract(sPlayer, PermissionRegistry.PICKUP, pos, false);
}
}
return true;
}
public static boolean canDropItem(PlayerEntity player, ItemStack stack) {
if (!player.isDead() && player instanceof ServerPlayerEntity) {
ClaimStorage storage = ClaimStorage.get((ServerWorld) player.world);
BlockPos pos = player.getBlockPos();
IPermissionContainer claim = storage.getForPermissionCheck(pos);
boolean allow = true;
if (claim != null)
allow = claim.canInteract((ServerPlayerEntity) player, PermissionRegistry.DROP, pos, false);
if (!allow) {
player.inventory.insertStack(stack);
DefaultedList<ItemStack> stacks = DefaultedList.of();
for (int j = 0; j < player.currentScreenHandler.slots.size(); ++j) {
ItemStack itemStack2 = player.currentScreenHandler.slots.get(j).getStack();
stacks.add(itemStack2.isEmpty() ? ItemStack.EMPTY : itemStack2);
}
((ServerPlayerEntity) player).networkHandler.sendPacket(new InventoryS2CPacket(player.currentScreenHandler.syncId, stacks));
}
return allow;
}
return true;
}
public static boolean witherCanDestroy(WitherEntity wither) {
if (wither.world.isClient)
return true;
ClaimStorage storage = ClaimStorage.get((ServerWorld) wither.world);
BlockPos.Mutable pos = wither.getBlockPos().mutableCopy();
for (int x = -1; x <= 1; x++)
for (int z = -1; z <= 1; z++) {
IPermissionContainer claim = storage.getForPermissionCheck(wither.getBlockPos().add(x, 0, z));
if (!claim.canInteract(null, PermissionRegistry.WITHER, pos.set(pos.getX() + x, pos.getY() + 3, pos.getZ() + z), false))
return false;
}
return true;
}
public static boolean canEndermanInteract(EndermanEntity enderman, BlockPos pos) {
if (enderman.world.isClient)
return true;
ClaimStorage storage = ClaimStorage.get((ServerWorld) enderman.world);
IPermissionContainer claim = storage.getForPermissionCheck(pos);
return claim.canInteract(null, PermissionRegistry.ENDERMAN, pos, false);
}
public static boolean canSnowGolemInteract(SnowGolemEntity snowgolem) {
if (snowgolem.world.isClient)
return true;
int x, y, z;
for (int l = 0; l < 4; ++l) {
x = MathHelper.floor(snowgolem.getX() + (l % 2 * 2 - 1) * 0.25F);
y = MathHelper.floor(snowgolem.getY());
z = MathHelper.floor(snowgolem.getZ() + (l / 2 % 2 * 2 - 1) * 0.25F);
BlockPos pos = new BlockPos(x, y, z);
IPermissionContainer claim = ClaimStorage.get((ServerWorld) snowgolem.world).getForPermissionCheck(pos);
if (!claim.canInteract(null, PermissionRegistry.SNOWGOLEM, pos, false))
return false;
}
return true;
}
public static void updateDroppedItem(PlayerEntity player, ItemEntity entity) {
((IOwnedItem) entity).setOriginPlayer((player));
}
public static void updateClaim(ServerPlayerEntity player, Claim currentClaim, Consumer<Claim> cons) {
Vec3d pos = player.getPos();
BlockPos rounded = TeleportUtils.roundedBlockPos(pos.add(0, player.getActiveEyeHeight(player.getPose(), player.getDimensions(player.getPose())), 0));
ClaimStorage storage = ClaimStorage.get(player.getServerWorld());
if (currentClaim != null) {
if (!currentClaim.insideClaim(rounded)) {
cons.accept(null);
} else {
if (!player.isSpectator()) {
BlockPos.Mutable bPos = rounded.mutableCopy();
if (!currentClaim.canInteract(player, PermissionRegistry.CANSTAY, bPos, true)) {
Vec3d tp = TeleportUtils.getTeleportPos(player, pos, storage, currentClaim.getDimensions(), bPos, (claim, nPos) -> claim.canInteract(player, PermissionRegistry.CANSTAY, nPos, false));
player.teleport(tp.getX(), tp.getY(), tp.getZ());
}
if (player.abilities.flying && !player.isCreative() && !currentClaim.canInteract(player, PermissionRegistry.FLIGHT, rounded, true)) {
player.abilities.flying = false;
player.networkHandler.sendPacket(new PlayerAbilitiesS2CPacket(player.abilities));
}
}
}
} else if (player.age % 3 == 0) {
Claim claim = storage.getClaimAt(rounded);
cons.accept(claim);
}
}
}

View File

@ -0,0 +1,119 @@
package io.github.flemmli97.flan.forgeevent;
import com.google.common.collect.Sets;
import com.mojang.authlib.GameProfile;
import io.github.flemmli97.flan.api.ClaimPermission;
import io.github.flemmli97.flan.api.PermissionRegistry;
import io.github.flemmli97.flan.claim.Claim;
import io.github.flemmli97.flan.claim.ClaimStorage;
import io.github.flemmli97.flan.claim.IPermissionContainer;
import io.github.flemmli97.flan.claim.ObjectToPermissionMap;
import io.github.flemmli97.flan.claim.PermHelper;
import io.github.flemmli97.flan.config.ConfigHandler;
import io.github.flemmli97.flan.integration.permissionapi.CommandPermission;
import io.github.flemmli97.flan.player.EnumDisplayType;
import io.github.flemmli97.flan.player.EnumEditMode;
import io.github.flemmli97.flan.player.PlayerClaimData;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.item.Items;
import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import java.util.Set;
public class ItemInteractEventsForge {
public static TypedActionResult<ItemStack> useItem(PlayerInteractEvent.RightClickItem event) {
event.set
PlayerInteractEvent.RightClickItem event
if (world.isClient || p.isSpectator())
return TypedActionResult.pass(p.getStackInHand(hand));
ServerPlayerEntity player = (ServerPlayerEntity) p;
ItemStack stack = player.getStackInHand(hand);
if (stack.getItem() == ConfigHandler.config.claimingItem) {
HitResult ray = player.rayTrace(64, 0, false);
if (ray != null && ray.getType() == HitResult.Type.BLOCK) {
claimLandHandling(player, ((BlockHitResult) ray).getBlockPos());
return TypedActionResult.success(stack);
}
return TypedActionResult.pass(stack);
}
if (stack.getItem() == ConfigHandler.config.inspectionItem) {
HitResult ray = player.rayTrace(32, 0, false);
if (ray != null && ray.getType() == HitResult.Type.BLOCK) {
inspect(player, ((BlockHitResult) ray).getBlockPos());
return TypedActionResult.success(stack);
}
return TypedActionResult.pass(stack);
}
ClaimStorage storage = ClaimStorage.get((ServerWorld) world);
BlockPos pos = player.getBlockPos();
IPermissionContainer claim = storage.getForPermissionCheck(pos);
if (claim == null)
return TypedActionResult.pass(stack);
ClaimPermission perm = ObjectToPermissionMap.getFromItem(stack.getItem());
if (perm != null)
return claim.canInteract(player, perm, pos, true) ? TypedActionResult.pass(stack) : TypedActionResult.fail(stack);
return TypedActionResult.pass(stack);
}
private static final Set<Item> blackListedItems = Sets.newHashSet(Items.COMPASS, Items.FILLED_MAP, Items.FIREWORK_ROCKET);
public static ActionResult onItemUseBlock(ItemUsageContext context) {
//Check for Fakeplayer. Since there is no api for that directly check the class
if (!(context.getPlayer() instanceof ServerPlayerEntity) || !context.getPlayer().getClass().equals(ServerPlayerEntity.class) || context.getStack().isEmpty())
return ActionResult.PASS;
ClaimStorage storage = ClaimStorage.get((ServerWorld) context.getWorld());
BlockPos placePos = new ItemPlacementContext(context).getBlockPos();
IPermissionContainer claim = storage.getForPermissionCheck(placePos.add(0, 255, 0));
if (claim == null)
return ActionResult.PASS;
if (blackListedItems.contains(context.getStack().getItem()))
return ActionResult.PASS;
boolean actualInClaim = !(claim instanceof Claim) || placePos.getY() >= ((Claim) claim).getDimensions()[4];
ServerPlayerEntity player = (ServerPlayerEntity) context.getPlayer();
ClaimPermission perm = ObjectToPermissionMap.getFromItem(context.getStack().getItem());
if (perm != null) {
if (claim.canInteract(player, perm, placePos, false))
return ActionResult.PASS;
else if (actualInClaim) {
player.sendMessage(PermHelper.simpleColoredText(ConfigHandler.lang.noPermissionSimple, Formatting.DARK_RED), true);
return ActionResult.FAIL;
}
}
if (claim.canInteract(player, PermissionRegistry.PLACE, placePos, false)) {
if (!actualInClaim && context.getStack().getItem() instanceof BlockItem) {
((Claim) claim).extendDownwards(placePos);
}
return ActionResult.PASS;
} else if (actualInClaim) {
player.sendMessage(PermHelper.simpleColoredText(ConfigHandler.lang.noPermissionSimple, Formatting.DARK_RED), true);
BlockState other = context.getWorld().getBlockState(placePos.up());
player.networkHandler.sendPacket(new BlockUpdateS2CPacket(placePos.up(), other));
PlayerClaimData.get(player).addDisplayClaim(claim, EnumDisplayType.MAIN, player.getBlockPos().getY());
updateHeldItem(player);
return ActionResult.FAIL;
}
return ActionResult.PASS;
}
}

View File

@ -0,0 +1,40 @@
package io.github.flemmli97.flan.forgeevent;
import io.github.flemmli97.flan.api.PermissionRegistry;
import io.github.flemmli97.flan.claim.ClaimStorage;
import io.github.flemmli97.flan.claim.IPermissionContainer;
import io.github.flemmli97.flan.event.WorldEvents;
import net.minecraft.block.BlockState;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.living.LivingSpawnEvent;
import net.minecraftforge.event.world.ExplosionEvent;
import net.minecraftforge.event.world.PistonEvent;
public class WorldEventsForge {
public static void modifyExplosion(ExplosionEvent.Detonate event) {
if (event.getWorld() instanceof ServerWorld)
WorldEvents.modifyExplosion(event.getExplosion(), (ServerWorld) event.getWorld());
}
public static void pistonCanPush(PistonEvent.Pre event) {
if (!(event.getWorld() instanceof World))
return;
if (!WorldEvents.pistonCanPush(event.getState(), (World) event.getWorld(), event.getPos(), event.getDirection(), event.getDirection()))
event.setCanceled(true);
}
public static void preventMobSpawn(LivingSpawnEvent.CheckSpawn event) {
if (!(event.getWorld() instanceof ServerWorld) || !(event.getEntityLiving() instanceof MobEntity))
return;
if (WorldEvents.preventMobSpawn((ServerWorld) event.getWorld(), (MobEntity) event.getEntityLiving()))
event.setCanceled(true);
}
}

View File

@ -0,0 +1,21 @@
package io.github.flemmli97.flan.integration.gunpowder.forge;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import io.github.flemmli97.flan.claim.PermHelper;
import io.github.flemmli97.flan.config.ConfigHandler;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.util.Formatting;
public class CommandCurrencyImpl {
public static int sellClaimBlocks(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
context.getSource().sendFeedback(PermHelper.simpleColoredText(ConfigHandler.lang.gunpowderMissing, Formatting.DARK_RED), false);
return 0;
}
public static int buyClaimBlocks(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
context.getSource().sendFeedback(PermHelper.simpleColoredText(ConfigHandler.lang.gunpowderMissing, Formatting.DARK_RED), false);
return 0;
}
}

View File

@ -0,0 +1,16 @@
package io.github.flemmli97.flan.integration.permissionapi.forge;
import io.github.flemmli97.flan.config.ConfigHandler;
import net.minecraft.server.command.CommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
public class CommandPermissionImpl {
public static boolean perm(CommandSource src, String perm, boolean adminCmd) {
return !adminCmd || src.hasPermissionLevel(ConfigHandler.config.permissionLevel);
}
public static boolean perm(ServerPlayerEntity src, String perm, boolean adminCmd) {
return !adminCmd || src.hasPermissionLevel(ConfigHandler.config.permissionLevel);
}
}

View File

@ -0,0 +1,15 @@
modLoader="javafml"
loaderVersion="[35,)"
license="All rights reserved"
issueTrackerURL="https://github.com/Flemmli97/Flan/issues"
displayURL="https://github.com/Flemmli97/Flan"
# logoFile="flan/icon.png"
credits=""
authors="Flemmli97"
[[mods]]
modId="flan"
version="${file.jarVersion}"
displayName="Flan"
# updateJSONURL=""
authors="Flemmli97"
description='''Land claiming mod'''

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,24 +1,29 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx2G
# Forge Properties
forge_version=36.1.31
# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version=1.16.2
yarn_mappings=1.16.2+build.1
loader_version=0.9.1+build.205
minecraft_version=1.16.5
yarn_mappings=1.16.5+build.9
loader_version=0.11.3
# Mod Properties
mod_version=1.4.2
maven_group=io.github.flemmli97
archives_base_name=flan
# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.19.0+build.398-1.16
fabric_version=0.34.2+1.16
gunpowder_version=0.2.10
fabric_permissions_api=0.1-SNAPSHOT
player_ability_lib=1.2.2
# Curse properties
curse_page=https://www.curseforge.com/minecraft/mc-mods/flan
curse_versions=1.16.5, Java 8, Fabric
curse_id=404578
curse_dep=fabric-api
curse_page_fabric=https://www.curseforge.com/minecraft/mc-mods/flan
curse_versions=1.16.5, Java 8
curse_id_fabric=404578
curse_dep_fabric=fabric-api
curse_page_forge=https://www.curseforge.com/minecraft/mc-mods/flan
curse_id_forge=404578
curse_dep_forge=
# Other
project_name=Flan
project_name=Flan

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -1,10 +1,17 @@
pluginManagement {
repositories {
jcenter()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
maven { url "https://maven.architectury.dev/" }
maven { url "https://maven.minecraftforge.net/" }
gradlePluginPortal()
}
}
include("common")
include("fabric")
include("forge")
rootProject.name = "Flan Arch"

View File

@ -1,34 +0,0 @@
package io.github.flemmli97.flan.api;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos;
public interface ClaimPermissionEvent {
Event<ClaimPermissionEvent> CHECK = EventFactory.createArrayBacked(ClaimPermissionEvent.class,
(listeners) -> (player, permission, pos) -> {
for (ClaimPermissionEvent event : listeners) {
ActionResult result = event.check(player, permission, pos);
if (result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
}
);
/**
* Callback for when permissions are checked
*
* @param player The corresponding player. Can be null if the check is e.g. caused by tnt explosions
* @param permission The permission to check
* @param pos The block pos where the action is occuring
* @return ActionResult#PASS to do nothing. ActionResult#FAIL to prevent the action. Else to allow the action
*/
ActionResult check(ServerPlayerEntity player, ClaimPermission permission, BlockPos pos);
}