Compare commits
8 Commits
8856bec073
...
1.3.1
Author | SHA1 | Date | |
---|---|---|---|
b6bb6565a8 | |||
8cebb278b8 | |||
f17519a547 | |||
8be2f2dc31 | |||
091efb900a | |||
824c84e329 | |||
73b8be0930 | |||
645529a9f6 |
53
README.md
53
README.md
@ -1,38 +1,43 @@
|
|||||||
# Survival Fabric
|
|
||||||
|
|
||||||
|
# 
|
||||||
|
|
||||||
This mod is FAR FROM FINISHED, and initially just created for our private Survival Server.
|
This mod is FAR FROM FINISHED, and initially just created for our private Survival Server.
|
||||||
As a challenge I'm trying to make it as user-friendly as possible. (It ain't there yet tho ;) )
|
As a challenge I'm trying to make it as user-friendly as possible. (It ain't there yet tho ;) )
|
||||||
## Current feature-set
|
## Current feature-set
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
- Custom join message
|
- Custom join message
|
||||||
- Custom quit message
|

|
||||||
- Custom chat message
|
- Custom quit message
|
||||||
- Tab list dimension indicator
|

|
||||||
|
- Custom chat message
|
||||||
|

|
||||||
|
- Tab list dimension indicator
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
- Config
|
||||||
|
- Configurable messages
|
||||||
|
- Feature toggle
|
||||||
|
- Version "control"
|
||||||
|
- Shared Ender Chest
|
||||||
|
- Shared EC Access control (via config)
|
||||||
|
- Vein miner
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
### Commands
|
### Commands
|
||||||
- /spectator | Essentially server-side free-cam, you get put in spectator and are able to fly around, once you use the command again you get put back to where you were.
|
- /spectator | Essentially server-side free-cam, you get put in spectator and are able to fly around, once you use the command again you get put back to where you were.
|
||||||
|
- /slimechunk (/sc) | See if you're currently in a slimechunk
|
||||||
## Currently working on v1.3.0
|
|
||||||
|
|
||||||
### Features
|
|
||||||
- [x] Config
|
|
||||||
- [x] Configurable messages
|
|
||||||
- [x] Feature toggle
|
|
||||||
- [x] Version "control"
|
|
||||||
- [x] Shared Ender Chest
|
|
||||||
- [x] Shared EC Access control (via config)
|
|
||||||
- [ ] Vein miner
|
|
||||||
- [ ] Telekinesis
|
|
||||||
|
|
||||||
### Commands
|
|
||||||
|
|
||||||
- [ ] /slimechunk (/sc) | See if you're currently in a slimechunk
|
|
||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
- [x] Updated icon
|
- Updated icon
|
||||||
|
|
||||||
## Features to come
|
## Features to come
|
||||||
|
|
||||||
For now there are no more feautures!
|
- Telekinesis
|
||||||
Be sure to give your idea by [opening an issue](https://git.hak.wtf/hkuijlman/SurvivalFabric/issues/new) wit the label Feature Request
|
|
||||||
|
Other than that no more features!
|
||||||
|
Be sure to give your idea by [opening an issue](https://git.hak.wtf/hkuijlman/SurvivalFabric/issues/new) with the label Feature Request
|
@ -4,14 +4,14 @@ org.gradle.parallel=true
|
|||||||
|
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://fabricmc.net/develop
|
# check these on https://fabricmc.net/develop
|
||||||
minecraft_version=1.21.4
|
minecraft_version=1.21.5
|
||||||
yarn_mappings=1.21.4+build.8
|
yarn_mappings=1.21.5+build.1
|
||||||
loader_version=0.16.10
|
loader_version=0.16.10
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=1.3.0
|
mod_version=1.3.1
|
||||||
maven_group=wtf.hak.survivalfabric
|
maven_group=wtf.hak.survivalfabric
|
||||||
archives_base_name=survivalfabric
|
archives_base_name=survivalfabric
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
fabric_version=0.119.0+1.21.4
|
fabric_version=0.119.5+1.21.5
|
@ -3,11 +3,16 @@ package wtf.hak.survivalfabric;
|
|||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
|
||||||
|
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import wtf.hak.survivalfabric.commands.ReloadConfigCommand;
|
import wtf.hak.survivalfabric.commands.ReloadConfigCommand;
|
||||||
|
import wtf.hak.survivalfabric.commands.SlimeChunkCommand;
|
||||||
import wtf.hak.survivalfabric.commands.SpectatorCommand;
|
import wtf.hak.survivalfabric.commands.SpectatorCommand;
|
||||||
import wtf.hak.survivalfabric.sharedenderchest.SharedEnderChest;
|
import wtf.hak.survivalfabric.sharedenderchest.SharedEnderChest;
|
||||||
|
import wtf.hak.survivalfabric.veinminer.VeinMinerEvents;
|
||||||
|
|
||||||
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
|
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
|
||||||
|
|
||||||
@ -21,8 +26,22 @@ public class SurvivalFabric implements ModInitializer {
|
|||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SpectatorCommand.register(dispatcher, new String[] { "spectator", "s", "S", "camera", "c", "C", }));
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SpectatorCommand.register(dispatcher, new String[] { "spectator", "s", "S", "camera", "c", "C", }));
|
||||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> ReloadConfigCommand.register(dispatcher, new String[] { "reloadsurvivalconfig" }));
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> ReloadConfigCommand.register(dispatcher, new String[] { "reloadsurvivalconfig" }));
|
||||||
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SlimeChunkCommand.register(dispatcher, new String[] { "slimechunk", "sc" }));
|
||||||
|
|
||||||
if(getConfig().sharedEnderChestEnabled)
|
if(getConfig().sharedEnderChestEnabled)
|
||||||
new SharedEnderChest().onInitialize();
|
new SharedEnderChest().onInitialize();
|
||||||
|
|
||||||
|
if(getConfig().veinMinerEnabled) {
|
||||||
|
PlayerBlockBreakEvents.BEFORE.register((world, player, pos, state, blockEntity) -> {
|
||||||
|
if (player instanceof ServerPlayerEntity serverPlayer) {
|
||||||
|
return VeinMinerEvents.beforeBlockBreak(world, serverPlayer, pos, state);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ServerEntityEvents.ENTITY_LOAD.register(VeinMinerEvents::onEntityLoad);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package wtf.hak.survivalfabric.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import net.minecraft.server.command.CommandManager;
|
||||||
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.math.random.CheckedRandom;
|
||||||
|
import net.minecraft.util.math.random.ChunkRandom;
|
||||||
|
import net.minecraft.util.math.random.Random;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import wtf.hak.survivalfabric.config.ConfigManager;
|
||||||
|
|
||||||
|
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
|
||||||
|
|
||||||
|
public class SlimeChunkCommand {
|
||||||
|
|
||||||
|
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, String... aliases) {
|
||||||
|
for (String str : aliases)
|
||||||
|
dispatcher.register(CommandManager.literal(str)
|
||||||
|
.executes(SlimeChunkCommand::execute));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int execute(CommandContext<ServerCommandSource> context) {
|
||||||
|
ServerCommandSource source = context.getSource();
|
||||||
|
if (source.getEntity() == null) {
|
||||||
|
source.sendMessage(Text.literal("Console cannot go into spectator mode!"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ServerPlayerEntity p = (ServerPlayerEntity) source.getEntity();
|
||||||
|
Chunk chunk = p.getServerWorld().getChunk(p.getBlockPos());
|
||||||
|
Random slimeRandom = ChunkRandom.getSlimeRandom(chunk.getPos().x, chunk.getPos().z, p.getServerWorld().getSeed(), 987234911L);
|
||||||
|
if(slimeRandom.nextInt(10) == 0) {
|
||||||
|
p.sendMessage(Text.literal(getConfig().inSlimeChunkMessage));
|
||||||
|
} else
|
||||||
|
p.sendMessage(Text.literal(getConfig().notInSlimeChunkMessage));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
@ -32,6 +32,12 @@ public class Config {
|
|||||||
public boolean sharedEnderChestLimitedAccess = true;
|
public boolean sharedEnderChestLimitedAccess = true;
|
||||||
public List<String> sharedEnderChestNames = Lists.newArrayList("AlwaysHAK", "LunaticFox");
|
public List<String> sharedEnderChestNames = Lists.newArrayList("AlwaysHAK", "LunaticFox");
|
||||||
|
|
||||||
|
public String inSlimeChunkMessage = "§aYou're currently in a slime chunk";
|
||||||
|
public String notInSlimeChunkMessage = "§cYou're currently not in a slime chunk";
|
||||||
|
|
||||||
|
public boolean veinMinerEnabled = true;
|
||||||
|
public int maxVeinSize = 99999;
|
||||||
|
|
||||||
public ScreenHandlerType<GenericContainerScreenHandler> screenHandlerType() {
|
public ScreenHandlerType<GenericContainerScreenHandler> screenHandlerType() {
|
||||||
return switch (sharedEnderChestRows) {
|
return switch (sharedEnderChestRows) {
|
||||||
case 1 -> ScreenHandlerType.GENERIC_9X1;
|
case 1 -> ScreenHandlerType.GENERIC_9X1;
|
||||||
|
@ -28,6 +28,7 @@ import net.minecraft.util.collection.DefaultedList;
|
|||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import static wtf.hak.survivalfabric.SurvivalFabric.LOGGER;
|
||||||
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
|
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
|
||||||
|
|
||||||
public class SharedEnderChest implements ServerLifecycleEvents.ServerStopping, ServerLifecycleEvents.ServerStarted, ServerTickEvents.EndTick {
|
public class SharedEnderChest implements ServerLifecycleEvents.ServerStopping, ServerLifecycleEvents.ServerStarted, ServerTickEvents.EndTick {
|
||||||
@ -46,7 +47,7 @@ public class SharedEnderChest implements ServerLifecycleEvents.ServerStopping, S
|
|||||||
Inventories.readNbt(nbt, inventoryItemStacks, server.getRegistryManager());
|
Inventories.readNbt(nbt, inventoryItemStacks, server.getRegistryManager());
|
||||||
sharedInventory = new SharedInventory(inventoryItemStacks);
|
sharedInventory = new SharedInventory(inventoryItemStacks);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println("[ShareEnderChest] Error while loading inventory: " + e);
|
LOGGER.error("Error while loading Shared Ender Chest: " + e);
|
||||||
sharedInventory = new SharedInventory(getConfig().sharedEnderChestRows);
|
sharedInventory = new SharedInventory(getConfig().sharedEnderChestRows);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -64,10 +65,9 @@ public class SharedEnderChest implements ServerLifecycleEvents.ServerStopping, S
|
|||||||
inventoryFile.createNewFile();
|
inventoryFile.createNewFile();
|
||||||
NbtIo.writeCompressed(nbt, inventoryFileDataOutput);
|
NbtIo.writeCompressed(nbt, inventoryFileDataOutput);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println("[ShareEnderChest] Error while saving inventory: " + e);
|
LOGGER.error("Error while saving Shared Ender Chest: " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServerStopping(MinecraftServer server) {
|
public void onServerStopping(MinecraftServer server) {
|
||||||
saveInventory(server);
|
saveInventory(server);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
package wtf.hak.survivalfabric.sharedenderchest;
|
package wtf.hak.survivalfabric.sharedenderchest;
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.inventory.Inventories;
|
import net.minecraft.inventory.Inventories;
|
||||||
import net.minecraft.inventory.Inventory;
|
import net.minecraft.inventory.Inventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.collection.DefaultedList;
|
import net.minecraft.util.collection.DefaultedList;
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
public class SharedInventory implements Inventory {
|
public class SharedInventory implements Inventory {
|
||||||
|
|
||||||
private final DefaultedList<ItemStack> stacks;
|
private final DefaultedList<ItemStack> stacks;
|
||||||
@ -19,28 +18,6 @@ public class SharedInventory implements Inventory {
|
|||||||
this.stacks = dl;
|
this.stacks = dl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
@Override
|
|
||||||
public void onClose(PlayerEntity player) {
|
|
||||||
Inventory.super.onClose(player);
|
|
||||||
EnderChestBlockEntity blockEntity = enderChests.remove(player);
|
|
||||||
if (blockEntity != null)
|
|
||||||
blockEntity.onClose(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOpen(PlayerEntity player) {
|
|
||||||
Inventory.super.onOpen(player);
|
|
||||||
EnderChestBlockEntity blockEntity = enderChests.get(player);
|
|
||||||
if (blockEntity != null)
|
|
||||||
blockEntity.onOpen(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlockEntity(PlayerEntity player, EnderChestBlockEntity be) {
|
|
||||||
enderChests.put(player, be);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
public DefaultedList<ItemStack> getList(DefaultedList<ItemStack> dl) {
|
public DefaultedList<ItemStack> getList(DefaultedList<ItemStack> dl) {
|
||||||
dl = stacks;
|
dl = stacks;
|
||||||
@ -54,7 +31,7 @@ public class SharedInventory implements Inventory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
Iterator<ItemStack> var1 = this.stacks.iterator();
|
var var1 = this.stacks.iterator();
|
||||||
|
|
||||||
ItemStack itemStack_1;
|
ItemStack itemStack_1;
|
||||||
do {
|
do {
|
||||||
@ -62,7 +39,7 @@ public class SharedInventory implements Inventory {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemStack_1 = (ItemStack)var1.next();
|
itemStack_1 = var1.next();
|
||||||
} while(itemStack_1.isEmpty());
|
} while(itemStack_1.isEmpty());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -76,10 +53,6 @@ public class SharedInventory implements Inventory {
|
|||||||
@Override
|
@Override
|
||||||
public ItemStack removeStack(int int_1, int int_2) {
|
public ItemStack removeStack(int int_1, int int_2) {
|
||||||
ItemStack itemStack_1 = Inventories.splitStack(this.stacks, int_1, int_2);
|
ItemStack itemStack_1 = Inventories.splitStack(this.stacks, int_1, int_2);
|
||||||
if (!itemStack_1.isEmpty()) {
|
|
||||||
//this.container.onContentChanged(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return itemStack_1;
|
return itemStack_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +64,6 @@ public class SharedInventory implements Inventory {
|
|||||||
@Override
|
@Override
|
||||||
public void setStack(int i, ItemStack itemStack) {
|
public void setStack(int i, ItemStack itemStack) {
|
||||||
this.stacks.set(i, itemStack);
|
this.stacks.set(i, itemStack);
|
||||||
//this.container.onContentChanged(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
10
src/main/java/wtf/hak/survivalfabric/veinminer/Drill.java
Normal file
10
src/main/java/wtf/hak/survivalfabric/veinminer/Drill.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package wtf.hak.survivalfabric.veinminer;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
|
public interface Drill {
|
||||||
|
boolean canHandle(BlockState blockState);
|
||||||
|
boolean isRightTool(BlockPos pos);
|
||||||
|
boolean drill(BlockPos blockPos);
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package wtf.hak.survivalfabric.veinminer;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import wtf.hak.survivalfabric.veinminer.drills.LeavesDrill;
|
||||||
|
import wtf.hak.survivalfabric.veinminer.drills.OreDrill;
|
||||||
|
import wtf.hak.survivalfabric.veinminer.drills.WoodDrill;
|
||||||
|
|
||||||
|
public class VeinMinerEvents {
|
||||||
|
|
||||||
|
public static boolean beforeBlockBreak(World world, ServerPlayerEntity player, BlockPos pos, BlockState state) {
|
||||||
|
if (world.isClient) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isVeinMining = VeinMinerSession.sessionForPlayer(player) != null;
|
||||||
|
boolean canVeinMine = player.isInSneakingPose();
|
||||||
|
if (canVeinMine && !isVeinMining) {
|
||||||
|
VeinMinerSession session = VeinMinerSession.start(player, (ServerWorld)world, pos);
|
||||||
|
boolean shouldContinue = !mine(session);
|
||||||
|
session.finish();
|
||||||
|
return shouldContinue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onEntityLoad(Entity entity, ServerWorld world) {
|
||||||
|
BlockPos pos = entity.getBlockPos();
|
||||||
|
VeinMinerSession session = VeinMinerSession.sessionForPosition(pos);
|
||||||
|
if (session != null) {
|
||||||
|
entity.setPos(session.initialPos.getX(), session.initialPos.getY(), session.initialPos.getZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean mine(VeinMinerSession session) {
|
||||||
|
Drill[] drills = new Drill[] {
|
||||||
|
new OreDrill(session),
|
||||||
|
new WoodDrill(session),
|
||||||
|
new LeavesDrill(session)
|
||||||
|
};
|
||||||
|
|
||||||
|
BlockPos pos = session.initialPos;
|
||||||
|
BlockState blockState = session.world.getBlockState(pos);
|
||||||
|
for (Drill drill : drills) {
|
||||||
|
if (drill.canHandle(blockState) && drill.isRightTool(pos)) {
|
||||||
|
return drill.drill(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package wtf.hak.survivalfabric.veinminer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
|
public class VeinMinerSession {
|
||||||
|
private static ArrayList<VeinMinerSession> sessions = new ArrayList<>();
|
||||||
|
|
||||||
|
public ServerPlayerEntity player;
|
||||||
|
public ServerWorld world;
|
||||||
|
public Set<BlockPos> positions;
|
||||||
|
public BlockPos initialPos;
|
||||||
|
|
||||||
|
public static VeinMinerSession sessionForPlayer(ServerPlayerEntity player) {
|
||||||
|
for (var session: sessions) {
|
||||||
|
if (session.player == player) {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VeinMinerSession sessionForPosition(BlockPos position) {
|
||||||
|
for (var session: sessions) {
|
||||||
|
if (session.positions.contains(position)) {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VeinMinerSession start(ServerPlayerEntity player, ServerWorld world, BlockPos initialPos) {
|
||||||
|
var session = new VeinMinerSession(player, world, initialPos);
|
||||||
|
sessions.add(session);
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void finish(VeinMinerSession session) {
|
||||||
|
sessions.remove(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
private VeinMinerSession(ServerPlayerEntity player, ServerWorld world, BlockPos initialPos) {
|
||||||
|
this.player = player;
|
||||||
|
this.world = world;
|
||||||
|
this.initialPos = initialPos;
|
||||||
|
this.positions = new HashSet<>();
|
||||||
|
positions.add(initialPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPosition(BlockPos pos) {
|
||||||
|
positions.add(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePosition(BlockPos pos) {
|
||||||
|
positions.remove(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finish() {
|
||||||
|
finish(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,133 @@
|
|||||||
|
package wtf.hak.survivalfabric.veinminer.drills;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.MutableText;
|
||||||
|
import net.minecraft.text.PlainTextContent;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import wtf.hak.survivalfabric.veinminer.Drill;
|
||||||
|
import wtf.hak.survivalfabric.veinminer.VeinMinerSession;
|
||||||
|
|
||||||
|
import static wtf.hak.survivalfabric.SurvivalFabric.LOGGER;
|
||||||
|
|
||||||
|
public class DrillBase implements Drill {
|
||||||
|
|
||||||
|
protected VeinMinerSession session;
|
||||||
|
|
||||||
|
public DrillBase(VeinMinerSession session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canHandle(BlockState blockId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean drill(BlockPos blockPos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRightTool(BlockPos pos) {
|
||||||
|
var blockState = session.world.getBlockState(pos);
|
||||||
|
return session.player.getMainHandStack().isSuitableFor(blockState);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected interface ForXYZHandler {
|
||||||
|
public void handle(BlockPos pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected interface ForXYZCounter {
|
||||||
|
public int handle(BlockPos pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void forXYZ(BlockPos pos, int max, ForXYZHandler handler) {
|
||||||
|
forXYZ(pos, max, handlerPos -> {
|
||||||
|
handler.handle(handlerPos);
|
||||||
|
return 0;
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int forXYZ(BlockPos pos, int max, ForXYZCounter handler) {
|
||||||
|
return forXYZ(pos, max, handler, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void forXYZ(BlockPos pos, int max, ForXYZHandler handler, boolean forceVertical) {
|
||||||
|
forXYZ(pos, max, handlerPos -> {
|
||||||
|
handler.handle(handlerPos);
|
||||||
|
return 0;
|
||||||
|
}, forceVertical);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int forXYZ(BlockPos pos, int max, ForXYZCounter handler, boolean forceVertical) {
|
||||||
|
ArrayList<Integer> offsets = new ArrayList<Integer>();
|
||||||
|
for (int d = 0; d <= max; ++d) {
|
||||||
|
offsets.add(d);
|
||||||
|
if (d != -d) {
|
||||||
|
offsets.add(-d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] order = new String[] { "x", "y", "z" };
|
||||||
|
if (forceVertical) {
|
||||||
|
order = new String[] { "y", "x", "z" };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ServerPlayerEntity player = session.player;
|
||||||
|
boolean majorPitchChange = player.getPitch() < -45.0 || player.getPitch() > 45.0;
|
||||||
|
boolean majorYawChange = (player.getYaw() > 45.0 && player.getYaw() < 135.0) || (player.getYaw() < -45.0 && player.getYaw() > -135.0);
|
||||||
|
if (majorPitchChange) {
|
||||||
|
if (majorYawChange) {
|
||||||
|
order = new String[] { "y", "z", "x" };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
order = new String[] { "y", "x", "z" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (majorYawChange) {
|
||||||
|
order = new String[] { "z", "y", "x" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
for (int i1: offsets) {
|
||||||
|
for (int i2: offsets) {
|
||||||
|
for (int i3: offsets) {
|
||||||
|
int ix = order[0] == "x" ? i1 : order[1] == "x" ? i2 : i3;
|
||||||
|
int iy = order[0] == "y" ? i1 : order[1] == "y" ? i2 : i3;
|
||||||
|
int iz = order[0] == "z" ? i1 : order[1] == "z" ? i2 : i3;
|
||||||
|
|
||||||
|
int px = pos.getX() + ix;
|
||||||
|
int py = pos.getY() + iy;
|
||||||
|
int pz = pos.getZ() + iz;
|
||||||
|
|
||||||
|
counter += handler.handle(new BlockPos(px, py, pz));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean tryBreakBlock(BlockPos blockPos) {
|
||||||
|
session.addPosition(blockPos);
|
||||||
|
boolean success = isRightTool(blockPos) && session.player.interactionManager.tryBreakBlock(blockPos);
|
||||||
|
if (!success) {
|
||||||
|
session.removePosition(blockPos);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void _log(String message) {
|
||||||
|
PlainTextContent literal = new PlainTextContent.Literal(message);
|
||||||
|
Text text = MutableText.of(literal);
|
||||||
|
session.player.sendMessage(text);
|
||||||
|
LOGGER.info(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package wtf.hak.survivalfabric.veinminer.drills;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.registry.RegistryKeys;
|
||||||
|
import net.minecraft.registry.tag.TagKey;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import wtf.hak.survivalfabric.veinminer.VeinMinerSession;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
|
||||||
|
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
|
||||||
|
|
||||||
|
public class LeavesDrill extends DrillBase {
|
||||||
|
|
||||||
|
public LeavesDrill(VeinMinerSession session) {
|
||||||
|
super(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final TagKey<Block> leavesTag = TagKey.of(RegistryKeys.BLOCK, Identifier.of("survivalfabric", "leaves"));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canHandle(BlockState blockState) {
|
||||||
|
return blockState.isIn(leavesTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean drill(BlockPos startPos) {
|
||||||
|
ServerWorld world = session.world;
|
||||||
|
Block initialBlock = world.getBlockState(startPos).getBlock();
|
||||||
|
int brokenLeaves = 0;
|
||||||
|
ArrayDeque<BlockPos> pending = new ArrayDeque<BlockPos>();
|
||||||
|
pending.add(startPos);
|
||||||
|
|
||||||
|
while (!pending.isEmpty() && brokenLeaves < getConfig().maxVeinSize) {
|
||||||
|
BlockPos leavesPos = pending.remove();
|
||||||
|
Block leavesBlock = world.getBlockState(leavesPos).getBlock();
|
||||||
|
if (tryBreakBlock(leavesPos)) {
|
||||||
|
if (leavesBlock == initialBlock) {
|
||||||
|
brokenLeaves += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leavesBlock == initialBlock) {
|
||||||
|
// look around current block
|
||||||
|
forXYZ(leavesPos, 1, newPos -> {
|
||||||
|
BlockState newBlockState = world.getBlockState(newPos);
|
||||||
|
Block newBlock = newBlockState.getBlock();
|
||||||
|
boolean isSameOreBlock = newBlock == leavesBlock;
|
||||||
|
if (!pending.contains(newPos) && isSameOreBlock) {
|
||||||
|
pending.add(newPos);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package wtf.hak.survivalfabric.veinminer.drills;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.registry.RegistryKeys;
|
||||||
|
import net.minecraft.registry.tag.TagKey;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import wtf.hak.survivalfabric.veinminer.VeinMinerSession;
|
||||||
|
|
||||||
|
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
|
||||||
|
|
||||||
|
public class OreDrill extends DrillBase {
|
||||||
|
|
||||||
|
public OreDrill(VeinMinerSession session) {
|
||||||
|
super(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final TagKey<Block> oreTag = TagKey.of(RegistryKeys.BLOCK, Identifier.of("survivalfabric", "ore"));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canHandle(BlockState blockState) {
|
||||||
|
return blockState.isIn(oreTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean drill(BlockPos startPos) {
|
||||||
|
ServerWorld world = session.world;
|
||||||
|
Block initialBlock = world.getBlockState(startPos).getBlock();
|
||||||
|
int brokenOre = 0;
|
||||||
|
ArrayDeque<BlockPos> pending = new ArrayDeque<BlockPos>();
|
||||||
|
pending.add(startPos);
|
||||||
|
|
||||||
|
while (!pending.isEmpty() && brokenOre < getConfig().maxVeinSize) {
|
||||||
|
BlockPos orePos = pending.remove();
|
||||||
|
Block oreBlock = world.getBlockState(orePos).getBlock();
|
||||||
|
if (tryBreakBlock(orePos)) {
|
||||||
|
if (oreBlock == initialBlock) {
|
||||||
|
brokenOre += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oreBlock == initialBlock) {
|
||||||
|
// look around current block
|
||||||
|
forXYZ(orePos, 1, newPos -> {
|
||||||
|
BlockState newBlockState = world.getBlockState(newPos);
|
||||||
|
Block newBlock = newBlockState.getBlock();
|
||||||
|
boolean isSameOreBlock = newBlock == oreBlock;
|
||||||
|
if (!pending.contains(newPos) && isSameOreBlock) {
|
||||||
|
pending.add(newPos);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package wtf.hak.survivalfabric.veinminer.drills;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.registry.RegistryKeys;
|
||||||
|
import net.minecraft.registry.tag.TagKey;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import wtf.hak.survivalfabric.veinminer.VeinMinerSession;
|
||||||
|
|
||||||
|
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
|
||||||
|
|
||||||
|
public class WoodDrill extends DrillBase {
|
||||||
|
|
||||||
|
public WoodDrill(VeinMinerSession session) {
|
||||||
|
super(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final TagKey<Block> woodTag = TagKey.of(RegistryKeys.BLOCK, Identifier.of("survivalfabric", "wood"));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canHandle(BlockState blockState) {
|
||||||
|
return blockState.isIn(woodTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean drill(BlockPos startPos) {
|
||||||
|
ServerWorld world = session.world;
|
||||||
|
int broken = 0;
|
||||||
|
ArrayDeque<BlockPos> pendingLogs = new ArrayDeque<BlockPos>();
|
||||||
|
ArrayDeque<BlockPos> logBlocks = new ArrayDeque<BlockPos>();
|
||||||
|
pendingLogs.add(startPos);
|
||||||
|
|
||||||
|
String leavesBlockId = Registries.BLOCK.getId(world.getBlockState(startPos).getBlock()).toString().replace("_log", "_leaves");
|
||||||
|
|
||||||
|
while (!pendingLogs.isEmpty() && broken < getConfig().maxVeinSize) {
|
||||||
|
BlockPos woodPos = pendingLogs.remove();
|
||||||
|
Block woodBlock = world.getBlockState(woodPos).getBlock();
|
||||||
|
|
||||||
|
if (tryBreakBlock(woodPos)) {
|
||||||
|
logBlocks.add(woodPos);
|
||||||
|
broken += 1;
|
||||||
|
|
||||||
|
// look around current block
|
||||||
|
forXYZ(woodPos, 1, newPos -> {
|
||||||
|
Block newBlock = world.getBlockState(newPos).getBlock();
|
||||||
|
if (newBlock == woodBlock && !pendingLogs.contains(newPos)) {
|
||||||
|
pendingLogs.add(newPos);
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// second round, leaves
|
||||||
|
// The pending blocks are all air now,
|
||||||
|
ArrayDeque<BlockPos> pendingLeaves = logBlocks;
|
||||||
|
while (!pendingLeaves.isEmpty() && broken < getConfig().maxVeinSize) {
|
||||||
|
// remove the immediately surrounding leaves around the log blocks
|
||||||
|
broken += forXYZ(pendingLeaves.remove(), 1, newPos -> {
|
||||||
|
int brokenLeaves = 0;
|
||||||
|
Block newBlock = world.getBlockState(newPos).getBlock();
|
||||||
|
String newBlockId = Registries.BLOCK.getId(newBlock).toString();
|
||||||
|
if (newBlockId.equals(leavesBlockId)) {
|
||||||
|
if (tryBreakBlock(newPos)) {
|
||||||
|
brokenLeaves += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return brokenLeaves;
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLeaf(Block block) {
|
||||||
|
return Registries.BLOCK.getId(block).toString().endsWith("_leaves");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"values": [
|
||||||
|
"#minecraft:leaves"
|
||||||
|
]
|
||||||
|
}
|
14
src/main/resources/data/survivalfabric/tags/block/ore.json
Normal file
14
src/main/resources/data/survivalfabric/tags/block/ore.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"values": [
|
||||||
|
"#minecraft:iron_ores",
|
||||||
|
"#minecraft:gold_ores",
|
||||||
|
"#minecraft:lapis_ores",
|
||||||
|
"#minecraft:redstone_ores",
|
||||||
|
"#minecraft:diamond_ores",
|
||||||
|
"#minecraft:emerald_ores",
|
||||||
|
"#minecraft:coal_ores",
|
||||||
|
"#minecraft:copper_ores",
|
||||||
|
"minecraft:ancient_debris",
|
||||||
|
"minecraft:magma_block"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"values": [
|
||||||
|
"#minecraft:logs"
|
||||||
|
]
|
||||||
|
}
|
Reference in New Issue
Block a user