From 8354ed6c09e960d2f48d7bc40b7c7978947524eb Mon Sep 17 00:00:00 2001 From: ketsuban_152 Date: Sat, 4 Jul 2026 21:59:07 +0900 Subject: Initial commit --- src/main/java/luckyblock/Main.java | 59 ++++++++++++++ .../java/luckyblock/action/LuckyActionHolder.java | 62 +++++++++++++++ .../java/luckyblock/action/LuckyActionManager.java | 67 ++++++++++++++++ .../action/triggers/BroadcastTrigger.java | 33 ++++++++ .../luckyblock/action/triggers/ILuckyTrigger.java | 12 +++ .../action/triggers/SummonItemTrigger.java | 34 ++++++++ .../luckyblock/action/triggers/SummonTrigger.java | 72 +++++++++++++++++ .../action/triggers/TrappedRoomTrigger.java | 38 +++++++++ src/main/java/luckyblock/block/LuckyBlock.java | 15 ++++ .../luckyblock/configurations/Configuration.java | 92 ++++++++++++++++++++++ .../java/luckyblock/configurations/Settings.java | 39 +++++++++ .../luckyblock/listener/LuckyBlockListener.java | 61 ++++++++++++++ 12 files changed, 584 insertions(+) create mode 100644 src/main/java/luckyblock/Main.java create mode 100644 src/main/java/luckyblock/action/LuckyActionHolder.java create mode 100644 src/main/java/luckyblock/action/LuckyActionManager.java create mode 100644 src/main/java/luckyblock/action/triggers/BroadcastTrigger.java create mode 100644 src/main/java/luckyblock/action/triggers/ILuckyTrigger.java create mode 100644 src/main/java/luckyblock/action/triggers/SummonItemTrigger.java create mode 100644 src/main/java/luckyblock/action/triggers/SummonTrigger.java create mode 100644 src/main/java/luckyblock/action/triggers/TrappedRoomTrigger.java create mode 100644 src/main/java/luckyblock/block/LuckyBlock.java create mode 100644 src/main/java/luckyblock/configurations/Configuration.java create mode 100644 src/main/java/luckyblock/configurations/Settings.java create mode 100644 src/main/java/luckyblock/listener/LuckyBlockListener.java (limited to 'src/main/java') diff --git a/src/main/java/luckyblock/Main.java b/src/main/java/luckyblock/Main.java new file mode 100644 index 0000000..e6c525e --- /dev/null +++ b/src/main/java/luckyblock/Main.java @@ -0,0 +1,59 @@ +package luckyblock; + +import com.mojang.logging.LogUtils; +import luckyblock.action.LuckyActionManager; +import luckyblock.block.LuckyBlock; +import luckyblock.configurations.Configuration; +import luckyblock.configurations.Settings; +import luckyblock.listener.LuckyBlockListener; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fml.loading.FMLPaths; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; +import org.slf4j.Logger; + +import java.util.List; + +@Mod(Main.MODID) +public class Main { + public static final String MODID = "lucky_block"; + public static Settings settings; + + private static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID); + private static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID); + + public static final RegistryObject LUCKY_BLOCK = BLOCKS.register("lucky_block", LuckyBlock::new); + public static final RegistryObject LUCKY_BLOCK_ITEM = ITEMS.register("lucky_block", () -> { + return new BlockItem(LUCKY_BLOCK.get(), new Item.Properties()); + }); + + private static final Logger LOGGER = LogUtils.getLogger(); + + public Main(FMLJavaModLoadingContext context) { + // === Register + IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus(); + BLOCKS.register(eventBus); + ITEMS.register(eventBus); + + // === Configurations + String path = FMLPaths.CONFIGDIR.get().resolve("settings.json").toString(); + Configuration config = new Configuration(path, new Settings()); + settings = config.load(); + + // === Event BUS + MinecraftForge.EVENT_BUS.register(LuckyActionManager.class); + MinecraftForge.EVENT_BUS.register(new LuckyBlockListener()); + + } + + public static Logger getLOGGER() { + return LOGGER; + } +} diff --git a/src/main/java/luckyblock/action/LuckyActionHolder.java b/src/main/java/luckyblock/action/LuckyActionHolder.java new file mode 100644 index 0000000..b18ad67 --- /dev/null +++ b/src/main/java/luckyblock/action/LuckyActionHolder.java @@ -0,0 +1,62 @@ +package luckyblock.action; + +import com.google.gson.JsonElement; +import com.google.gson.annotations.SerializedName; +import luckyblock.action.triggers.*; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; + +import java.util.ArrayList; +import java.util.List; + +public class LuckyActionHolder { + private static final List cmdList = new ArrayList<>(); + + static { + cmdList.add(new BroadcastTrigger()); + cmdList.add(new SummonItemTrigger()); + cmdList.add(new SummonTrigger()); + cmdList.add(new TrappedRoomTrigger()); + } + + public String type = ""; + public int weight = -1; + public List queue; + + @SerializedName("delay-queue") + public List delay_queue; + public JsonElement json; + public List items; + public List mobs; + public int count = 1; + public int height = 0; + @SerializedName("is-powered") + public boolean is_powered = false; + @SerializedName("wall-block") + public String wall_block = "minecraft:stone_bricks"; + public int radius = 3; + + public void execute(Level level, BlockPos pos) { + if (!(level instanceof ServerLevel serverLevel)) { return; } + + for (ILuckyTrigger c : cmdList) { + if (this.type != null && this.type.equals(c.getName())) { + c.execute(serverLevel, pos, this, level.getRandom()); + break; + } + } + + if (this.queue != null && !this.queue.isEmpty()) { + for (int i=0;i actions = new LinkedList<>(); + + public static void enqueue(String actionField, BlockPos pos, ServerLevel level, int delayTicks) { + actions.offer(new Task(actionField, pos, level, delayTicks)); + } + + public static void enqueue(String actionField, BlockPos pos, int delayTicks) { + if (net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer() != null) { + enqueue(actionField, pos, net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer().overworld(), delayTicks); + } + } + + @SubscribeEvent + public static void onServerTick(TickEvent.ServerTickEvent event) { + if (event.phase != TickEvent.Phase.END + || actions.isEmpty() + || Main.settings == null) { + return; + } + + int size = actions.size(); + for (int i=0;i messages = new ArrayList<>(); + if (holder.json.isJsonArray()) { + holder.json.getAsJsonArray().forEach(e -> messages.add(e.getAsString())); + } else if (holder.json.isJsonPrimitive()) { + messages.add(holder.json.getAsString()); + } + for (String msg : messages) { + level.getServer().getPlayerList().broadcastSystemMessage(Component.literal(msg), false); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/luckyblock/action/triggers/ILuckyTrigger.java b/src/main/java/luckyblock/action/triggers/ILuckyTrigger.java new file mode 100644 index 0000000..6e42d01 --- /dev/null +++ b/src/main/java/luckyblock/action/triggers/ILuckyTrigger.java @@ -0,0 +1,12 @@ +package luckyblock.action.triggers; + +import luckyblock.action.LuckyActionHolder; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; + +public interface ILuckyTrigger { + String getName(); + + void execute(ServerLevel level, BlockPos pos, LuckyActionHolder holder, RandomSource random); +} diff --git a/src/main/java/luckyblock/action/triggers/SummonItemTrigger.java b/src/main/java/luckyblock/action/triggers/SummonItemTrigger.java new file mode 100644 index 0000000..fbf44ff --- /dev/null +++ b/src/main/java/luckyblock/action/triggers/SummonItemTrigger.java @@ -0,0 +1,34 @@ +package luckyblock.action.triggers; + + +import luckyblock.action.LuckyActionHolder; +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; + +public class SummonItemTrigger implements ILuckyTrigger { + @Override + public String getName() { + return "summon_item"; + } + + @Override + public void execute(ServerLevel level, BlockPos pos, LuckyActionHolder holder, RandomSource random) { + if (holder.items != null) { + for (String itemId : holder.items) { + var item = BuiltInRegistries.ITEM.get(new ResourceLocation(itemId)); + if (item != Blocks.AIR.asItem()) { + for (int i = 0; i < holder.count; i++) { + ItemEntity entity = new ItemEntity(level, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, new ItemStack(item)); + level.addFreshEntity(entity); + } + } + } + } + } +} diff --git a/src/main/java/luckyblock/action/triggers/SummonTrigger.java b/src/main/java/luckyblock/action/triggers/SummonTrigger.java new file mode 100644 index 0000000..54103f5 --- /dev/null +++ b/src/main/java/luckyblock/action/triggers/SummonTrigger.java @@ -0,0 +1,72 @@ +package luckyblock.action.triggers; + + +import luckyblock.action.LuckyActionHolder; +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.entity.item.PrimedTnt; +import net.minecraft.world.entity.monster.Creeper; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class SummonTrigger implements ILuckyTrigger { + @Override + public String getName() { + return "summon"; + } + + @Override + public void execute(ServerLevel level, BlockPos pos, LuckyActionHolder holder, RandomSource random) { + if (holder.items != null) { + for (String itemId : holder.items) { + if (itemId.equals("minecraft:tnt")) { + for (int i = 0; i < holder.count; i++) { + PrimedTnt tnt = new PrimedTnt(EntityType.TNT, level); + double rx = pos.getX() + 0.5 + (random.nextDouble() - 0.5) * 4; + double rz = pos.getZ() + 0.5 + (random.nextDouble() - 0.5) * 4; + double ry = pos.getY() + holder.height; + tnt.moveTo(rx, ry, rz, 0.0F, 0.0F); + tnt.setFuse(holder.height > 0 ? 40 + random.nextInt(20) : 60 + random.nextInt(20)); + level.addFreshEntity(tnt); + } + } else { + Block block = BuiltInRegistries.BLOCK.get(new ResourceLocation(itemId)); + if (block != Blocks.AIR) { + BlockState blockState = block.defaultBlockState(); + for (int i = 0; i < holder.count; i++) { + BlockPos spawnPos = pos.above(holder.height + i); + FallingBlockEntity falling = FallingBlockEntity.fall(level, spawnPos, blockState); + level.addFreshEntity(falling); + } + } + } + } + } + if (holder.mobs != null) { + for (String mobId : holder.mobs) { + EntityType entityType = BuiltInRegistries.ENTITY_TYPE.get(new ResourceLocation(mobId)); + if (entityType != null) { + for (int i = 0; i < holder.count; i++) { + BlockPos spawnPos = pos.above(holder.height > 0 ? holder.height : 1); + var entity = entityType.spawn(level, spawnPos, MobSpawnType.COMMAND); + if (entity instanceof Creeper creeper && holder.is_powered) { + CompoundTag nbt = new CompoundTag(); + creeper.saveWithoutId(nbt); + nbt.putBoolean("powered", true); + creeper.load(nbt); + } + } + } + } + } + } +} + diff --git a/src/main/java/luckyblock/action/triggers/TrappedRoomTrigger.java b/src/main/java/luckyblock/action/triggers/TrappedRoomTrigger.java new file mode 100644 index 0000000..818fb07 --- /dev/null +++ b/src/main/java/luckyblock/action/triggers/TrappedRoomTrigger.java @@ -0,0 +1,38 @@ +package luckyblock.action.triggers; + + +import luckyblock.action.LuckyActionHolder; +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class TrappedRoomTrigger implements ILuckyTrigger { + @Override + public String getName() { + return "trapped_room"; + } + + @Override + public void execute(ServerLevel level, BlockPos pos, LuckyActionHolder holder, RandomSource random) { + Block block = BuiltInRegistries.BLOCK.get(new ResourceLocation(holder.wall_block)); + BlockState wallState = (block != null) ? block.defaultBlockState() : Blocks.STONE_BRICKS.defaultBlockState(); + int r = holder.radius; + for (int x = -r; x <= r; x++) { + for (int y = 0; y <= r * 2; y++) { + for (int z = -r; z <= r; z++) { + BlockPos targetPos = pos.offset(x, y, z); + if (Math.abs(x) == r || Math.abs(z) == r || y == 0 || y == r * 2) { + level.setBlock(targetPos, wallState, 3); + } else { + level.setBlock(targetPos, Blocks.AIR.defaultBlockState(), 3); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/luckyblock/block/LuckyBlock.java b/src/main/java/luckyblock/block/LuckyBlock.java new file mode 100644 index 0000000..753b6c3 --- /dev/null +++ b/src/main/java/luckyblock/block/LuckyBlock.java @@ -0,0 +1,15 @@ +package luckyblock.block; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.material.MapColor; + +public class LuckyBlock extends Block { + public LuckyBlock() { + super(Properties + .of() + .mapColor(MapColor.GOLD) + .strength(5.0F, 1200F) + .sound(SoundType.STONE)); + } +} diff --git a/src/main/java/luckyblock/configurations/Configuration.java b/src/main/java/luckyblock/configurations/Configuration.java new file mode 100644 index 0000000..a3b366e --- /dev/null +++ b/src/main/java/luckyblock/configurations/Configuration.java @@ -0,0 +1,92 @@ +package luckyblock.configurations; + +import com.google.gson.*; +import luckyblock.Main; +import luckyblock.action.LuckyActionHolder; + +import java.io.*; +import java.lang.reflect.Field; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +public class Configuration { + private final File file; + private final Object impl; + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + public Configuration(File file, Object impl) { + this.file = file; + this.impl = impl; + + this.loadFromResources(this.impl); + + if (!file.exists()) { + this.loadDefault(); + } + } + + public Configuration(String path, Object impl) { + this(new File(path), impl); + } + + private void loadFromResources(Object r) { + try (InputStream input = Main.class.getResourceAsStream("/settings.json")) { + if (input == null) return; + + JsonObject root = JsonParser.parseReader(new InputStreamReader(input, StandardCharsets.UTF_8)).getAsJsonObject(); + this.model(r, root); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected void loadDefault() { + try { + file.getParentFile().mkdirs(); + JsonObject root = new JsonObject(); + String section = (String) this.impl.getClass().getField("section").get(this.impl); + root.add(section, gson.toJsonTree(this.impl).getAsJsonObject().get("events")); + + try (FileWriter writer = new FileWriter(file)) { + gson.toJson(root, writer); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public T load() { + try { + if (!file.exists() || file.length() == 0) { + this.loadDefault(); + } + JsonObject root = JsonParser.parseReader(new FileReader(file)).getAsJsonObject(); + this.model(this.impl, root); + return (T) this.impl; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @SuppressWarnings("unchecked") + private void model(Object r, JsonObject root) throws Exception { + String section = (String) r.getClass().getField("section").get(r); + if (!root.has(section)) return; + JsonObject sectionJson = root.getAsJsonObject(section); + for (Field field : r.getClass().getDeclaredFields()) { + if (field.getName().equals("section")) continue; + field.setAccessible(true); + if (Map.class.isAssignableFrom(field.getType())) { + Map eventsMap = (Map) field.get(r); + if (eventsMap != null) { + eventsMap.clear(); + for (Map.Entry entry : sectionJson.entrySet()) { + String k = entry.getKey().replace("-", "_"); + LuckyActionHolder holder = gson.fromJson(entry.getValue(), LuckyActionHolder.class); + eventsMap.put(k, holder); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/luckyblock/configurations/Settings.java b/src/main/java/luckyblock/configurations/Settings.java new file mode 100644 index 0000000..53b8b3a --- /dev/null +++ b/src/main/java/luckyblock/configurations/Settings.java @@ -0,0 +1,39 @@ +package luckyblock.configurations; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import luckyblock.Main; +import luckyblock.action.LuckyActionHolder; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +public class Settings { + public String section = "LuckyBlock"; + + public Map events = new HashMap<>(); + + public Settings() { + try (InputStream input = Main.class.getResourceAsStream("/settings.json")) { + if (input != null) { + Gson gson = new Gson(); + JsonObject root = JsonParser.parseReader(new InputStreamReader(input, StandardCharsets.UTF_8)).getAsJsonObject(); + Main.getLOGGER().info(root.toString()); + if (root.has(this.section)) { + JsonObject sectionJson = root.getAsJsonObject(this.section); + for (Map.Entry entry : sectionJson.entrySet()) { + String k = entry.getKey().replace("-", "_"); + LuckyActionHolder holder = gson.fromJson(entry.getValue(), LuckyActionHolder.class); + this.events.put(k, holder); + } + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/src/main/java/luckyblock/listener/LuckyBlockListener.java b/src/main/java/luckyblock/listener/LuckyBlockListener.java new file mode 100644 index 0000000..b291aa2 --- /dev/null +++ b/src/main/java/luckyblock/listener/LuckyBlockListener.java @@ -0,0 +1,61 @@ +package luckyblock.listener; + +import luckyblock.Main; +import luckyblock.action.LuckyActionHolder; +import luckyblock.action.LuckyActionManager; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraftforge.event.level.BlockEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class LuckyBlockListener { + @SubscribeEvent + public void onBlockBreak(BlockEvent.BreakEvent event) { + if (event.getLevel().isClientSide() + || !(event.getLevel() instanceof ServerLevel level) + || Main.settings == null) { + return; + } + + if (!event.getState().is(Main.LUCKY_BLOCK.get())) { return; } + + BlockPos pos = event.getPos(); + Map events = Main.settings.events; + RandomSource random = level.getRandom(); + + List poolNames = new ArrayList<>(); + List poolWeights = new ArrayList<>(); + int totalWeight = 0; + + for (Map.Entry entry:events.entrySet()) { + String Name = entry.getKey(); + LuckyActionHolder holder = entry.getValue(); + + if (holder.weight == 0) { + LuckyActionManager.enqueue(Name, pos, 0); + }else if (holder.weight > 0) { + poolNames.add(Name); + poolWeights.add(holder.weight); + totalWeight += holder.weight; + } + } + + if (totalWeight > 0 && !poolNames.isEmpty()) { + int rolled = random.nextInt(totalWeight); + int sum = 0; + for (int i=0;i< poolNames.size();i++) { + sum += poolWeights.get(i); + if (rolled < sum) { + LuckyActionManager.enqueue(poolNames.get(i), pos, 0); + break; + } + } + } + + } +} -- cgit v1.2.1