95 Commits
Author SHA1 Message Date
okx-code e2f0e609e9 this breaks the nice geometric series
this was also supposed to be decremented when the 1m/s sky buff was added
2024-01-15 17:52:33 +00:00
okx-code 13a22b6f14 Fix copper oxidising not as much as it should 2024-01-10 23:49:40 +00:00
okx-code 863cae02d3 rails shouldn't oxidise naturally 2023-12-21 04:31:58 +00:00
okx-code af9e2cfb44 fix default 2023-12-13 01:13:46 +00:00
okx-code 04f28a3d39 add faster speeds if exposed to the sky 2023-12-13 01:12:58 +00:00
okx-code 358a2aeb54 ignore cancelled (better citadel interaction) 2023-12-13 00:22:29 +00:00
okx-code edc7e08272 update damage 2023-12-13 00:18:16 +00:00
okx-code 3fd3020cc2 Add BetterRails, FasterHorses, RailDeoxidise, and miscellaneous things
- BetterRails lets you change rail speed based on the block below.
- FasterHorses increases the maximum speed of horses
- CopperRail lets you deoxidise a block below a rail by right-clicking on the rail, and oxidises copper when a minecart goes over it
- Fixed StriderBreeding randomness calculations
- Order /sah list alphabetically
- Actually disable hacks that should be disabled
2023-12-13 00:16:01 +00:00
wingzero54 c350c4f79c Merge pull request #72 from CivMC/wingzero54-patch-2
Update version
2023-07-16 09:43:33 -05:00
wingzero54 20c459210f Update version 2023-07-16 09:43:23 -05:00
AngrySoundTech 89e21d73f5 Merge pull request #70 from Protonull/ott-fix
Overhauling OTT
2023-06-19 13:06:16 -04:00
Alexander 446b15f47b Make suggested changes 2023-06-16 00:27:35 +01:00
Alexander 7ed328ea69 Inline OTT's isRestrictedDestination method
Then more specific responses can be sent.
2023-06-15 19:40:36 +01:00
Alexander b1c3d2321e Minor OTT fixup
The OTT request message now suggests the accept command rather than sending it, just in case this can be abused.

The blacklisted and unsafe materials are already immutable, so there's no point in wrapping them.

Renamed isSafeLocation to isRestrictedDestination for clarity and flipped the logic.

Sends a reject message to the rejector.

Logs to the console when an OTT is granted.

Limit OTT commands to other players.
2023-06-15 19:11:09 +01:00
Alexander f58126fbd2 Initialise commands before hacks
Also separates enabling hacks out of loadAllHacks, since loading != enabling.
2023-06-15 19:10:28 +01:00
Alexander 38522a98c2 Remove old OTT command from plugin.yml 2023-06-15 15:56:05 +01:00
Alexander a10b207de3 Add OTT grant command, add syntaxes, and print teleports to console 2023-06-15 02:34:59 +01:00
Alexander f5609cba46 Reduce duplicate code in OTT
Defers the shared OTT permissibility checks to a method and the returned enum is checked against to give the appropriate response messages.
2023-06-15 01:32:08 +01:00
Alexander 9ab2aad3f6 Add ExilePearl as a dependency 2023-06-15 01:02:17 +01:00
Alexander 0d1ee9f7c2 Improve OTT commands 2023-06-14 02:17:54 +01:00
Alexander 557b47e4ea Add config option to OTT to limit to same world 2023-06-14 02:06:50 +01:00
Alexander 332e701b89 Check pearled status in OTT 2023-06-14 02:01:45 +01:00
Alexander c271bf848a Initial fix 2023-06-14 01:32:30 +01:00
wingzero54 6439102f9c Merge pull request #68 from CivMC/wingzero54-patch-1
Bump to 2.2.2
2023-05-31 09:16:07 -05:00
wingzero54 53c8cbf1f7 Bump to 2.2.2 2023-05-31 09:15:55 -05:00
wingzero54 a99d68e3b3 Merge pull request #65 from CivMC/OTT
Add OTT hack to SAH
2023-05-31 09:14:28 -05:00
wingzero54 6104b7d80f Merge pull request #67 from CivMC/RedDevel2-patch-1
Turn safeorebreak off by default.
2023-05-31 09:10:54 -05:00
RedDevel2 7ecb9ecd7a Turn safeorebreak off by default.
Set default state for SafeOreBreak ores to disabled.
2023-05-29 22:12:07 +02:00
RedDevel2 5a12262e74 Add bastion dependancy
For OTT
2023-05-16 17:54:41 +02:00
RedDevel2 3fc3d5d7eb Create OneTimeTeleportConfig.java 2023-05-11 22:06:03 +02:00
RedDevel2 8044fda7c7 Add OTT to config.yml 2023-05-11 22:03:14 +02:00
RedDevel2 273ff0ec0e Add OTT to plugin.yml 2023-05-11 22:01:51 +02:00
RedDevel2 7e2d1225a5 Add OneTimeTeleport.java
Add OTT to SAH
2023-05-11 21:56:26 +02:00
AngrySoundTech 22a7cf2e18 Bump version to 2.2.1 2023-04-25 14:00:57 -04:00
AngrySoundTech dc345c04c6 Merge pull request #63 from awoo-civ/pr1
Notify the player on every failed ore break attempt
2023-04-21 12:26:23 -04:00
awoo-civ 14869c9da9 Notify the player on every failed ore break attempt 2023-04-11 02:55:14 +00:00
AngrySoundTech fc0e9ca9dd Merge branch 'master' of ast.github.com:CivMC/SimpleAdminHacks 2023-04-04 17:10:13 -04:00
AngrySoundTech 95907238c9 Update civgradle and bump version to 2.2.0 2023-04-04 17:10:07 -04:00
AngrySoundTech 2ed7225a41 Merge pull request #61 from okx-code/safe-ore-break
Add safe ore break
2023-03-27 09:53:44 -04:00
okx-code 8ca971c160 Use array 2023-03-23 23:37:15 +00:00
okx-code 71c2e1c663 fix print 2023-03-22 02:41:11 +00:00
okx-code 0c8a5c9a72 Simplify code 2023-03-22 02:36:59 +00:00
okx-code 2edbe1b0a9 add early return 2023-03-22 01:05:40 +00:00
okx-code 32401ad468 add safe ore break 2023-03-22 01:03:32 +00:00
AngrySoundTech 5347466bd4 Update build.gradle.kts 2022-09-05 12:49:48 -04:00
AngrySoundTech a010d56573 Merge pull request #50 from Diet-Cola/bound-fixes
Bound fixes
2022-09-05 12:49:35 -04:00
Cola 3b9d9bce18 Fix first item being unbound + bound item 2022-09-05 17:37:38 +01:00
Cola 168657a858 Check if the second item has key 2022-09-05 16:53:20 +01:00
Cola 2cd0b18aea Update inventory
Weird bug with first item?
2022-09-05 16:32:13 +01:00
Cola 0775bb0d91 Items MUST have matching uuids 2022-09-05 16:21:54 +01:00
AngrySoundTech ada854607d Update build.gradle.kts 2022-09-05 10:45:31 -04:00
AngrySoundTech 68dd8e0267 Merge pull request #49 from Diet-Cola/bound-fixes
Check anvil if the second item has armour bound pdc
2022-09-05 10:44:58 -04:00
Cola 3d27999357 Check anvil if the second item has armour bound pdc 2022-08-30 23:24:58 +01:00
wingzero54 1193ac92c9 version 2022-08-17 10:34:00 -05:00
wingzero54 88056253a5 Merge pull request #47 from Aleksey-Terzi/errors
Fix exceptions
2022-08-17 10:01:23 -05:00
wingzero54 5f08ba1399 Merge pull request #46 from CivMC/SAH-Grindstone-patch
Disable Grindstone use so they can be placed as decorative blocks
2022-08-17 10:01:03 -05:00
Aleksey Terzi 4e5e7581ee Fix BankStick to BanStick 2022-08-13 20:37:07 -06:00
Aleksey Terzi 088fc4773b Fix exception on enable of StrayStats and BedLocator, add soft dependency to BanStick 2022-08-13 12:04:28 -06:00
Aleksey Terzi 1e019768b5 Merge pull request #4 from CivMC/master
Sync
2022-08-12 20:58:30 -06:00
AhriVG 85e4fcc7d2 Add grindstone setting to config 2022-08-12 16:17:04 -03:00
AhriVG c68aaa6cbc Disable Grindstone use
Copied existing enderchest functionality
2022-08-12 16:09:01 -03:00
wingzero54 5f12e02d69 Version 2022-08-10 09:21:26 -05:00
wingzero54 901fb2abd2 Merge pull request #43 from Diet-Cola/bombing-fixes
Add onEnable to GameFixes and register listener
2022-08-10 09:11:25 -05:00
Aleksey Terzi fd67578db4 Merge pull request #3 from CivMC/master
Sync
2022-08-08 19:48:22 -06:00
Cola 7def3c7be3 Add onEnable to GameFixes and register listener 2022-08-09 00:42:12 +01:00
wingzero54 5590655ddb Merge pull request #22 from Diet-Cola/sapling-chance
Add SaplingHack
2022-07-01 12:57:32 -05:00
wingzero54 d9b69d3802 Merge pull request #23 from Diet-Cola/fix-ab-craft
Prevent Bound Armour being repaired via Crafting
2022-06-27 21:53:02 -05:00
Cola 5e26f234ae Make result null 2022-06-24 13:20:05 +01:00
Cola 6fbc3abc47 Add SaplingHack 2022-06-24 08:53:01 +01:00
Cola 0968fb35c4 Add SaplingHack 2022-06-24 02:39:16 +01:00
Cola 280a182600 Prevent Bound Armour being repaired via Crafting 2022-06-23 13:02:17 +01:00
Cola 02aafdf9b5 Add SaplingHack 2022-06-19 03:53:09 +01:00
AngrySoundTech 927ba898f2 Merge pull request #19 from Diet-Cola/fix-old-enchanting
Change target field
2022-06-13 11:49:28 -04:00
AngrySoundTech e8721db8b4 Merge pull request #17 from Aleksey-Terzi/master
Fix messages for elevator block
2022-06-13 11:48:03 -04:00
AngrySoundTech e097ab457f Merge pull request #21 from Diet-Cola/armour-bound-fixes
Check for metadata to make compat with CTP
2022-06-13 11:47:33 -04:00
Cola 2fc000c2e9 Check for metadata to make compat with CTP 2022-06-12 02:40:30 +01:00
Cola 9e8a217bdf Implement method from paper 2022-06-03 23:44:17 +01:00
Aleksey Terzi c871729a15 Fix messages for GoldBlockElevators 2022-06-02 20:02:14 -06:00
Aleksey Terzi 9c44bf9588 Merge pull request #1 from CivMC/master
Synchronization
2022-06-02 18:32:39 -06:00
AngrySoundTech 99fc5d2b31 Merge pull request #16 from Aleksey-Terzi/master
Make elevator block configurable
2022-06-02 12:23:25 -04:00
AngrySoundTech b41b0fd067 Merge pull request #15 from Diet-Cola/portal-modify
PortalModify Improvements
2022-06-02 08:46:02 -04:00
Aleksey Terzi e1932e2a81 Make elevator block configurable 2022-06-01 20:52:11 -06:00
Cola cb4f4c50d5 Improve logic 2022-05-24 19:33:39 +01:00
Cola d9dbf6ba96 Merge branch 'master' into portal-modify 2022-05-24 19:33:13 +01:00
wingzero54 520a8deb89 Merge pull request #13 from Diet-Cola/portal-modify
Portal feature
2022-05-21 10:10:55 -05:00
Cola fcb398ba1d Latest Portals 2022-05-18 01:58:28 +01:00
Cola cd4d0cfd71 Merge remote-tracking branch 'CivMC/master' into portal-modify 2022-05-13 00:30:04 +01:00
wingzero54 8a64118213 Merge pull request #9 from Gjum/round-player-list-ping
roundPlayerListPing to same 6 levels vanilla displays
2022-04-25 21:39:47 -05:00
wingzero54 c5e7e57b6a Merge pull request #6 from CivMC/1.18.2
1.18.2
2022-04-25 21:33:37 -05:00
Gjum 131e3617d7 roundPlayerListPing to same 6 levels vanilla displays 2022-04-22 17:15:58 +02:00
wingzero54 9135691c26 Merge pull request #8 from okx-code/master
Fix AttrHider not hiding enchants properly
2022-04-11 18:19:53 -05:00
Cola 9e19fa6293 Default config, disabled by default 2022-03-10 02:02:06 +00:00
Cola ae47739a13 Clunky but works 2022-03-10 01:50:43 +00:00
Cola 846a18a397 Latest 2022-03-09 23:39:52 +00:00
Cola b1973290b4 1.18.2 2022-03-07 21:52:58 +00:00
41 changed files with 1744 additions and 163 deletions

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
name: Build
on:
push:
branches:
- '*'
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
- uses: gradle/gradle-build-action@v2
with:
arguments: build
+25
View File
@@ -0,0 +1,25 @@
name: Publish
on:
push:
tags:
- 'v*.*.*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
- uses: gradle/gradle-build-action@v2
with:
arguments: publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CIVMC_NEXUS_USER: ${{ secrets.CIVMC_NEXUS_USER }}
CIVMC_NEXUS_PASSWORD: ${{ secrets.CIVMC_NEXUS_PASSWORD }}
-7
View File
@@ -1,7 +0,0 @@
name: Build
on:
pull_request:
jobs:
call_build:
uses: CivMC/.github/.github/workflows/gradle_build.yml@master
-8
View File
@@ -1,8 +0,0 @@
name: Publish
on:
release:
types: [created]
jobs:
call_publish:
uses: CivMC/.github/.github/workflows/gradle_publish.yml@master
+6 -44
View File
@@ -1,61 +1,23 @@
import net.civmc.civgradle.common.util.civRepo
import net.civmc.civgradle.CivGradleExtension
plugins {
`java-library`
`maven-publish`
id("net.civmc.civgradle.plugin") version "1.0.0-SNAPSHOT"
}
// Temporary hack:
// Remove the root build directory
gradle.buildFinished {
project.buildDir.deleteRecursively()
}
allprojects {
group = "net.civmc.simpleadminhacks"
version = "2.0.0-SNAPSHOT"
description = "SimpleAdminHacks"
id("net.civmc.civgradle") version "2.+" apply false
}
subprojects {
apply(plugin = "net.civmc.civgradle.plugin")
apply(plugin = "java-library")
apply(plugin = "maven-publish")
apply(plugin = "net.civmc.civgradle")
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
configure<CivGradleExtension> {
pluginName = project.property("pluginName") as String
}
repositories {
mavenCentral()
civRepo("CivMC/CivModCore")
civRepo("CivMC/NameLayer")
civRepo("CivMC/Citadel")
civRepo("CivMC/CombatTagPlus")
civRepo("CivMC/BanStick")
maven("https://repo.civmc.net/repository/maven-public")
maven("https://repo.dmulloy2.net/repository/public/")
maven("https://ci.frostcast.net/plugin/repository/everything")
maven("https://jitpack.io")
}
publishing {
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/CivMC/SimpleAdminHacks")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
publications {
register<MavenPublication>("gpr") {
from(components["java"])
}
}
}
}
+7
View File
@@ -0,0 +1,7 @@
# Gradle properties
group = net.civmc.simpleadminhacks
version = 2.2.3
description = SimpleAdminHacks
# Custom Properties
pluginName = SimpleAdminHacks
+8 -14
View File
@@ -1,23 +1,17 @@
plugins {
`java-library`
id("net.civmc.civgradle.plugin")
id("io.papermc.paperweight.userdev") version "1.3.1"
}
civGradle {
paper {
pluginName = "SimpleAdminHacks"
}
id("io.papermc.paperweight.userdev")
}
dependencies {
paperDevBundle("1.18.1-R0.1-SNAPSHOT")
paperDevBundle("1.18.2-R0.1-SNAPSHOT")
compileOnly("net.civmc.civmodcore:paper:2.0.0-SNAPSHOT:dev-all")
compileOnly("net.civmc.namelayer:paper:3.0.0-SNAPSHOT:dev")
compileOnly("net.civmc.citadel:paper:5.0.0-SNAPSHOT:dev")
compileOnly("net.civmc.civmodcore:civmodcore-paper:2.3.5:dev-all")
compileOnly("net.civmc.namelayer:namelayer-paper:3.0.4:dev")
compileOnly("net.civmc.citadel:citadel-paper:5.1.2:dev")
compileOnly("net.civmc.combattagplus:paper:2.0.0-SNAPSHOT:dev")
compileOnly("net.civmc.banstick:paper:2.0.0-SNAPSHOT:dev")
compileOnly("net.civmc.banstick:banstick-paper:2.0.1:dev")
compileOnly("net.civmc.bastion:bastion-paper:3.0.1:dev")
compileOnly("net.civmc.exilepearl:exilepearl-paper:2.1.3:dev")
compileOnly("com.comphenix.protocol:ProtocolLib:4.8.0")
@@ -38,8 +38,9 @@ public class SimpleAdminHacks extends ACivMod {
setEnabled(false);
return;
}
this.manager.loadAllHacks();
this.commands = new CommandRegistrar(this);
this.manager.loadAllHacks();
this.manager.enableAllHacks();
}
@Override
@@ -0,0 +1,64 @@
package com.programmerdan.minecraft.simpleadminhacks.configs;
import com.google.common.collect.Maps;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHackConfig;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import vg.civcraft.mc.civmodcore.utilities.CivLogger;
import java.util.*;
public final class BetterRailsConfig extends SimpleHackConfig {
private final CivLogger logger;
private Map<Material, Double> speeds;
private double baseSpeed = 8;
private Map<Material, Double> skySpeeds;
private double skySpeed = 0;
public BetterRailsConfig(SimpleAdminHacks plugin, ConfigurationSection base) {
super(plugin, base, false);
this.logger = CivLogger.getLogger(getClass());
wireup(base);
}
@Override
protected void wireup(ConfigurationSection config) {
this.baseSpeed = config.getDouble("base");
ConfigurationSection materials = config.getConfigurationSection("materials");
Set<String> keys = materials.getKeys(false);
this.speeds = Maps.newHashMapWithExpectedSize(keys.size());
for (String key : keys) {
this.speeds.put(Material.valueOf(key), materials.getDouble(key));
}
this.skySpeed = config.getDouble("skyBase");
ConfigurationSection skyMaterials = config.getConfigurationSection("skyMaterials");
Set<String> skyKeys = skyMaterials.getKeys(false);
this.skySpeeds = Maps.newHashMapWithExpectedSize(skyKeys.size());
for (String key : skyKeys) {
this.skySpeeds.put(Material.valueOf(key), skyMaterials.getDouble(key));
}
}
public Double getMaxSpeedMetresPerSecond(Material material) {
return speeds.get(material);
}
public Double getSkySpeedMetresPerSecond(Material material) {
return skySpeeds.get(material);
}
public double getBaseSpeed() {
return baseSpeed;
}
public double getSkySpeed() {
return skySpeed;
}
}
@@ -18,6 +18,7 @@ public class GameFeaturesConfig extends SimpleHackConfig {
private boolean isPhantomSpawning;
private boolean enderChestPlacement;
private boolean enderChestUse;
private boolean grindstoneUse;
private boolean shulkerBoxUse;
private boolean totemPowers;
private boolean chorusFruitUse;
@@ -61,6 +62,9 @@ public class GameFeaturesConfig extends SimpleHackConfig {
this.enderChestUse = config.getBoolean("enderChestUse", false);
if (!this.enderChestUse) plugin().log(" Using EnderChests is disabled");
this.grindstoneUse = config.getBoolean("grindstoneUse", false);
if (!this.grindstoneUse) plugin().log(" Using Grindstones is disabled");
this.shulkerBoxUse = config.getBoolean("shulkerBoxUse", false);
if (!this.shulkerBoxUse) plugin().log(" Using Shulker Boxes is disabled");
@@ -132,6 +136,10 @@ public class GameFeaturesConfig extends SimpleHackConfig {
public boolean isEnderChestUse() {
return this.enderChestUse;
}
public boolean isGrindstoneUse() {
return this.grindstoneUse;
}
public boolean isShulkerBoxUse() {
return this.shulkerBoxUse;
@@ -0,0 +1,80 @@
package com.programmerdan.minecraft.simpleadminhacks.configs;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHackConfig;
import java.util.List;
import java.util.Objects;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import vg.civcraft.mc.civmodcore.config.ConfigHelper;
import vg.civcraft.mc.civmodcore.inventory.items.ItemUtils;
import vg.civcraft.mc.civmodcore.inventory.items.MaterialUtils;
import vg.civcraft.mc.civmodcore.utilities.CivLogger;
public final class OneTimeTeleportConfig extends SimpleHackConfig {
private final CivLogger LOGGER = CivLogger.getLogger(OneTimeTeleportConfig.class);
private List<Material> materialBlacklist;
private List<Material> unsafeMaterials;
private long timeLimitOnUsage;
private boolean limitToSameWorld;
public OneTimeTeleportConfig(
final @NotNull SimpleAdminHacks plugin,
final @NotNull ConfigurationSection config
) {
super(plugin, config);
}
@Override
protected void wireup(final ConfigurationSection config) {
// Parse blacklisted item materials
this.materialBlacklist = config.getStringList("material_blacklist")
.stream()
.map((raw) -> {
final Material material = MaterialUtils.getMaterial(raw);
if (!ItemUtils.isValidItemMaterial(material)) {
LOGGER.warning("Blacklisted material [" + raw + "] is not a valid item material!");
return null;
}
return material;
})
.filter(Objects::nonNull)
.toList();
// Parse unsafe blocks
this.unsafeMaterials = config.getStringList("unsafe_materials")
.stream()
.map((raw) -> {
final Material material = MaterialUtils.getMaterial(raw);
if (material == null || !material.isBlock()) {
LOGGER.warning("Unsafe material [" + raw + "] is not a valid block material!");
return null;
}
return material;
})
.filter(Objects::nonNull)
.toList();
// Parse maximum time limit to use OTT
this.timeLimitOnUsage = ConfigHelper.parseTime(config.getString("ott_timeout", "2d"));
// Parse same-world limit
this.limitToSameWorld = config.getBoolean("limitToSameWorld", false);
}
public @NotNull List<Material> getMaterialBlacklist() {
return Objects.requireNonNullElseGet(this.materialBlacklist, List::of);
}
public @NotNull List<Material> getUnsafeMaterials() {
return Objects.requireNonNullElseGet(this.unsafeMaterials, List::of);
}
public long getTimeLimitOnUsageInMillis() {
return this.timeLimitOnUsage;
}
public boolean isLimitingToSameWorld() {
return this.limitToSameWorld;
}
}
@@ -0,0 +1,45 @@
package com.programmerdan.minecraft.simpleadminhacks.configs;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHackConfig;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
public class SaplingConfig extends SimpleHackConfig {
private Map<Material, Double> chanceMap;
private boolean allowFortune;
public SaplingConfig(SimpleAdminHacks plugin, ConfigurationSection base) {
super(plugin, base);
}
public SaplingConfig(SimpleAdminHacks plugin, ConfigurationSection base, boolean wireup) {
super(plugin, base, wireup);
}
@Override
protected void wireup(ConfigurationSection config) {
this.allowFortune = config.getBoolean("allow_fortune", false);
this.chanceMap = new HashMap<>();
for (String replace : config.getConfigurationSection("blocks").getKeys(false)) {
Material leaves = Material.matchMaterial(replace.toUpperCase());
//Incase this breaks, default to no extra drops
Double chance = config.getConfigurationSection("blocks").getDouble(replace, 0.0);
if (leaves != null && chance != null) {
chanceMap.put(leaves, chance);
}
}
}
public Map<Material, Double> getChanceMap() {
return Collections.unmodifiableMap(this.chanceMap);
}
public boolean isAllowFortune() {
return this.allowFortune;
}
}
@@ -124,18 +124,15 @@ public final class HackManager {
}
register(hack);
this.plugin.info("Registered hack: " + hackName);
interactWithHack(hack, (finalHack) -> {
finalHack.onLoad();
if (finalHack.shouldEnable()) {
finalHack.enable();
}
});
interactWithHack(hack, SimpleHack::onLoad);
return hack;
}
public void enableAllHacks() {
for (final SimpleHack<?> hack : hacks) {
enableHack(hack);
if (hack.shouldEnable()) {
enableHack(hack);
}
}
}
@@ -211,6 +211,8 @@ public abstract class SimpleHack<T extends SimpleHackConfig> {
}
else {
value = config.getObject(identifier, clazz, null);
if (value == null)
value = config.getString(identifier);
}
if (value == null) {
// do nothing
@@ -5,8 +5,9 @@ import co.aikar.commands.CommandCompletions;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHack;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHackConfig;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import vg.civcraft.mc.civmodcore.commands.CommandManager;
public class CommandRegistrar extends CommandManager {
@@ -31,7 +32,7 @@ public class CommandRegistrar extends CommandManager {
public void registerCompletions(final CommandCompletions<BukkitCommandCompletionContext> completions) {
super.registerCompletions(completions);
completions.registerAsyncCompletion("hacks", (context) -> {
final List<String> names = new ArrayList<>();
final Set<String> names = new TreeSet<>();
for (final SimpleHack<? extends SimpleHackConfig> hack : this.plugin.getHackManager().getHacks()) {
names.add(hack.getName());
}
@@ -13,7 +13,9 @@ import com.google.common.base.Strings;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHack;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHackConfig;
import java.util.List;
import java.util.*;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.command.CommandSender;
@@ -34,11 +36,13 @@ public class HacksCommand extends BaseCommand {
if (hacks.isEmpty()) {
sender.sendMessage(" No hacks registered.");
}
else {
for (final SimpleHack<? extends SimpleHackConfig> hack : hacks) {
sender.sendMessage(" • " + ChatColor.YELLOW + hack.getName() + ": " + ChatColor.AQUA +
(hack.isEnabled() ? "enabled" : "disabled"));
}
final Map<String, SimpleHack<? extends SimpleHackConfig>> names = new TreeMap<>();
for (SimpleHack<? extends SimpleHackConfig> hack : hacks) {
names.put(hack.getName(), hack);
}
for (final SimpleHack<? extends SimpleHackConfig> hack : names.values()) {
sender.sendMessage(" • " + ChatColor.YELLOW + hack.getName() + ": " + ChatColor.AQUA +
(hack.isEnabled() ? "enabled" : "disabled"));
}
}
@@ -0,0 +1,112 @@
package com.programmerdan.minecraft.simpleadminhacks.hacks;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.configs.BetterRailsConfig;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHack;
import org.bukkit.HeightMap;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.event.vehicle.VehicleExitEvent;
import org.bukkit.event.vehicle.VehicleMoveEvent;
public final class BetterRails extends SimpleHack<BetterRailsConfig> implements Listener {
// A minecart goes at 8m/s but its internal speed is 0.4, this adjusts for that
private static final double METRES_PER_SECOND_TO_SPEED = 0.05;
private static final double VANILLA_SPEED = 0.4;
public BetterRails(SimpleAdminHacks plugin, final BetterRailsConfig config) {
super(plugin, config);
}
public static BetterRailsConfig generate(SimpleAdminHacks plugin, ConfigurationSection config) {
return new BetterRailsConfig(plugin, config);
}
@Override
public void onEnable() {
plugin().registerListener(this);
}
@Override
public void onDisable() {
HandlerList.unregisterAll(this);
}
@EventHandler
public void on(VehicleMoveEvent event) {
if (!(event.getVehicle() instanceof Minecart minecart)) {
return;
}
Location to = event.getTo();
Location from = event.getFrom();
if (to.getBlockX() == from.getBlockX() && to.getBlockY() == from.getBlockY() && to.getBlockZ() == from.getBlockZ()) {
return;
}
for (Entity entity : minecart.getPassengers()) {
if (entity instanceof Player) {
adjustSpeed(minecart);
return;
}
}
}
@EventHandler
public void on(VehicleEnterEvent event) {
if (!(event.getVehicle() instanceof Minecart minecart)) {
return;
}
if (event.getEntered() instanceof Player) {
adjustSpeed(minecart);
}
}
@EventHandler
public void on(VehicleExitEvent event) {
if (!(event.getVehicle() instanceof Minecart minecart)) {
return;
}
// Empty minecarts should return to their vanilla speed
minecart.setMaxSpeed(VANILLA_SPEED);
}
private void adjustSpeed(Minecart minecart) {
Material belowRail = minecart.getLocation().subtract(0, 1, 0).getBlock().getType();
Material belowRail2 = minecart.getLocation().subtract(0, 2, 0).getBlock().getType();
double speedMetresPerSecond = maxOrGet(config.getMaxSpeedMetresPerSecond(belowRail), config.getMaxSpeedMetresPerSecond(belowRail2), config.getBaseSpeed());
if (minecart.getLocation().getBlockY() == minecart.getWorld().getHighestBlockYAt(minecart.getLocation(), HeightMap.WORLD_SURFACE)) {
speedMetresPerSecond += maxOrGet(config.getSkySpeedMetresPerSecond(belowRail), config.getSkySpeedMetresPerSecond(belowRail2), config.getSkySpeed());
}
minecart.setMaxSpeed(speedMetresPerSecond * METRES_PER_SECOND_TO_SPEED);
}
private double maxOrGet(Double left, Double right, double defaultAmount) {
if (left != null && right != null) {
return Math.max(left, right);
} else if (left != null) {
return left;
} else if (right != null) {
return right;
} else {
return defaultAmount;
}
}
}
@@ -6,7 +6,7 @@ import com.programmerdan.minecraft.simpleadminhacks.configs.DisableAIConfig;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHack;
import net.minecraft.nbt.CompoundTag;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.craftbukkit.v1_18_R1.persistence.CraftPersistentDataContainer;
import org.bukkit.craftbukkit.v1_18_R2.persistence.CraftPersistentDataContainer;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -155,7 +155,14 @@ public class GameFeatures extends SimpleHack<GameFeaturesConfig> implements List
} else {
genStatus.append("disabled\n");
}
genStatus.append(" Grindstone use is ");
if (config.isGrindstoneUse()) {
genStatus.append("enabled\n");
} else {
genStatus.append("disabled\n");
}
genStatus.append(" Shulker Box use is ");
if (config.isShulkerBoxUse()) {
genStatus.append("enabled\n");
@@ -316,6 +323,20 @@ public class GameFeatures extends SimpleHack<GameFeaturesConfig> implements List
}
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void disableGrindstoneUse(PlayerInteractEvent event) {
if (!config.isEnabled()) return;
if (!config.isGrindstoneUse()) {
Action action = event.getAction();
Material material = event.getClickedBlock().getType();
boolean Grindstone = action == Action.RIGHT_CLICK_BLOCK &&
Material.GRINDSTONE.equals(material);
if (Grindstone) {
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void disableShulkerBoxUse(InventoryOpenEvent event){
@@ -59,6 +59,12 @@ public class GameFixes extends SimpleHack<GameFixesConfig> implements Listener {
super.onDisable();
}
@Override
public void onEnable() {
Bukkit.getPluginManager().registerEvents(this, plugin);
super.onEnable();
}
@Override
public String status() {
StringBuilder genStatus = new StringBuilder();
@@ -17,6 +17,7 @@ import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.inventory.ItemStack;
public class HorseStats extends SimpleHack<HorseStatsConfig> implements Listener {
private static final double INTERNAL_TO_METRES_PER_SECOND = 42.15778758471;
public HorseStats(SimpleAdminHacks plugin, HorseStatsConfig config) {
super(plugin, config);
@@ -36,24 +37,31 @@ public class HorseStats extends SimpleHack<HorseStatsConfig> implements Listener
AbstractHorse horse = (AbstractHorse)entity;
AttributeInstance attrHealth = horse.getAttribute(Attribute.GENERIC_MAX_HEALTH);
AttributeInstance attrSpeed = horse.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
event.getPlayer().sendMessage(String.format("%sHealth = %f, Speed = %f, Jump height = %f",
event.getPlayer().sendMessage(String.format("%sHealth = %f, Speed = %fm/s, Jump height = %f blocks",
ChatColor.YELLOW,
attrHealth.getBaseValue(),
attrSpeed.getBaseValue(),
horse.getJumpStrength()));
attrSpeed.getBaseValue() * INTERNAL_TO_METRES_PER_SECOND,
jumpHeightInBlocks(horse.getJumpStrength())));
event.setCancelled(true);
} else if (entity instanceof Strider) {
Strider strider = (Strider) entity;
AttributeInstance attrHealth = strider.getAttribute(Attribute.GENERIC_MAX_HEALTH);
AttributeInstance attrSpeed = strider.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
event.getPlayer().sendMessage(String.format("%sHealth = %f, Speed = %f",
event.getPlayer().sendMessage(String.format("%sHealth = %f, Speed = %fm/s",
ChatColor.YELLOW,
attrHealth.getBaseValue(),
attrSpeed.getBaseValue()));
attrSpeed.getBaseValue() * INTERNAL_TO_METRES_PER_SECOND));
event.setCancelled(true);
} else {
return;
}
}
private double jumpHeightInBlocks(double x) {
// This is a curve-fitted formula, so not 100% accurate
return -0.1817584952 * x * x * x + 3.689713992 * x * x + 2.128599134 * x - 0.343930367;
}
@Override
public void registerListeners() {
if (config.isEnabled()) {
@@ -16,8 +16,8 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.craftbukkit.v1_18_R1.CraftServer;
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftInventoryPlayer;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryCloseEvent;
@@ -0,0 +1,434 @@
package com.programmerdan.minecraft.simpleadminhacks.hacks;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.BukkitCommandCompletionContext;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Default;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Flags;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.devotedmc.ExilePearl.ExilePearlPlugin;
import com.google.common.collect.Lists;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.configs.OneTimeTeleportConfig;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHack;
import isaac.bastion.Bastion;
import isaac.bastion.BastionBlock;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.minelink.ctplus.CombatTagPlus;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import vg.civcraft.mc.civmodcore.commands.TabComplete;
import vg.civcraft.mc.civmodcore.players.settings.PlayerSetting;
import vg.civcraft.mc.civmodcore.players.settings.PlayerSettingAPI;
import vg.civcraft.mc.civmodcore.players.settings.impl.LongSetting;
import vg.civcraft.mc.civmodcore.utilities.TextUtil;
import vg.civcraft.mc.civmodcore.world.WorldUtils;
public final class OneTimeTeleport extends SimpleHack<OneTimeTeleportConfig> implements Listener {
public OneTimeTeleport(
final @NotNull SimpleAdminHacks plugin,
final @NotNull OneTimeTeleportConfig config
) {
super(plugin, config);
}
public static @NotNull OneTimeTeleportConfig generate(
final @NotNull SimpleAdminHacks plugin,
final @NotNull ConfigurationSection config
) {
return new OneTimeTeleportConfig(plugin, config);
}
@Override
public void onEnable() {
// Since there's no way to unregister settings without some gnarly reflection, this will only register settings
// that aren't already registered. Also, MoreCollectionUtils.getMissing() when?
final Collection<PlayerSetting<?>> allSettings = PlayerSettingAPI.getAllSettings();
final Collection<PlayerSetting<?>> ourSettings = Lists.newArrayList(this.grantedTimestamps);
ourSettings.removeIf(allSettings::contains);
ourSettings.forEach((setting) -> PlayerSettingAPI.registerSetting(setting, null));
plugin().registerListener(this);
plugin().getCommands().registerCommand(this.commands);
}
@Override
public void onDisable() {
plugin().getCommands().unregisterCommand(this.commands);
HandlerList.unregisterAll(this);
}
private final Map<UUID, UUID> senderToReceiver = new HashMap<>();
private static final long OTT_AVAILABLE = -1L;
private static final long OTT_UNAVAILABLE = -2L;
private final LongSetting grantedTimestamps = new LongSetting(
plugin(),
OTT_AVAILABLE,
"Time since OTT granted",
"timeSinceOTTGrant"
);
private final OTTCommand commands = new OTTCommand();
@CommandAlias("ott")
private final class OTTCommand extends BaseCommand {
@Default
public void defaultCommand(
final Player sender
) {
if (checkOTT(sender.getUniqueId())) {
final long expiresIn = config().getTimeLimitOnUsageInMillis() - (System.currentTimeMillis() - OneTimeTeleport.this.grantedTimestamps.getValue(sender.getUniqueId()));
sender.sendMessage(Component.text()
.content("Your one time teleport will expire in " + TextUtil.formatDuration(expiresIn))
.color(NamedTextColor.GREEN)
.decorate(TextDecoration.UNDERLINED)
.hoverEvent(HoverEvent.showText(Component.text("Clicking this message will suggest an OTT request command")))
.clickEvent(ClickEvent.suggestCommand("/ott to "))
);
return;
}
sender.sendMessage(Component.text("You don't have a one-time teleport.", NamedTextColor.RED));
}
@Subcommand("to|request")
@Description("Makes an OTT request to a player. If accepted, you'll teleport to them.")
@Syntax("<player>")
public void requestOTT(
final Player sender,
@Flags("other")
final Player targetPlayer
) {
if (targetPlayer == sender) {
sender.sendMessage(Component.text("You cannot OTT to yourself!", NamedTextColor.RED));
return;
}
switch (testPermissibility(sender, targetPlayer)) {
case OK -> {}
case FAIL_NO_OTT -> {
sender.sendMessage(Component.text("Your are no longer able to use OTT!"));
return;
}
case FAIL_IN_COMBAT -> {
sender.sendMessage(Component.text("You cannot OTT while in combat!", NamedTextColor.RED));
return;
}
case FAIL_IS_PEARLED -> {
sender.sendMessage(Component.text("You cannot OTT while pearled!", NamedTextColor.RED));
return;
}
case FAIL_DIFFERENT_WORLD -> {
sender.sendMessage(Component.text("You cannot OTT to another world!", NamedTextColor.RED));
return;
}
}
final UUID previousRequest = OneTimeTeleport.this.senderToReceiver.put(
sender.getUniqueId(),
targetPlayer.getUniqueId()
);
if (previousRequest != null) {
final Player previousTargetPlayer = Bukkit.getPlayer(previousRequest);
if (previousTargetPlayer != null) {
previousTargetPlayer.sendMessage(Component.text(sender.getName() + " has rescinded their OTT request to you.", NamedTextColor.GREEN));
}
}
sender.sendMessage(Component.text("You have requested to teleport to " + targetPlayer.getName() + "!", NamedTextColor.GREEN));
final String commandStr = "/ott accept " + sender.getName();
targetPlayer.sendMessage(Component.text()
.content("Click me or type \"" + commandStr + "\" to accept!")
.color(NamedTextColor.DARK_GREEN)
.decorate(TextDecoration.BOLD, TextDecoration.UNDERLINED)
.hoverEvent(HoverEvent.showText(Component.text("Clicking this message will suggest an accept command.")))
.clickEvent(ClickEvent.suggestCommand(commandStr))
);
}
@Subcommand("revoke|rescind|stop")
@Description("Revokes your OTT request.")
public void rescindRequest(
final Player sender
) {
final UUID targetUUID = OneTimeTeleport.this.senderToReceiver.remove(sender.getUniqueId());
if (targetUUID == null) {
sender.sendMessage(Component.text("You have no active OTT requests.", NamedTextColor.RED));
return;
}
sender.sendMessage(Component.text("You have revoked your OTT request!", NamedTextColor.GREEN));
final Player targetPlayer = Bukkit.getPlayer(targetUUID);
if (targetPlayer != null) {
targetPlayer.sendMessage(Component.text(sender.getName() + " has rescinded their OTT request to you.", NamedTextColor.GREEN));
}
}
@TabComplete("sah_ott_requests")
public List<String> getRequestsToMe(
final @NotNull BukkitCommandCompletionContext context
) {
final UUID targetPlayerUUID = context.getPlayer().getUniqueId();
return OneTimeTeleport.this.senderToReceiver.entrySet()
.stream()
.filter((entry) -> Objects.equals(targetPlayerUUID, entry.getValue()))
.map((entry) -> Bukkit.getPlayer(entry.getKey()))
.filter(Objects::nonNull)
.map(Player::getName)
.toList();
}
@Subcommand("accept|approve|allow|yes")
@CommandCompletion("@sah_ott_requests")
@Description("Accepts an OTT request to your location.")
@Syntax("<requester>")
public void acceptOTT(
final Player sender,
@Flags("other")
final Player requestingPlayer
) {
if (requestingPlayer == sender) {
sender.sendMessage(Component.text("You cannot accept an OTT from yourself!", NamedTextColor.RED));
return;
}
if (!OneTimeTeleport.this.senderToReceiver.remove(
requestingPlayer.getUniqueId(),
sender.getUniqueId()
)) {
sender.sendMessage(Component.text("There are no active requests from that player!", NamedTextColor.RED));
return;
}
switch (testPermissibility(requestingPlayer, sender)) {
case OK -> {}
case FAIL_NO_OTT -> {
sender.sendMessage(Component.text(requestingPlayer.getName() + "'s one-time teleport has expired!"));
requestingPlayer.sendMessage(Component.text("Failed to teleport because your one-time teleport has expired!"));
return;
}
case FAIL_IN_COMBAT -> {
sender.sendMessage(Component.text(requestingPlayer.getName() + " could not one-time teleport as they're in combat!", NamedTextColor.RED));
requestingPlayer.sendMessage(Component.text(sender.getName() + " accepted your request, but you're in combat!", NamedTextColor.RED));
OneTimeTeleport.this.senderToReceiver.put(requestingPlayer.getUniqueId(), sender.getUniqueId()); // Be kind and put the request back!
return;
}
case FAIL_IS_PEARLED -> {
sender.sendMessage(Component.text(requestingPlayer.getName() + " could not one-time teleport as they're pearled!", NamedTextColor.RED));
requestingPlayer.sendMessage(Component.text(sender.getName() + " accepted your request, but you're pearled!", NamedTextColor.RED));
return;
}
case FAIL_DIFFERENT_WORLD -> {
sender.sendMessage(Component.text(requestingPlayer.getName() + " could not one-time teleport as they're in a different world!", NamedTextColor.RED));
requestingPlayer.sendMessage(Component.text(sender.getName() + " accepted your request, but you're in a different world!", NamedTextColor.RED));
return;
}
}
if (Bukkit.getPluginManager().isPluginEnabled("Bastion")) {
for (final BastionBlock bastion : Bastion.getBastionManager().getBlockingBastions(sender.getLocation())) {
if (!bastion.canPlace(sender) || !bastion.canPlace(requestingPlayer)) {
sender.sendMessage(Component.text(requestingPlayer.getName() + " could not one-time teleport to a hostile bastion!", NamedTextColor.RED));
requestingPlayer.sendMessage(Component.text(sender.getName() + " accepted your request, but they're in a hostile bastion!", NamedTextColor.RED));
OneTimeTeleport.this.senderToReceiver.put(requestingPlayer.getUniqueId(), sender.getUniqueId()); // Be kind and put the request back!
return;
}
}
}
for (final Block block : getNearbyBlocks(sender.getLocation().getBlock(), 8)) {
if (config().getUnsafeMaterials().contains(block.getType())) {
sender.sendMessage(Component.text(requestingPlayer.getName() + " could not one-time teleport with unsafe blocks nearby!", NamedTextColor.RED));
requestingPlayer.sendMessage(Component.text(sender.getName() + " accepted your request, but there's unsafe blocks nearby!", NamedTextColor.RED));
OneTimeTeleport.this.senderToReceiver.put(requestingPlayer.getUniqueId(), sender.getUniqueId()); // Be kind and put the request back!
return;
}
}
// Remove any blacklisted materials from the player's inventory
requestingPlayer.sendMessage(Component.text("You may find some items missing after teleporting, these were removed as they are blacklisted to be teleported with!", NamedTextColor.AQUA));
final Inventory requestingPlayerInventory = requestingPlayer.getInventory();
config().getMaterialBlacklist().forEach(requestingPlayerInventory::remove);
OneTimeTeleport.this.grantedTimestamps.setValue(requestingPlayer.getUniqueId(), OTT_UNAVAILABLE);
OneTimeTeleport.this.logger.info("Player[" + requestingPlayer.getName() + "] has OTT-teleported from [" + WorldUtils.getBlockLocation(requestingPlayer.getLocation()) + "] to [" + sender.getName() + "] at [" + WorldUtils.getBlockLocation(sender.getLocation()) + "]");
requestingPlayer.teleport(sender.getLocation());
sender.sendMessage(Component.text(requestingPlayer.getName() + " has been teleported to you!", NamedTextColor.GREEN));
requestingPlayer.sendMessage(Component.text("You have been teleported to " + sender.getName() + "!", NamedTextColor.GREEN));
}
@Subcommand("reject|refuse|deny|no")
@CommandCompletion("@sah_ott_requests")
@Description("Rejects an OTT to your location.")
@Syntax("<requester>")
public void rejectOTT(
final Player sender,
@Flags("other")
final Player requestingPlayer
) {
if (requestingPlayer == sender) {
sender.sendMessage(Component.text("You cannot reject an OTT from yourself!", NamedTextColor.RED));
return;
}
if (!OneTimeTeleport.this.senderToReceiver.remove(
requestingPlayer.getUniqueId(),
sender.getUniqueId()
)) {
sender.sendMessage(Component.text("There are no active requests from that player!", NamedTextColor.RED));
return;
}
sender.sendMessage(Component.text("You have rejected " + requestingPlayer.getName() + "'s OTT request!", NamedTextColor.GREEN));
requestingPlayer.sendMessage(Component.text(sender.getName() + " has denied your OTT request!", NamedTextColor.RED));
}
@Subcommand("grant|bestow|give")
@CommandPermission("simpleadmin.grantott")
@CommandCompletion("@allplayers")
@Description("Gives a player a use of OTT as if they first joined.")
@Syntax("<recipient>")
public void grantOTT(
final CommandSender sender,
final String receivingPlayerName
) {
final OfflinePlayer receivingPlayer = Bukkit.getOfflinePlayerIfCached(receivingPlayerName);
if (receivingPlayer == null) {
sender.sendMessage(Component.text("Could not find player " + receivingPlayerName + "!", NamedTextColor.RED));
return;
}
OneTimeTeleport.this.grantedTimestamps.setValue(receivingPlayer.getUniqueId(), System.currentTimeMillis());
sender.sendMessage(Component.text("You have granted " + receivingPlayer.getName() + " an OTT!", NamedTextColor.GREEN));
final Player onlineReceivingPlayer = receivingPlayer.getPlayer();
if (onlineReceivingPlayer != null) {
onlineReceivingPlayer.sendMessage(Component.text("You have been granted an OTT!", NamedTextColor.GREEN));
}
OneTimeTeleport.this.logger.info(sender.getName() + " has granted " + receivingPlayer.getName() + " an OTT!");
}
};
@EventHandler
public void onFirstJoin(final PlayerJoinEvent event) {
checkOTT(event.getPlayer().getUniqueId());
}
@EventHandler
public void onQuit(final PlayerQuitEvent event) {
final Player whoQuit = event.getPlayer();
// Remove all pending OTT's involving this player
this.senderToReceiver.entrySet().removeIf((entry) -> {
final UUID requesterUUID = entry.getKey(), targetUUID = entry.getValue();
// The player was the target of OTT requests
if (Objects.equals(whoQuit.getUniqueId(), targetUUID)) {
final Player requesterPlayer = Bukkit.getPlayer(requesterUUID);
if (requesterPlayer != null) { // Just in case
requesterPlayer.sendMessage(Component.text("Your OTT request to " + whoQuit.getName() + " has been voided."));
}
return true;
}
// The player had made an OTT request
if (Objects.equals(whoQuit.getUniqueId(), requesterUUID)) {
final Player targetPlayer = Bukkit.getPlayer(targetUUID);
if (targetPlayer != null) { // Just in case
targetPlayer.sendMessage(Component.text(whoQuit.getName() + "'s OTT request has been voided."));
}
}
return false;
});
}
/** All possible permissible states that requesting and accepting share! */
private enum OttPermissible { OK, FAIL_NO_OTT, FAIL_IN_COMBAT, FAIL_IS_PEARLED, FAIL_DIFFERENT_WORLD }
private @NotNull OttPermissible testPermissibility(
final @NotNull Player requestingPlayer,
final @NotNull Player destinationPlayer
) {
if (!checkOTT(requestingPlayer.getUniqueId())) {
return OttPermissible.FAIL_NO_OTT;
}
if (Bukkit.getPluginManager().isPluginEnabled("CombatTagPlus")) {
final CombatTagPlus combatTagPlus = JavaPlugin.getPlugin(CombatTagPlus.class);
if (combatTagPlus.getTagManager().isTagged(requestingPlayer.getUniqueId())) {
return OttPermissible.FAIL_IN_COMBAT;
}
}
if (Bukkit.getPluginManager().isPluginEnabled("ExilePearl")) {
if (ExilePearlPlugin.getApi().getPearlManager().getPearl(requestingPlayer.getUniqueId()) != null) {
return OttPermissible.FAIL_IS_PEARLED;
}
}
if (config().isLimitingToSameWorld()) {
if (!Objects.equals(requestingPlayer.getWorld(), destinationPlayer.getWorld())) {
return OttPermissible.FAIL_DIFFERENT_WORLD;
}
}
return OttPermissible.OK;
}
private @NotNull List<Block> getNearbyBlocks(
final @NotNull Block start,
final int radius
) {
if (radius <= 0) {
return new ArrayList<>(0);
}
final int iterations = (radius * 2) + 1;
final var blocks = new ArrayList<Block>(iterations * iterations * iterations);
for (int x = -radius; x <= radius; x++) {
for (int y = -radius; y <= radius; y++) {
for (int z = -radius; z <= radius; z++) {
blocks.add(start.getRelative(x, y, z));
}
}
}
return blocks;
}
private boolean checkOTT(
final @NotNull UUID uuid
) {
final long grantedTimestamp = this.grantedTimestamps.getValue(uuid);
if (grantedTimestamp == OTT_UNAVAILABLE) {
return false;
}
if (grantedTimestamp == OTT_AVAILABLE) {
this.grantedTimestamps.setValue(uuid, System.currentTimeMillis());
return true;
}
if (System.currentTimeMillis() >= (grantedTimestamp + config().getTimeLimitOnUsageInMillis())) {
this.grantedTimestamps.setValue(uuid, OTT_UNAVAILABLE);
return false;
}
return true;
}
}
@@ -0,0 +1,95 @@
package com.programmerdan.minecraft.simpleadminhacks.hacks;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.configs.SaplingConfig;
import com.programmerdan.minecraft.simpleadminhacks.framework.SimpleHack;
import java.util.Random;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.LeavesDecayEvent;
import org.bukkit.inventory.ItemStack;
public class SaplingHack extends SimpleHack<SaplingConfig> implements Listener {
private Random random = new Random();
public SaplingHack(SimpleAdminHacks plugin, SaplingConfig config) {
super(plugin, config);
}
@Override
public void onEnable() {
super.onEnable();
this.plugin.registerListener(this);
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
Block brokenBlock = event.getBlock();
if (!checkIfLeafBlock(brokenBlock)) {
return;
}
if (!this.config.isAllowFortune()) {
if (checkIfItemHasFortune(event.getPlayer().getItemInUse())) {
return;
}
}
if (!this.config.getChanceMap().containsKey(brokenBlock.getType())) {
return;
}
double nextDouble = random.nextDouble();
if (nextDouble <= this.config.getChanceMap().get(brokenBlock.getType())) {
brokenBlock.getWorld().dropItemNaturally(brokenBlock.getLocation(), new ItemStack(getSaplingMaterial(brokenBlock.getType()), 1));
logger.info("Dropped extra " + getSaplingMaterial(brokenBlock.getType()) + " from being broken at " + brokenBlock.getLocation());
}
}
@EventHandler
public void onLeafDecay(LeavesDecayEvent event) {
Block decayedBlock = event.getBlock();
if (!checkIfLeafBlock(decayedBlock)) {
return;
}
double nextDouble = random.nextDouble();
if (nextDouble <= this.config.getChanceMap().get(decayedBlock.getType())) {
decayedBlock.getWorld().dropItemNaturally(decayedBlock.getLocation(), new ItemStack(getSaplingMaterial(decayedBlock.getType()), 1));
logger.info("Dropped extra " + getSaplingMaterial(decayedBlock.getType()) + " from being broken at " + decayedBlock.getLocation());
}
}
private boolean checkIfLeafBlock(Block block) {
return switch (block.getType()) {
case OAK_LEAVES, BIRCH_LEAVES, SPRUCE_LEAVES, JUNGLE_LEAVES, ACACIA_LEAVES, DARK_OAK_LEAVES -> true;
default -> false;
};
}
private boolean checkIfItemHasFortune(ItemStack itemStack) {
if (itemStack == null) {
return false;
}
return itemStack.getEnchantments().containsKey(Enchantment.LOOT_BONUS_BLOCKS);
}
private Material getSaplingMaterial(Material material) {
return switch (material) {
case OAK_LEAVES -> Material.OAK_SAPLING;
case BIRCH_LEAVES -> Material.BIRCH_SAPLING;
case SPRUCE_LEAVES -> Material.SPRUCE_SAPLING;
case JUNGLE_LEAVES -> Material.JUNGLE_SAPLING;
case ACACIA_LEAVES -> Material.ACACIA_SAPLING;
case DARK_OAK_LEAVES -> Material.DARK_OAK_SAPLING;
//We set this to air so nothing will drop if it comes to erroring
default -> Material.AIR;
};
}
public static SaplingConfig generate(SimpleAdminHacks plugin, ConfigurationSection config) {
return new SaplingConfig(plugin, config);
}
}
@@ -20,8 +20,8 @@ import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_18_R1.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_18_R2.util.CraftMagicNumbers;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -12,10 +12,16 @@ import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.PrepareAnvilEvent;
import org.bukkit.event.inventory.PrepareItemCraftEvent;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
@@ -63,7 +69,7 @@ public class ArmourBound extends BasicHack {
return;
}
UUID boundUUID = UUID.fromString(itemContainer.get(this.key, PersistentDataType.STRING));
if (!boundUUID.equals(player.getUniqueId())) {
if (!boundUUID.equals(player.getUniqueId()) && !player.hasMetadata("NPC")) {
player.closeInventory();
ItemStack toDrop = newItem.clone();
newItem.setAmount(0);
@@ -72,6 +78,95 @@ public class ArmourBound extends BasicHack {
}
}
@EventHandler
public void onItemCraft(PrepareItemCraftEvent event) {
if (event.getRecipe() == null) {
return;
}
CraftingInventory inventory = event.getInventory();
ItemStack[] matrix = inventory.getMatrix();
ItemStack boundItem = null;
PersistentDataContainer container = null;
ItemMeta meta = null;
for (ItemStack item : matrix) {
if (item == null) {
continue;
}
if (!whitelist.contains(item.getType().toString())) {
continue;
}
meta = item.getItemMeta();
if (meta == null) {
continue;
}
container = meta.getPersistentDataContainer();
if (!container.has(this.key, PersistentDataType.STRING)) {
continue;
}
boundItem = item;
break;
}
if (boundItem == null) {
return;
}
inventory.setResult(null);
for (HumanEntity viewer : inventory.getViewers()) {
if (viewer instanceof final Player playerViewer) {
playerViewer.updateInventory();
}
}
}
@EventHandler
public void onAnvilRepair(PrepareAnvilEvent event) {
AnvilInventory inventory = event.getInventory();
ItemStack first = inventory.getFirstItem();
if (first == null || first.getType() == Material.AIR) {
return;
}
ItemStack second = inventory.getSecondItem();
ItemStack result = event.getResult();
if (second == null || second.getType() == Material.AIR) {
return;
}
if (result == null || result.getType() == Material.AIR) {
return;
}
if (!first.hasItemMeta()) {
return;
}
if (!second.hasItemMeta()) {
return;
}
PersistentDataContainer firstContainer = first.getItemMeta().getPersistentDataContainer();
PersistentDataContainer secondContainer = second.getItemMeta().getPersistentDataContainer();
if (!firstContainer.has(this.key, PersistentDataType.STRING)) {
if (secondContainer.has(this.key, PersistentDataType.STRING)) {
result.setItemMeta(second.getItemMeta());
result.editMeta(meta -> {
if (meta instanceof Damageable damageable) {
damageable.setDamage(((Damageable)event.getResult().getItemMeta()).getDamage());
}
});
event.setResult(result);
}
return;
}
UUID firstUUID = UUID.fromString(firstContainer.get(this.key, PersistentDataType.STRING));
if (!secondContainer.has(this.key, PersistentDataType.STRING)) {
return;
}
UUID secondUUID = UUID.fromString(secondContainer.get(this.key, PersistentDataType.STRING));
if (firstUUID.equals(secondUUID)) {
//We dont want to do anything if these both match, otherwise set the result to null
return;
}
event.setResult(null);
for (HumanEntity entity : inventory.getViewers()) {
((Player)entity).updateInventory();
}
}
private EquipmentSlot getRealSlot(PlayerArmorChangeEvent.SlotType slotType) {
switch (slotType) {
case HEAD:
@@ -7,6 +7,7 @@ import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.Pair;
import com.comphenix.protocol.wrappers.PlayerInfoData;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
import com.destroystokyo.paper.MaterialTags;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
@@ -26,6 +27,9 @@ import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData;
import java.util.ArrayList;
import java.util.List;
public final class AttrHider extends BasicHack {
public static final String BYPASS_PERMISSION = "attrhider.bypass";
@@ -41,6 +45,9 @@ public final class AttrHider extends BasicHack {
@AutoLoad
private boolean hideHealth;
@AutoLoad
private boolean roundPlayerListPing;
public AttrHider(final SimpleAdminHacks plugin, final BasicHackConfig config) {
super(plugin, config);
}
@@ -152,6 +159,41 @@ public final class AttrHider extends BasicHack {
}
});
}
if (this.roundPlayerListPing) {
this.packets.addAdapter(new PacketAdapter(this.plugin, PacketType.Play.Server.PLAYER_INFO) {
@Override
public void onPacketSending(final PacketEvent event) {
final PacketContainer packet = event.getPacket();
final Player player = event.getPlayer();
if (player.hasPermission(BYPASS_PERMISSION)) {
return;
}
final PacketContainer cloned = packet.deepClone();
List<PlayerInfoData> newInfos = new ArrayList<>();
List<PlayerInfoData> oldInfos = cloned.getPlayerInfoDataLists().read(0);
for (PlayerInfoData oldInfo : oldInfos) {
int latency = oldInfo.getLatency();
// Limit player ping in the tablist to the same 6 values vanilla clients can discern visually
// this follows 1.16.5 PlayerTabOverlay#renderPingIcon()
if (latency < 0) latency = -1;
else if (latency < 150) latency = 75; // average of 0 and 150, arbitrary
else if (latency < 300) latency = 225;
else if (latency < 600) latency = 450;
else if (latency < 1000) latency = 800;
else latency = 1000;
newInfos.add(new PlayerInfoData(
oldInfo.getProfile(),
latency,
oldInfo.getGameMode(),
oldInfo.getDisplayName()));
}
cloned.getPlayerInfoDataLists().write(0, newInfos);
// The packet data is shared between events, but the event
// instance is exclusive to THIS sending of the packet
event.setPacket(cloned);
}
});
}
}
@Override
@@ -177,5 +219,4 @@ public final class AttrHider extends BasicHack {
|| material == Material.LINGERING_POTION
|| material == Material.SPLASH_POTION;
}
}
@@ -11,26 +11,32 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player;
import vg.civcraft.mc.civmodcore.chat.Componentify;
import vg.civcraft.mc.civmodcore.commands.CommandManager;
import vg.civcraft.mc.civmodcore.world.WorldUtils;
public final class BedLocator extends BasicHack {
private final BedLocatorCommand locatorCommand;
private final CommandManager commands;
public BedLocator(final SimpleAdminHacks plugin, final BasicHackConfig config) {
super(plugin, config);
this.locatorCommand = new BedLocatorCommand();
this.commands = new CommandManager(plugin()) {
@Override
public void registerCommands() {
registerCommand(new BedLocatorCommand());
}
};
}
@Override
public void onEnable() {
super.onEnable();
plugin().getCommands().registerCommand(this.locatorCommand);
commands.init();
}
@Override
public void onDisable() {
plugin().getCommands().unregisterCommand(this.locatorCommand);
commands.reset();
super.onDisable();
}
@@ -28,9 +28,9 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
@@ -0,0 +1,191 @@
package com.programmerdan.minecraft.simpleadminhacks.hacks.basic;
import com.destroystokyo.paper.MaterialTags;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHack;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHackConfig;
import com.programmerdan.minecraft.simpleadminhacks.framework.autoload.AutoLoad;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.level.block.WeatheringCopper;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_18_R2.event.CraftEventFactory;
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.BlockFormEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.vehicle.VehicleMoveEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class CopperRail extends BasicHack {
// ServerLevel has a private version of this so we will make one ourselves
private final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom();
@AutoLoad
private boolean deoxidise;
@AutoLoad
private double damage;
private boolean formingBlock = false;
public CopperRail(SimpleAdminHacks plugin, BasicHackConfig config) {
super(plugin, config);
}
@EventHandler
public void on(VehicleMoveEvent event) {
if (this.damage <= 0 || !(event.getVehicle() instanceof Minecart minecart)) {
return;
}
boolean hasPlayer = false;
for (Entity entity : minecart.getPassengers()) {
if (entity instanceof Player) {
hasPlayer = true;
break;
}
}
if (!hasPlayer) {
return;
}
Location to = event.getTo();
Location from = event.getFrom();
if (to.getBlockX() == from.getBlockX() && to.getBlockY() == from.getBlockY() && to.getBlockZ() == from.getBlockZ()) {
return;
}
int signX = from.getBlockX() > to.getBlockX() ? 1 : -1;
int signZ = from.getBlockZ() > to.getBlockZ() ? 1 : -1;
boolean firstBlock = true;
List<Block> copperBlocks = new ArrayList<>(4);
for (int x = to.getBlockX(); x != to.getBlockX() + (from.getBlockX() - to.getBlockX()) + signX; x += signX) {
for (int z = to.getBlockZ(); z != to.getBlockZ() + (from.getBlockZ() - to.getBlockZ()) + signZ; z += signZ) {
if (firstBlock) {
firstBlock = false;
continue;
}
Location location = new Location(minecart.getWorld(), x, from.getY(), z);
Block topCopperBlock = location.getBlock().getRelative(BlockFace.DOWN);
Optional<net.minecraft.world.level.block.Block> next = WeatheringCopper.getNext(((CraftBlock) topCopperBlock).getNMS().getBlock());
if (next.isPresent()) {
copperBlocks.add(topCopperBlock);
}
Block belowCopperBlock = topCopperBlock.getRelative(BlockFace.DOWN);
next = WeatheringCopper.getNext(((CraftBlock) belowCopperBlock).getNMS().getBlock());
if (next.isPresent()) {
copperBlocks.add(belowCopperBlock);
}
}
}
for (Block copperBlock : copperBlocks) {
CraftBlock craftBlock = (CraftBlock) copperBlock;
BlockState state = craftBlock.getNMS();
ServerLevel level = ((CraftWorld) copperBlock.getWorld()).getHandle();
// We damage the copper directly instead of using random ticking, as random ticking is easy to cheese
// by placing waxed copper next to the rail, entirely preventing the rest of the rail from oxidising.
WeatheringCopper copper = (WeatheringCopper) state.getBlock();
float chanceModifier = copper.getChanceModifier();
if (this.damage * chanceModifier > this.randomTickRandom.nextFloat()) {
copper.getNext(state).ifPresent((iblockdata2) -> {
try {
formingBlock = true;
CraftEventFactory.handleBlockFormEvent(level, craftBlock.getPosition(), iblockdata2);
} finally {
formingBlock = false;
}
});
}
}
}
@EventHandler(ignoreCancelled = true)
public void on(PlayerInteractEvent event) {
if (!this.deoxidise) {
return;
}
ItemStack item = event.getItem();
if (item == null || !MaterialTags.AXES.isTagged(item)) {
return;
}
Block block = event.getClickedBlock();
if (block == null || !MaterialTags.RAILS.isTagged(block)) {
return;
}
Block copperBlock = block.getRelative(BlockFace.DOWN);
Optional<BlockState> previous = WeatheringCopper.getPrevious(((CraftBlock) copperBlock).getNMS());
if (previous.isEmpty()) {
copperBlock = copperBlock.getRelative(BlockFace.DOWN);
}
previous = WeatheringCopper.getPrevious(((CraftBlock) copperBlock).getNMS());
if (previous.isEmpty()) {
return;
}
copperBlock.setType(previous.get().getBukkitMaterial());
block.getWorld().playSound(block.getLocation(), Sound.ITEM_AXE_SCRAPE, SoundCategory.BLOCKS, 1, 1);
block.getWorld().playEffect(block.getLocation(), Effect.OXIDISED_COPPER_SCRAPE, 0);
CraftPlayer player = (CraftPlayer) event.getPlayer();
// TODO: In 1.19 or above, this can be replaced with ItemStack#damage thanks to Paper
((CraftItemStack) item).handle.hurtAndBreak(1, player.getHandle(), p -> {
p.broadcastBreakEvent(event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND);
});
event.setCancelled(true);
}
// It's not really fair for copper blocks that are below rails to naturally oxidise,
// as it is easy to cheese by placing a waxed copper block every 9 blocks
@EventHandler
public void on(BlockFormEvent event) {
if (formingBlock) {
return;
}
Block block = event.getBlock();
Optional<net.minecraft.world.level.block.Block> next = WeatheringCopper.getNext(((CraftBlock) block).getNMS().getBlock());
if (next.isEmpty()) {
return;
}
Block railAbove = block.getRelative(BlockFace.UP);
if (!MaterialTags.RAILS.isTagged(railAbove)) {
railAbove = railAbove.getRelative(BlockFace.UP);
}
if (!MaterialTags.RAILS.isTagged(railAbove)) {
return;
}
event.setCancelled(true);
}
}
@@ -14,7 +14,7 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -0,0 +1,63 @@
package com.programmerdan.minecraft.simpleadminhacks.hacks.basic;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHack;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHackConfig;
import com.programmerdan.minecraft.simpleadminhacks.framework.autoload.AutoLoad;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityBreedEvent;
import java.util.logging.Level;
public class FasterHorses extends BasicHack {
@AutoLoad
private double minSpeed;
@AutoLoad
private double maxSpeed;
public FasterHorses(SimpleAdminHacks plugin, BasicHackConfig config) {
super(plugin, config);
}
@EventHandler(priority = EventPriority.HIGH)
public void on(EntityBreedEvent event) {
if (event.getEntity().getType() != EntityType.HORSE) {
return;
}
double dadSpeed = event.getFather().getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).getBaseValue();
double mumSpeed = event.getMother().getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).getBaseValue();
double irwinHallDist = (Math.random() * 0.3 + Math.random() * 0.3 + Math.random() * 0.3) * ((this.maxSpeed - this.minSpeed) / 0.9) + this.minSpeed;
double newSpeed = (dadSpeed + mumSpeed + irwinHallDist) / 3;
if (newSpeed < minSpeed) {
newSpeed = minSpeed;
} else if (newSpeed > maxSpeed) {
newSpeed = maxSpeed;
}
event.getEntity().getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(newSpeed);
plugin.getLogger().log(Level.INFO, "Horse breed to have speed: " + newSpeed);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void on(CreatureSpawnEvent event) {
if (event.getEntity().getType() != EntityType.HORSE) {
return;
}
if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.BREEDING) {
return;
}
AttributeInstance moveSpeed = event.getEntity().getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
if (moveSpeed == null) {
return;
}
double irwinHallDist = (Math.random() * 0.3 + Math.random() * 0.3 + Math.random() * 0.3) * ((this.maxSpeed - this.minSpeed) / 0.9) + this.minSpeed;
moveSpeed.setBaseValue(irwinHallDist);
plugin.getLogger().log(Level.INFO, "Setting Horse Speed to: " + irwinHallDist);
}
}
@@ -4,10 +4,11 @@ import com.destroystokyo.paper.event.player.PlayerJumpEvent;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHack;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHackConfig;
import com.programmerdan.minecraft.simpleadminhacks.framework.autoload.AutoLoad;
import com.programmerdan.minecraft.simpleadminhacks.framework.autoload.DataParser;
import com.programmerdan.minecraft.simpleadminhacks.framework.utilities.TeleportUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
@@ -19,6 +20,7 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import vg.civcraft.mc.civmodcore.inventory.items.ItemUtils;
import vg.civcraft.mc.civmodcore.players.settings.PlayerSettingAPI;
import vg.civcraft.mc.civmodcore.players.settings.gui.MenuSection;
import vg.civcraft.mc.civmodcore.players.settings.impl.BooleanSetting;
@@ -26,20 +28,39 @@ import vg.civcraft.mc.civmodcore.utilities.DoubleInteractFixer;
public class GoldBlockElevators extends BasicHack {
@AutoLoad(processor = DataParser.MATERIAL)
private Material elevatorBlock;
private BooleanSetting useJumpSneakTP;
private DoubleInteractFixer interactFixer;
private String blockName;
public GoldBlockElevators(SimpleAdminHacks plugin, BasicHackConfig config) {
super(plugin, config);
this.interactFixer = new DoubleInteractFixer(plugin);
}
@Override
public void onEnable() {
super.onEnable();
if (elevatorBlock == null)
elevatorBlock = Material.GOLD_BLOCK;
this.blockName = ItemUtils.getItemName(this.elevatorBlock).toLowerCase();
if (this.blockName.startsWith("block of"))
this.blockName = this.blockName.substring("block of ".length());
initSettings();
}
private void initSettings() {
MenuSection mainMenu = plugin.getSettingManager().getMainMenu();
this.useJumpSneakTP =
new BooleanSetting(plugin, true, "Use Jump or Sneak to teleport on gold blocks", "jumpOrSneakTp",
"When true, jumping or sneaking on gold blocks will teleport you up/down, when false, right or left clicking will do the same.");
String name = String.format("Use Jump or Sneak to teleport on %s blocks", this.blockName);
String description = String.format("When true, jumping or sneaking on %s blocks will teleport you up/down, when false, right or left clicking will do the same.",
this.blockName);
this.useJumpSneakTP = new BooleanSetting(plugin, true, name, "jumpOrSneakTp", description);
PlayerSettingAPI.registerSetting(this.useJumpSneakTP, mainMenu);
}
@@ -49,7 +70,7 @@ public class GoldBlockElevators extends BasicHack {
return;
}
Block below = event.getPlayer().getLocation().getBlock().getRelative(BlockFace.DOWN);
if (below.getType() != Material.GOLD_BLOCK) {
if (below.getType() != elevatorBlock) {
return;
}
if (!event.isSneaking()) {
@@ -60,8 +81,10 @@ public class GoldBlockElevators extends BasicHack {
return;
}
}
event.getPlayer().sendMessage(
ChatColor.RED + "No gold block to teleport you down to. Jump to teleport up instead.");
String message = String.format("No %s block to teleport you down to. Jump to teleport up instead.", this.blockName);
event.getPlayer().sendMessage(Component.text(message).color(NamedTextColor.RED));
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
@@ -70,7 +93,7 @@ public class GoldBlockElevators extends BasicHack {
return;
}
Block below = event.getFrom().getBlock().getRelative(BlockFace.DOWN);
if (below.getType() != Material.GOLD_BLOCK) {
if (below.getType() != elevatorBlock) {
return;
}
for (int y = below.getY() + 1; y <= below.getWorld().getMaxHeight(); y++) {
@@ -78,8 +101,10 @@ public class GoldBlockElevators extends BasicHack {
return;
}
}
event.getPlayer()
.sendMessage(ChatColor.RED + "No gold block to teleport you up to. Sneak to teleport down instead.");
String message = String.format("No %s block to teleport you up to. Sneak to teleport down instead.", this.blockName);
event.getPlayer().sendMessage(Component.text(message).color(NamedTextColor.RED));
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
@@ -95,7 +120,7 @@ public class GoldBlockElevators extends BasicHack {
return;
}
Block below = event.getPlayer().getLocation().getBlock().getRelative(BlockFace.DOWN);
if (below.getType() != Material.GOLD_BLOCK) {
if (below.getType() != elevatorBlock) {
return;
}
if (event.getClickedBlock() == null) {
@@ -110,24 +135,26 @@ public class GoldBlockElevators extends BasicHack {
return;
}
}
event.getPlayer().sendMessage(
Component.text("No gold block to teleport you down to. Right click to teleport up instead.")
.color(NamedTextColor.RED));
String message = String.format("No %s block to teleport you down to. Right click to teleport up instead.", this.blockName);
event.getPlayer().sendMessage(Component.text(message).color(NamedTextColor.RED));
} else {
for (int y = below.getY() + 1; y <= below.getWorld().getMaxHeight(); y++) {
if (doTeleport(below, event.getPlayer(), y)) {
return;
}
}
event.getPlayer().sendMessage(
Component.text("No gold block to teleport you up to. Left click to teleport down instead.")
.color(NamedTextColor.RED));
String message = String.format("No %s block to teleport you up to. Left click to teleport down instead.", this.blockName);
event.getPlayer().sendMessage(Component.text(message).color(NamedTextColor.RED));
}
}
private boolean doTeleport(Block source, Player player, int y) {
Block target = source.getWorld().getBlockAt(source.getX(), y, source.getZ());
if (target.getType() != Material.GOLD_BLOCK) {
if (target.getType() != elevatorBlock) {
return false;
}
if (!TeleportUtil.checkForTeleportSpace(target.getRelative(BlockFace.UP).getLocation())) {
@@ -25,7 +25,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftInventoryView;
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryView;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
@@ -149,7 +149,7 @@ public final class OldEnchanting extends BasicHack {
// Setup enchantment randomiser
Field randomiser = null;
try {
randomiser = FieldUtils.getDeclaredField(EnchantmentMenu.class, "h", true);
randomiser = FieldUtils.getDeclaredField(EnchantmentMenu.class, "p", true);
}
catch (final Throwable throwable) {
this.logger.log(Level.WARNING, "An exception was thrown while trying to reflect the enchanting " +
@@ -0,0 +1,84 @@
package com.programmerdan.minecraft.simpleadminhacks.hacks.basic;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHack;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHackConfig;
import com.programmerdan.minecraft.simpleadminhacks.framework.autoload.AutoLoad;
import org.bukkit.Bukkit;
import org.bukkit.HeightMap;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
public class PortalModifyHack extends BasicHack {
@AutoLoad
private String targetWorld;
@AutoLoad
private String homeWorld;
public PortalModifyHack(SimpleAdminHacks plugin, BasicHackConfig config) {
super(plugin, config);
}
//We want to go last incase any plugins want to cancel our attempt
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerEnterPortal(PlayerPortalEvent event) {
Player player = event.getPlayer();
if (event.getCause() != PlayerTeleportEvent.TeleportCause.END_PORTAL) {
return;
}
World world = Bukkit.getWorld(targetWorld);
if (world == null) {
return;
}
Location to;
switch (getTargetWorld(player).getEnvironment()) {
case NETHER:
to = new Location(getTargetWorld(player), event.getFrom().getX(), 125, event.getFrom().getZ());
break;
case NORMAL:
to = getTargetWorld(player).getHighestBlockAt(player.getLocation(), HeightMap.WORLD_SURFACE).getLocation().toCenterLocation().add(0,1,0);
break;
default:
return;
}
event.setTo(to);
if (to.getWorld().getName().equals(targetWorld)) {
spawnExit(to);
}
}
private World getTargetWorld(Player player) {
World target = Bukkit.getWorld(targetWorld);
World home = Bukkit.getWorld(homeWorld);
if (target == null) {
return player.getWorld();
}
if (home == null) {
return player.getWorld();
}
return player.getWorld().equals(target) ? home : target;
}
private void spawnExit(Location location) {
if (location == null) {
return;
}
//:Glad:
if (location.getBlock().getRelative(0,-2,0).getType() == Material.BEDROCK) {
location.getBlock().getRelative(0,-2,0).setType(Material.NETHERRACK);
};
if (location.getBlock().getRelative(0,-1,0).getType() == Material.BEDROCK) {
location.getBlock().getRelative(0,-1,0).setType(Material.NETHERRACK);
}
location.getBlock().setType(Material.AIR);
location.getBlock().getRelative(0,1,0).setType(Material.AIR);
location.getBlock().getRelative(0,2,0).setType(Material.END_PORTAL);
}
}
@@ -0,0 +1,132 @@
package com.programmerdan.minecraft.simpleadminhacks.hacks.basic;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHack;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHackConfig;
import com.programmerdan.minecraft.simpleadminhacks.framework.autoload.AutoLoad;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import vg.civcraft.mc.civmodcore.inventory.items.MaterialUtils;
import vg.civcraft.mc.civmodcore.players.settings.PlayerSettingAPI;
import vg.civcraft.mc.civmodcore.players.settings.gui.MenuSection;
import vg.civcraft.mc.civmodcore.players.settings.impl.BooleanSetting;
public final class SafeOreBreak extends BasicHack {
@AutoLoad
private List<List<String>> ores;
private final List<BooleanOreSetting> oreSettings = new ArrayList<>();
private final List<List<Material>> breakOres = new ArrayList<>();
public SafeOreBreak(final SimpleAdminHacks plugin, final BasicHackConfig config) {
super(plugin, config);
}
@Override
public void onEnable() {
super.onEnable();
MenuSection mainMenu = plugin.getSettingManager().getMainMenu();
OUTER:
for (List<String> parts : ores) {
List<Material> materialParts = new ArrayList<>(parts.size());
for (String part : parts) {
Material material = MaterialUtils.getMaterial(part);
if (material == null) {
logger.warning("Invalid material '" + part + "'. Skipping.");
continue OUTER;
}
materialParts.add(material);
}
breakOres.add(materialParts);
String materialName = PlainTextComponentSerializer.plainText().serialize(Component.translatable(materialParts.get(0)));
BooleanOreSetting setting = new BooleanOreSetting(plugin, false,
"Safe " + materialName + " break",
"safeOreBreak_" + materialParts.get(0).getKey().getKey(),
"Prevents you from breaking " + materialName
+ " without a silk touch pickaxe.",
materialParts.get(0));
oreSettings.add(setting);
PlayerSettingAPI.registerSetting(setting, mainMenu);
}
}
@Override
public void onDisable() {
super.onDisable();
}
@EventHandler(ignoreCancelled = true)
public void onOreBreak(BlockBreakEvent event) {
if (event.getPlayer().getGameMode() != GameMode.SURVIVAL) {
return;
}
ItemStack item = event.getPlayer().getInventory().getItemInMainHand();
if (item.hasItemMeta() && item.getItemMeta().hasEnchant(Enchantment.SILK_TOUCH)) {
return;
}
OUTER:
for (int i = 0; i < breakOres.size(); i++) {
List<Material> list = breakOres.get(i);
for (Material material : list) {
if (material == event.getBlock().getType()) {
Boolean value = oreSettings.get(i).getValue(event.getPlayer());
if (!value) {
continue OUTER;
}
event.getPlayer().sendMessage(Component.text(
"A SimpleAdminHacks /config option is preventing you from breaking that ore without a silk touch pickaxe.")
.color(NamedTextColor.RED));
event.setCancelled(true);
return;
}
}
}
}
private static class BooleanOreSetting extends BooleanSetting {
private final Material ore;
public BooleanOreSetting(JavaPlugin owningPlugin, Boolean defaultValue, String name, String identifier,
String description, Material ore) {
super(owningPlugin, defaultValue, name, identifier, description);
this.ore = ore;
}
@Override
public ItemStack getGuiRepresentation(UUID player) {
ItemStack item;
if (getValue(player)) {
item = new ItemStack(ore);
item.addUnsafeEnchantment(Enchantment.DURABILITY, 1);
item.addItemFlags(ItemFlag.HIDE_ENCHANTS);
} else {
item = new ItemStack(ore);
}
applyInfoToItemStack(item, player);
return item;
}
}
}
@@ -3,7 +3,6 @@ package com.programmerdan.minecraft.simpleadminhacks.hacks.basic;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import com.programmerdan.minecraft.banstick.BanStick;
import com.programmerdan.minecraft.banstick.handler.BanStickDatabaseHandler;
import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks;
import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHack;
@@ -17,29 +16,39 @@ import java.text.SimpleDateFormat;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import vg.civcraft.mc.civmodcore.commands.CommandManager;
public final class StrayStats extends BasicHack {
public StrayStats(final SimpleAdminHacks plugin, final BasicHackConfig config) {
super(plugin, config);
}
// ------------------------------------------------------------
// Bootstrap
// ------------------------------------------------------------
private final StatsCommand statsCommand = new StatsCommand();
private final CommandManager commands;
public StrayStats(final SimpleAdminHacks plugin, final BasicHackConfig config) {
super(plugin, config);
this.commands = new CommandManager(plugin()) {
@Override
public void registerCommands() {
registerCommand(new StatsCommand());
}
};
}
@Override
public void onEnable() {
super.onEnable();
BanStick.getPlugin();
this.plugin.getCommands().registerCommand(this.statsCommand);
if(plugin.getServer().getPluginManager().getPlugin("BanStick") == null) {
plugin.severe("StrayStats failed to initialize because BanStick plugin is not found");
return;
}
commands.init();
}
@Override
public void onDisable() {
this.plugin.getCommands().unregisterCommand(this.statsCommand);
commands.reset();
super.onDisable();
}
@@ -36,11 +36,8 @@ public class StriderBreeding extends BasicHack {
}
double dadSpeed = event.getFather().getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).getBaseValue();
double mumSpeed = event.getMother().getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).getBaseValue();
double randomSpeed = Math.random() * (this.maxSpeed - this.minSpeed) + this.minSpeed;
//the 0.44.... number, I was given this number by Okx#5481, apparently it is the horse speed generation number
//Also worth noting he told me it is not exactly a bell curve even if I did name it bellCurve
double bellCurve = (0.44999998807907104 + randomSpeed * 0.3 + randomSpeed * 0.3 + randomSpeed * 0.3) * 0.25;
double newStriderSpeed = (dadSpeed + mumSpeed + bellCurve) / 3;
double irwinHallDist = (0.45 + Math.random() * 0.3 + Math.random() * 0.3 + Math.random() * 0.3) * 0.25;
double newStriderSpeed = (dadSpeed + mumSpeed + irwinHallDist) / 3;
if (newStriderSpeed < minSpeed) {
newStriderSpeed = minSpeed;
} else if (newStriderSpeed > maxSpeed) {
@@ -80,15 +77,14 @@ public class StriderBreeding extends BasicHack {
if (moveSpeed == null) {
return;
}
double random = Math.random() * (maxSpeed - minSpeed) + minSpeed;
double bellCurve = (0.44999998807907104 + random * 0.3 + random * 0.3 + random * 0.3) * 0.25;
if (bellCurve < minSpeed) {
bellCurve = minSpeed;
} else if (bellCurve > maxSpeed) {
bellCurve = maxSpeed;
double irwinHallDist = (0.45 + Math.random() * 0.3 + Math.random() * 0.3 + Math.random() * 0.3) * 0.25;
if (irwinHallDist < minSpeed) {
irwinHallDist = minSpeed;
} else if (irwinHallDist > maxSpeed) {
irwinHallDist = maxSpeed;
}
moveSpeed.setBaseValue(bellCurve);
plugin.getLogger().log(Level.INFO, "Setting Strider Speed to: " + bellCurve);
moveSpeed.setBaseValue(irwinHallDist);
plugin.getLogger().log(Level.INFO, "Setting Strider Speed to: " + irwinHallDist);
}
public void rollHealthStat(LivingEntity strider, int minHealth, int maxHealth) {
+63
View File
@@ -62,6 +62,8 @@ hacks:
hideEffects: true
# Hide the health of entities
hideHealth: true
# Limit player ping in the tablist to the same 6 values vanilla clients can discern visually
roundPlayerListPing: true
AutoRespawn:
enabled: true
# Delay in MS
@@ -114,6 +116,7 @@ hacks:
enabled: true
GoldBlockElevators:
enabled: true
elevatorBlock: LODESTONE
HumbugBatchOne:
enabled: true
allowSheepDying: true
@@ -193,12 +196,26 @@ hacks:
enabled: true
PlayerStatistics:
enabled: true
#Alters end portals to send you to a target dimension instead of just the end
#This is a very specific hack made for CivMC, it is not recommended to enable
#Unless you want to fully mimic their behaviour
PortalModifyHack:
enabled: false
targetWorld: world_nether
homeWorld: world
PortalSpawnModifier:
enabled: true
pigManChance: 0.5
ghastChance: 0.07
witherSkeletonChance: 0.05
witherHeadDropChance: 0.04
SafeOreBreak:
enabled: true
ores:
- [DIAMOND_ORE,DEEPSLATE_DIAMOND_ORE]
- [COAL_ORE,DEEPSLATE_COAL_ORE]
- [REDSTONE_ORE,DEEPSLATE_REDSTONE_ORE]
- [LAPIS_ORE,DEEPSLATE_LAPIS_ORE]
ShipOutOfLuck:
enabled: true
# The list of Material's that boats cannot be placed on and will eject passengers
@@ -450,11 +467,29 @@ hacks:
- "This world is unforgiving."
- "Be sure to get a good night's"
- "rest soon."
OneTimeTeleport:
enabled: true
# Item materials that should be removed from the player upon teleporting
material_blacklist: []
# Blocks that will block OTT if in range of the target player
unsafe_materials: [LAVA, WATER]
# How long newfriends will have to use OTT before it expires
ott_timeout: 2d
# Whether or not to limit OTT to same-world teleports
limitToSameWorld: false
ReinforcedChestBreak:
enabled: true
# in seconds
delay: 180
message: "&4%player% is raiding a chest at %x% %y% %z%."
#Used to roll a dice on whether to drop an additional sapling on block break or leaf decay
SaplingHack:
enabled: true
#Should we still roll the dice for people when using a fortune enchanted tool?
allow_fortune: true
blocks:
JUNGLE_LEAVES: 0.5
DARK_OAK_LEAVES: 0.5
SanityHack:
enabled: true
trackPlace: true
@@ -478,3 +513,31 @@ hacks:
ToggleLamp:
enabled: false
cooldownTime: 100
BetterRails:
enabled: true
# All in metres per second
# Minecraft will prevent you going faster than 30m/s
base: 11
materials:
COBBLESTONE: 8
COPPER_BLOCK: 29
EXPOSED_COPPER: 23
WEATHERED_COPPER: 18
OXIDIZED_COPPER: 14
skyBase: 1
skyMaterials:
COBBLESTONE: 0
COPPER_BLOCK: 1
EXPOSED_COPPER: 1
WEATHERED_COPPER: 1
OXIDIZED_COPPER: 1
CopperRail:
enabled: true
deoxidise: true
# Chance to oxidise copper one level.
# Unoxidised copper will oxidise at 75% of this level.
damage: 0.03
FasterHorses:
enabled: true
minSpeed: 0.1125
maxSpeed: 0.438827582278 # 18.5m/s
+5 -1
View File
@@ -4,7 +4,7 @@ author: ProgrammerDan
authors: [ProgrammerDan, Maxopoly]
version: ${version}
depend: [CivModCore]
softdepend: [CombatTagPlus, NameLayer, Citadel, ProtocolLib]
softdepend: [CombatTagPlus, NameLayer, Citadel, ProtocolLib, BanStick, ExilePearl]
api-version: 1.18
commands:
hacks:
@@ -110,6 +110,7 @@ permissions:
simpleadmin.debugwand: true
simpleadmin.bedlocator: true
simpleadmin.elytrabypass: true
simpleadmin.grantott: true
simpleadmin.hacks:
description: Allows control of the hacks and settings which simpleadminhacks supports
default: op
@@ -158,3 +159,6 @@ permissions:
simpleadmin.elytrabypass:
description: Gives the ability to bypass elytra restrictions
default: op
simpleadmin.grantott:
description: Gives the ability to grant players OTT usages
default: op
+4 -9
View File
@@ -1,17 +1,12 @@
rootProject.name = "simpleadminhacks"
pluginManagement {
repositories {
gradlePluginPortal()
maven("https://repo.civmc.net/repository/maven-public/")
maven("https://papermc.io/repo/repository/maven-public/")
maven {
url = uri("https://maven.pkg.github.com/CivMC/CivGradle")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
}
rootProject.name = "simpleadminhacks"
include(":paper")
project(":paper").name = rootProject.name + "-paper"