Skip to content

Commit

Permalink
Merge pull request #141 from FTBTeam/1.20.1/dev
Browse files Browse the repository at this point in the history
1.20.1/dev
  • Loading branch information
desht authored Jan 3, 2024
2 parents f4d3574 + a7e5227 commit 1dc9370
Show file tree
Hide file tree
Showing 19 changed files with 403 additions and 109 deletions.
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [2001.1.4]

### Added
* Added configurable XP cost for ultimining (default remains free)
* See `experience_per_block` in server config
* Added configurable cooldown between ultimining operations (default remains 0 - no cooldown)
* See `ultimine_cooldown` in server config
* Overrideable in FTB Ranks with the `ftbultimine.ultimine_cooldown` permission node

### Fixed
* "Inner" ultimining preview block outlines are now rendered again
* Fixed checking of player's equipped tool

## [2001.1.3]

### Added
* Added new block tag `ftbultimine:block_whitelist`
* If this tag is non-empty, then _only_ blocks in this tag can be ultimined
* Complements the existing `ftbultimine:exclude_blocks` tag which can be used to blacklist blocks

## [2001.1.2]

### Added
* Updated to MC 1.20.1, based on 1902.4.1 release

## [1902.4.1]

### Added
Expand Down
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ allprojects {
apply plugin: "maven-publish"
apply from: "https://raw.githubusercontent.com/FTBTeam/mods-meta/main/gradle/git-md-changelog.gradle"

def ENV = System.getenv()
version = "${mod_version}-build.${ENV.GITHUB_RUN_NUMBER ?: 9999}"
version = project.mod_version
group = project.maven_group
archivesBaseName = project.archives_base_name

Expand Down
69 changes: 69 additions & 0 deletions common/src/main/java/dev/ftb/mods/ftbultimine/CooldownTracker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package dev.ftb.mods.ftbultimine;

import dev.ftb.mods.ftbultimine.config.FTBUltimineServerConfig;
import dev.ftb.mods.ftbultimine.net.SyncUltimineTimePacket;
import dev.ftb.mods.ftbultimine.net.SyncUltimineTimePacket.TimeType;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Player;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class CooldownTracker {
private static final CooldownTracker clientInstance = new CooldownTracker();
private static final CooldownTracker serverInstance = new CooldownTracker();

private final Map<UUID,Long> lastUltimineTime = new HashMap<>();

// client can't just look at the server config (even though it's sync'd) since we could be using Ranks...
// so this get sync'd when the server config changes, or when we get a Ranks event indicating a change
private static long ultimineCooldownClient;

public static long getLastUltimineTime(Player player) {
CooldownTracker instance = player.level().isClientSide ? clientInstance : serverInstance;
return instance.lastUltimineTime.getOrDefault(player.getUUID(), 0L);
}

public static void setLastUltimineTime(Player player, long when) {
CooldownTracker instance = player.level().isClientSide ? clientInstance : serverInstance;
instance.lastUltimineTime.put(player.getUUID(), when);
if (player instanceof ServerPlayer sp) {
new SyncUltimineTimePacket(when, TimeType.LAST_USED).sendTo(sp);
}
}

/**
* Get the remaining cooldown time for the player as a proportion of total time
* @param player the player to check
* @return a value in the range 0f -> 1f
*/
public static float getCooldownRemaining(Player player) {
long coolDown = getUltimineCooldown(player);
if (coolDown == 0L) {
return 1f;
}
long tickDelta = (System.currentTimeMillis() - getLastUltimineTime(player)) / 50; // ms -> ticks
return Mth.clamp((float)tickDelta / coolDown, 0f, 1f);
}

public static boolean isOnCooldown(Player player) {
long coolDown = getUltimineCooldown(player);
if (coolDown == 0L) {
return false;
}
long coolDownMs = coolDown * 50; // ticks -> ms
return coolDownMs > 0L && System.currentTimeMillis() - getLastUltimineTime(player) < coolDownMs;
}

private static long getUltimineCooldown(Player player) {
return player instanceof ServerPlayer sp ?
FTBUltimineServerConfig.getUltimineCooldown(sp) :
ultimineCooldownClient;
}

public static void setClientCooldownTime(long cooldown) {
ultimineCooldownClient = cooldown;
}
}
68 changes: 52 additions & 16 deletions common/src/main/java/dev/ftb/mods/ftbultimine/FTBUltimine.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,30 @@
import dev.architectury.event.events.common.*;
import dev.architectury.hooks.level.entity.PlayerHooks;
import dev.architectury.platform.Platform;
import dev.architectury.registry.ReloadListenerRegistry;
import dev.architectury.utils.EnvExecutor;
import dev.architectury.utils.value.IntValue;
import dev.ftb.mods.ftblibrary.snbt.SNBTCompoundTag;
import dev.ftb.mods.ftbultimine.client.FTBUltimineClient;
import dev.ftb.mods.ftbultimine.config.FTBUltimineCommonConfig;
import dev.ftb.mods.ftbultimine.config.FTBUltimineServerConfig;
import dev.ftb.mods.ftbultimine.integration.FTBRanksIntegration;
import dev.ftb.mods.ftbultimine.integration.FTBUltiminePlugins;
import dev.ftb.mods.ftbultimine.net.FTBUltimineNet;
import dev.ftb.mods.ftbultimine.net.SendShapePacket;
import dev.ftb.mods.ftbultimine.net.SyncConfigFromServerPacket;
import dev.ftb.mods.ftbultimine.net.SyncUltimineTimePacket;
import dev.ftb.mods.ftbultimine.net.SyncUltimineTimePacket.TimeType;
import dev.ftb.mods.ftbultimine.shape.*;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
import net.minecraft.tags.TagKey;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
Expand All @@ -36,6 +43,7 @@
import net.minecraft.world.phys.HitResult;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
Expand All @@ -44,9 +52,6 @@
import java.util.UUID;
import java.util.function.Predicate;

/**
* @author LatvianModder
*/
public class FTBUltimine {
public static FTBUltimine instance;

Expand All @@ -65,8 +70,9 @@ public class FTBUltimine {
public static final TagKey<Item> DENY_TAG = TagKey.create(Registries.ITEM, new ResourceLocation(MOD_ID, "excluded_tools"));
public static final TagKey<Item> STRICT_DENY_TAG = TagKey.create(Registries.ITEM, new ResourceLocation(MOD_ID, "excluded_tools/strict"));
public static final TagKey<Item> ALLOW_TAG = TagKey.create(Registries.ITEM, new ResourceLocation(MOD_ID, "included_tools"));
public static final TagKey<Block> EXCLUDED_BLOCKS = TagKey.create(Registries.BLOCK, new ResourceLocation(MOD_ID, "excluded_blocks"));

public static final TagKey<Block> EXCLUDED_BLOCKS = TagKey.create(Registries.BLOCK, new ResourceLocation(MOD_ID, "excluded_blocks"));
public static final TagKey<Block> BLOCK_WHITELIST = TagKey.create(Registries.BLOCK, new ResourceLocation(MOD_ID, "block_whitelist"));
public static final TagKey<Block> TILLABLE_TAG = TagKey.create(Registries.BLOCK, new ResourceLocation(MOD_ID, "farmland_tillable"));
public static final TagKey<Block> FLATTENABLE_TAG = TagKey.create(Registries.BLOCK, new ResourceLocation(MOD_ID, "shovel_flattenable"));

Expand All @@ -82,13 +88,16 @@ public FTBUltimine() {

if (Platform.isModLoaded("ftbranks")) {
ranksMod = true;
FTBRanksIntegration.init();
}

proxy = EnvExecutor.getEnvSpecific(() -> FTBUltimineClient::new, () -> FTBUltimineCommon::new);

FTBUltimineCommonConfig.load();
FTBUltiminePlugins.init();

ReloadListenerRegistry.register(PackType.SERVER_DATA, new DataReloadListener());

ShapeRegistry.register(new ShapelessShape(), true);
ShapeRegistry.register(new SmallTunnelShape());
ShapeRegistry.register(new SmallSquareShape());
Expand All @@ -105,14 +114,16 @@ public FTBUltimine() {
CommandRegistrationEvent.EVENT.register(FTBUltimineCommands::registerCommands);
}

public FTBUltiminePlayerData get(Player player) {
@NotNull
public FTBUltiminePlayerData getOrCreatePlayerData(Player player) {
return cachedDataMap.computeIfAbsent(player.getUUID(), FTBUltiminePlayerData::new);
}

private void playerJoined(ServerPlayer serverPlayer) {
SNBTCompoundTag config = new SNBTCompoundTag();
FTBUltimineServerConfig.CONFIG.write(config);
new SyncConfigFromServerPacket(config).sendTo(serverPlayer);
new SyncUltimineTimePacket(FTBUltimineServerConfig.getUltimineCooldown(serverPlayer), TimeType.COOLDOWN).sendTo(serverPlayer);
}

private void serverStarting(MinecraftServer server) {
Expand All @@ -122,7 +133,7 @@ private void serverStarting(MinecraftServer server) {
}

public void setKeyPressed(ServerPlayer player, boolean pressed) {
FTBUltiminePlayerData data = get(player);
FTBUltiminePlayerData data = getOrCreatePlayerData(player);
data.setPressed(pressed);
data.clearCache();

Expand All @@ -132,7 +143,7 @@ public void setKeyPressed(ServerPlayer player, boolean pressed) {
}

public void modeChanged(ServerPlayer player, boolean next) {
FTBUltiminePlayerData data = get(player);
FTBUltiminePlayerData data = getOrCreatePlayerData(player);
data.cycleShape(next);
data.clearCache();
new SendShapePacket(data.getCurrentShapeIndex(), Collections.emptyList()).sendTo(player);
Expand Down Expand Up @@ -167,7 +178,7 @@ public static boolean isValidTool(ItemStack mainHand, ItemStack offHand) {
}

public boolean canUltimine(Player player) {
if (PlayerHooks.isFake(player) || player.getUUID() == null) {
if (PlayerHooks.isFake(player) || player.getUUID() == null || CooldownTracker.isOnCooldown(player)) {
return false;
}

Expand All @@ -189,7 +200,7 @@ public EventResult blockBroken(Level world, BlockPos pos, BlockState state, Serv
return EventResult.pass();
}

FTBUltiminePlayerData data = get(player);
FTBUltiminePlayerData data = getOrCreatePlayerData(player);

if (!data.isPressed()) {
return EventResult.pass();
Expand All @@ -208,15 +219,21 @@ public EventResult blockBroken(Level world, BlockPos pos, BlockState state, Serv
return EventResult.pass();
}

if (player.totalExperience < data.cachedPositions().size() * FTBUltimineServerConfig.EXPERIENCE_PER_BLOCK.get()) {
return EventResult.pass();
}

isBreakingBlock = true;
tempBlockDropsList = new ItemCollection();
tempBlockDroppedXp = 0;
boolean hadItem = !player.getMainHandItem().isEmpty();

float baseSpeed = state.getDestroySpeed(world, pos);
int blocksMined = 0;
for (BlockPos p : data.cachedPositions()) {
float destroySpeed = world.getBlockState(p).getDestroySpeed(world, p);
if (!player.isCreative() && (destroySpeed < 0 || destroySpeed > baseSpeed)) {
BlockState state1 = world.getBlockState(p);
float destroySpeed = state1.getDestroySpeed(world, p);
if (!player.isCreative() && (destroySpeed < 0 || destroySpeed > baseSpeed || !player.hasCorrectToolForDrops(state1))) {
continue;
}
if (!player.gameMode.destroyBlock(p) && FTBUltimineServerConfig.CANCEL_ON_BLOCK_BREAK_FAIL.get()) {
Expand All @@ -231,14 +248,20 @@ public EventResult blockBroken(Level world, BlockPos pos, BlockState state, Serv
}

ItemStack stack = player.getMainHandItem();

if (hadItem && stack.isEmpty()) {
break;
} else if (hadItem && stack.hasTag() && stack.getTag().getBoolean("tic_broken")) {
break;
} else if (hadItem && FTBUltimineServerConfig.PREVENT_TOOL_BREAK.get() > 0 && stack.isDamageableItem() && stack.getDamageValue() >= stack.getMaxDamage() - FTBUltimineServerConfig.PREVENT_TOOL_BREAK.get()) {
break;
}

blocksMined++;
}

if (!player.isCreative()) {
CooldownTracker.setLastUltimineTime(player, System.currentTimeMillis());
data.addPendingXPCost(Math.max(0, blocksMined - 1));
}

isBreakingBlock = false;
Expand All @@ -260,7 +283,7 @@ public EventResult blockRightClick(Player player, InteractionHand hand, BlockPos
return EventResult.pass();
}

FTBUltiminePlayerData data = get(player);
FTBUltiminePlayerData data = getOrCreatePlayerData(player);
if (!data.isPressed()) {
return EventResult.pass();
}
Expand All @@ -282,7 +305,7 @@ public EventResult blockRightClick(Player player, InteractionHand hand, BlockPos
return EventResult.pass();
}

boolean didWork = false;
int didWork = 0;
if (FTBUltimineServerConfig.RIGHT_CLICK_HARVESTING.get() && shapeContext.matcher() == BlockMatcher.CROP_LIKE) {
didWork = RightClickHandlers.cropHarvesting(serverPlayer, hand, clickPos, face, data);
} else if (FTBUltimineServerConfig.RIGHT_CLICK_HOE.get() && serverPlayer.getItemInHand(hand).getItem() instanceof HoeItem) {
Expand All @@ -293,8 +316,12 @@ public EventResult blockRightClick(Player player, InteractionHand hand, BlockPos
didWork = RightClickHandlers.shovelFlattening(serverPlayer, hand, clickPos, data);
}

if (didWork) {
if (didWork > 0) {
player.swing(hand);
if (!player.isCreative()) {
CooldownTracker.setLastUltimineTime(player, System.currentTimeMillis());
data.addPendingXPCost(Math.max(0, didWork - 1));
}
return EventResult.interruptFalse();
} else {
return EventResult.pass();
Expand All @@ -303,7 +330,9 @@ public EventResult blockRightClick(Player player, InteractionHand hand, BlockPos

public void playerTick(Player player) {
if (player instanceof ServerPlayer serverPlayer) {
get(player).checkBlocks(serverPlayer, true, FTBUltimineServerConfig.getMaxBlocks(serverPlayer));
FTBUltiminePlayerData data = getOrCreatePlayerData(player);
data.checkBlocks(serverPlayer, true, FTBUltimineServerConfig.getMaxBlocks(serverPlayer));
data.takePendingXP(serverPlayer);
}
}

Expand Down Expand Up @@ -335,4 +364,11 @@ public static boolean isTooExhausted(ServerPlayer player) {
FoodData data = player.getFoodData();
return data.getExhaustionLevel() / 4f > data.getSaturationLevel() + data.getFoodLevel();
}

private static class DataReloadListener implements ResourceManagerReloadListener {
@Override
public void onResourceManagerReload(ResourceManager resourceManager) {
BlockMatcher.TagCache.onReload();
}
}
}
Loading

0 comments on commit 1dc9370

Please sign in to comment.