This is my first forum post so I aplogize if I do anything wrong or assume this is markdown somewhere since I'm used to it.
I'm building a mod to detect block changes, when people start raids, ...etc to prevent griefing while you afk.
Here is my code
package io.github.javaarchive.logitmod;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.Minecraft;
import net.minecraft.client.main.Main;
import net.minecraft.client.renderer.texture.NativeImage;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.ScreenShotHelper;
import net.minecraft.util.Util;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextComponent;
import net.minecraft.world.World;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.ForgeConfig.Client;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.entity.player.EntityItemPickupEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.BlockEvent.BreakEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.InterModComms;
import net.minecraftforge.fml.TextComponentMessageFormatHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent;
import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
// The value here should match an entry in the META-INF/mods.toml file
@Mod("logit")
@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.FORGE)
public class LogitMod
{
// Directly reference a log4j logger.
private static final Logger LOGGER = LogManager.getLogger();
public boolean DONOTDOUBLEEVENT = true;
PrintWriter pw;
public String EVIDENCE_DIR = "evidence";
public LogitMod() {
// Register the setup method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
// Register the enqueueIMC method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::enqueueIMC);
// Register the processIMC method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::processIMC);
// Register the doClientStuff method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::doClientStuff);
// Register ourselves for server and other game events we are interested in
MinecraftForge.EVENT_BUS.register(this);
}
public String getFormattedTime() {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy_HH-mm-ss");
Date date = new Date();
return formatter.format(date);
}
private void setup(final FMLCommonSetupEvent event)
{
// some preinit code
LOGGER.info("HELLO FROM PREINIT");
try {
pw = new PrintWriter(new BufferedWriter(new FileWriter("log-"+this.getFormattedTime()+".txt")));
File evidenceDir = new File(EVIDENCE_DIR);
if(!evidenceDir.isDirectory()) {
evidenceDir.mkdir();
}
}catch(IOException ex) {
ex.printStackTrace();
}
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
pw.close();
}
});
LOGGER.info("The DIRT BLOCK >> {}", Blocks.DIRT.getRegistryName());
}
private void doClientStuff(final FMLClientSetupEvent event) {
// do something that can only be done on the client
LOGGER.info("Got game settings {}", event.getMinecraftSupplier().get().gameSettings);
}
private void enqueueIMC(final InterModEnqueueEvent event)
{
// some example code to dispatch IMC to another mod
InterModComms.sendTo("examplemod", "helloworld", () -> { LOGGER.info("Hello world from the MDK"); return "Hello world";});
}
private void processIMC(final InterModProcessEvent event)
{
// some example code to receive and process InterModComms from other mods
LOGGER.info("Got IMC {}", event.getIMCStream().
map(m->m.getMessageSupplier().get()).
collect(Collectors.toList()));
}
// You can use SubscribeEvent and let the Event Bus discover methods to call
@SubscribeEvent
public void onServerStarting(FMLServerStartingEvent event) {
// do something when the server starts
LOGGER.info("HELLO from server starting");
}
public boolean isValuable(String name) {
if(name.contains("diamond")) {
return true;
}
return false;
}
@SubscribeEvent
public void ItemTossEvent(net.minecraftforge.event.entity.item.ItemTossEvent event) {
//System.out.println("Item picked up!");
if(isValuable(event.getEntityItem().getName().getString().toLowerCase())){
Minecraft mc = Minecraft.getInstance();
ITextComponent tc = new StringTextComponent("You have dropped a valuable item. It's name is "+event.getEntityItem().getName().getString()+" and it is waiting for you at "+Math.floor(event.getEntityItem().getPosX())+", "+Math.floor(event.getEntityItem().getPosY())+", "+Math.floor(event.getEntityItem().getPosZ()));
mc.player.sendMessage(tc);
//mc.getConnection()
//ScreenshotHelper.
/*
ScreenShotHelper.saveScreenshot(new File(EVIDENCE_DIR+"/"+getFormattedTime()+".jpg"), mc.currentScreen.width, mc.currentScreen.height, mc.getFramebuffer(), new Consumer<ITextComponent>() {
@Override
public void accept(ITextComponent arg0) {
// TODO Auto-generated method stub
}});
*/
/*try {
//screenshot.write(new File(EVIDENCE_DIR+"/"+getFormattedTime()+".jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} */
pw.println("ALERT: You dropped a "+event.getEntityItem().getName().getString());
}
pw.println("You dropped a "+event.getEntityItem().getName().getString()+" at "+Math.floor(event.getEntityItem().getPosX())+", "+Math.floor(event.getEntityItem().getPosY())+", "+Math.floor(event.getEntityItem().getPosZ()));
}
// You can use EventBusSubscriber to automatically subscribe events on the contained class (this is subscribing to the MOD
// Event bus for receiving Registry Events)
public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
if(player.getName().getString().equals(Minecraft.getInstance().player.getName().getString()) && DONOTDOUBLEEVENT) {
return; // We have our own handler for this
}
Block block = state.getBlock();
pw.println("The player "+player.getName().getString()+" broke(harvested) a "+block.getNameTextComponent().getString()+" block at "+pos.getX()+", "+pos.getY()+", "+pos.getZ());
}
public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(placer.getName().getString().equals(Minecraft.getInstance().player.getName().getString()) && DONOTDOUBLEEVENT) {
return; // We have our own handler for this
}
pw.println(placer.getName()+" placed a "+state.getBlock().getNameTextComponent().getString()+" block at "+" at "+pos.getX()+", "+pos.getY()+", "+pos.getZ());
}
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) {
pw.println("Block activated by "+player.getName().getString()+" at "+pos.getX()+", "+pos.getY()+", "+pos.getZ());
if(worldIn.isRemote) {
return true;
}else {
return false;
}
}
public void onBlockClicked(BlockState state, World worldIn, BlockPos pos, PlayerEntity player) {
if(player.getName().getString().equals(Minecraft.getInstance().player.getName().getString()) && DONOTDOUBLEEVENT) {
return; // We have our own handler for this
}
Block block = state.getBlock();
pw.println("The player "+player.getName().getString()+" left-clicked a "+block.getNameTextComponent().getString()+" block at "+pos.getX()+", "+pos.getY()+", "+pos.getZ());
}
@SubscribeEvent
public void GuiOpenEvent(GuiScreenEvent gui) {
//gui.getClass()
pw.flush();
}
@SubscribeEvent
public void onBlockPlaced(BlockEvent.EntityPlaceEvent event)
{
pw.println("You placed a "+event.getPlacedBlock().getBlock().getNameTextComponent().getString()+" at "+event.getPos().getX()+", "+event.getPos().getY()+", "+event.getPos().getZ());
}
@SubscribeEvent
public void onBreakBlock(BreakEvent event) {
PlayerEntity player = event.getPlayer();
BlockPos pos = event.getPos();
Block block = event.getState().getBlock();
if(player.getName().getString().equals(Minecraft.getInstance().player.getName().getString()) && DONOTDOUBLEEVENT) {
//return; // We have our own handler for this
}
pw.println("The player "+player.getName().getString()+" left-clicked a "+block.getNameTextComponent().getString()+" block at "+pos.getX()+", "+pos.getY()+", "+pos.getZ());
}
@SubscribeEvent
public void onBlockBreakEvent(BlockEvent.BreakEvent event)
{
// Check if a spawner broke
if(event.getState().getBlock() == Blocks.SPAWNER)
{
pw.println("ALERT: YOU BROKE A SPAWNER");
}
pw.println("Broke the block "+event.getState().getBlock().getNameTextComponent().getString()+" at "+event.getPos().getX()+", "+event.getPos().getY()+", "+event.getPos().getZ());
}
@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
public static class RegistryEvents {
@SubscribeEvent
public static void onBlocksRegistry(final RegistryEvent.Register<Block> blockRegistryEvent) {
// register a new block here
LOGGER.info("HELLO from Register Block");
}
}
}
This works when I play in a singleplayer world however when I build it, and copy it into a standard forge minecraft 1.15.2 client and run it none of the events are triggered. The log file is created but is empty. I know it's probaly a bad idea to flush the file when the inventory opens but that's just temporary testing.
Second question: Since I'm not able to test yet but does my code detect other players breaking/placing blocks. If so how can I make it detect those events?