Skip to content

Commit

Permalink
Replace the lamps' mob-killing logic with mob-blocking logic.
Browse files Browse the repository at this point in the history
  • Loading branch information
Baughn committed Feb 15, 2019
1 parent ba18a05 commit ae15706
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 90 deletions.
8 changes: 4 additions & 4 deletions src/main/java/mods/eln/Eln.java
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,7 @@ public class Eln {
public double fuelHeatFurnacePowerFactor = 1;
public int autominerRange = 10;

public boolean killMonstersAroundLamps;
public int killMonstersAroundLampsRange;
public int blockMonstersAroundLampsRange;

double stdBatteryHalfLife = 2 * Utils.minecraftDay;
double batteryCapacityFactor = 1.;
Expand All @@ -311,6 +310,7 @@ public class Eln {

public static double maxSoundDistance = 16;
private double cablePowerFactor;
private int lampMonsterBlockRange = 8;

@EventHandler
public void preInit(FMLPreInitializationEvent event) {
Expand Down Expand Up @@ -389,6 +389,7 @@ public void preInit(FMLPreInitializationEvent event) {
fuelGeneratorPowerFactor = config.get("balancing", "fuelGeneratorPowerFactor", 1).getDouble(1);
fuelHeatFurnacePowerFactor = config.get("balancing", "fuelHeatFurnacePowerFactor", 1.0).getDouble();
autominerRange = config.get("balancing", "autominerRange", 10, "Maximum horizontal distance from autominer that will be mined").getInt(10);
lampMonsterBlockRange = config.get("balancing", "lampMonsterBlockRange", 8, "Maximum distance for which lamps block monster spawning", 0, 32768).getInt();

Other.ElnToIc2ConversionRatio = config.get("balancing", "ElnToIndustrialCraftConversionRatio", 1.0 / 3.0).getDouble(1.0 / 3.0);
Other.ElnToOcConversionRatio = config.get("balancing", "ElnToOpenComputerConversionRatio", 1.0 / 3.0 / 2.5).getDouble(1.0 / 3.0 / 2.5);
Expand All @@ -405,8 +406,7 @@ public void preInit(FMLPreInitializationEvent event) {
replicatorPop = config.get("entity", "replicatorPop", true).getBoolean(true);
ReplicatorPopProcess.popPerSecondPerPlayer = config.get("entity", "replicatorPopWhenThunderPerSecond", 1.0 / 120).getDouble(1.0 / 120);
replicatorRegistrationId = config.get("entity", "replicatorId", -1).getInt(-1);
killMonstersAroundLamps = config.get("entity", "killMonstersAroundLamps", true).getBoolean(true);
killMonstersAroundLampsRange = config.get("entity", "killMonstersAroundLampsRange", 9).getInt(9);
blockMonstersAroundLampsRange = config.get("entity", "blockMonstersAroundLampsRange", 12).getInt(12);

forceOreRegen = config.get("mapGenerate", "forceOreRegen", false).getBoolean(false);
genCopper = config.get("mapGenerate", "copper", true).getBoolean(true);
Expand Down
61 changes: 61 additions & 0 deletions src/main/java/mods/eln/eventhandlers/MonsterEventHandler.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package mods.eln.eventhandlers

import mods.eln.entity.ReplicatorEntity
import mods.eln.misc.Coordonate
import mods.eln.misc.OctoTree
import net.minecraft.entity.boss.EntityWither
import net.minecraftforge.event.entity.EntityJoinWorldEvent
import kotlin.math.roundToInt

/**
* This is not an efficient way to do anything.
*
* The octree is a good start. It's fine in terms of CPU use, more or less, but that memory use scares me and is
* also entirely pointless. I'll have to find (or invent) a better algorithm. Though, the octree implementation
* supports clusterization so... maybe that's at least partially fine?
*
* It's also far too easy to imagine this counter getting desynced from reality.
* Although it seems to be working so far.
*/

object MonsterEventHandler {
private val trees: MutableMap<Int, OctoTree<Int>> = HashMap()

fun onSpawn(event: EntityJoinWorldEvent) {
val entity = event.entity
if (entity is ReplicatorEntity || entity is EntityWither) {
return
}
val x = entity.posX.roundToInt() + 32768
val y = entity.posY.roundToInt() + 32768
val z = entity.posZ.roundToInt() + 32768
if (trees[entity.dimension]?.get(x, y, z) ?: 0 > 0) {
event.isCanceled = true
}
}

private fun doCube(center: Coordonate, range: Int, f: (Int) -> Int) {
if (range <= 0) return
val xOffset = center.x + 32768
val yOffset = center.y + 32768
val zOffset = center.z + 32768
val tree = trees.getOrPut(center.dimention) { OctoTree(16) }
for (x in (xOffset - range)..(xOffset + range)) {
for (y in (yOffset - range)..(yOffset + range)) {
for (z in (zOffset - range)..(zOffset + range)) {
tree.set(x, y, z, f(tree.get(x, y, z) ?: 0))
}
}
}
}

fun registerMonsterBlock(coord: Coordonate, range: Int) {
println("Registering block at $coord - $range")
doCube(coord, range) { it + 1 }
}

fun unregisterMonsterBlock(coord: Coordonate, range: Int) {
println("Unregistering block at $coord - $range")
doCube(coord, range) { Math.max(0, it - 1) }
}
}
141 changes: 141 additions & 0 deletions src/main/java/mods/eln/misc/ocTree.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package mods.eln.misc

// Licensed under Apache 2.0
// Copyright JetBrains, 2017

class OctoTree<T>(val depth: Int) {

private var root: Node<T>? = null
private var actual = false

//-------------------------------------------------------------------------//

fun get(x: Int, y: Int, z: Int): T? {
var dep = depth
var iter = root
while (true) {
if (iter == null) return null
else if (iter is Node.Leaf) return iter.value

iter = (iter as Node.Branch<T>).nodes[number(x, y, z, --dep)]
}
}

//-------------------------------------------------------------------------//

fun set(x: Int, y: Int, z: Int, value: T) {
if (root == null) root = Node.Branch()
if (root!!.set(x, y, z, value, depth - 1)) {
root = Node.Leaf(value)
}
actual = false
}

//-------------------------------------------------------------------------//

override fun toString(): String = root.toString()

//-------------------------------------------------------------------------//

sealed class Node<T> {

abstract fun set(x: Int, y: Int, z: Int, value: T, depth: Int): Boolean

//---------------------------------------------------------------------//

class Leaf<T>(var value: T) : Node<T>() {

override fun set(x: Int, y: Int, z: Int, value: T, depth: Int): Boolean {
throw UnsupportedOperationException("set on Leaf element")
}

override fun toString(): String = "L{$value}"
}

//---------------------------------------------------------------------//

class Branch<T>() : Node<T>() {

constructor(value: T, exclude: Int) : this() {

var i = 0
while (i < 8) {
if (i != exclude) {
nodes[i] = Leaf(value)
}
i++
}
}

private fun canClusterize(value: T): Boolean {
var i = 0
while (i < 8) {
val w = nodes[i]
if (w == null || w !is Leaf || value != w.value) {
return false
}
i++
}
return true
}

override fun set(x: Int, y: Int, z: Int, value: T, depth: Int): Boolean {
val branchIndex = number(x, y, z, depth)
val node = nodes[branchIndex]
when (node) {
null -> {
if (depth == 0) {
nodes[branchIndex] = Leaf(value)
return canClusterize(value)
} else {
nodes[branchIndex] = Branch()
}
}
is Leaf<T> -> {
if (node.value == value) {
return false
} else if (depth == 0) {
node.value = value
return canClusterize(value)
}
nodes[branchIndex] = Branch(node.value, number(x, y, z, depth - 1))
}
}

if (nodes[branchIndex]!!.set(x, y, z, value, depth - 1)) {
nodes[branchIndex] = Leaf(value)
return canClusterize(value)
}
return false
}

val nodes = arrayOfNulls<Node<T>>(8)
override fun toString(): String = nodes.joinToString(prefix = "[", postfix = "]")
}
}
//-------------------------------------------------------------------------//

companion object {
fun number(x: Int, y: Int, z: Int, depth: Int): Int {
val mask = 1 shl depth
if (x and mask != 0) {
if (y and mask != 0) {
if (z and mask != 0)
return 7
return 6
}
if (z and mask != 0)
return 5
return 4
}
if (y and mask != 0) {
if (z and mask != 0)
return 3
return 2
}
if (z and mask != 0)
return 1
return 0
}
}
}
26 changes: 0 additions & 26 deletions src/main/java/mods/eln/server/ConsoleListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public class ConsoleListener extends CommandBase {
private final String cmdNameStr_newWind = "newWind";
private final String cmdNameStr_regenOre = "regenOre";
private final String cmdNameStr_generateLangFileTemplate = "generateLangFileTemplate";
private final String cmdNameStr_killMonstersAroundLamps = "killMonstersAroundLamps";

private final String strOffsetL0 = " ";
private final String strOffsetL1 = " ";
Expand All @@ -50,7 +49,6 @@ public ConsoleListener() {
cmdVisibleList.add(cmdNameStr_newWind);
cmdVisibleList.add(cmdNameStr_regenOre);
cmdVisibleList.add(cmdNameStr_generateLangFileTemplate);
cmdVisibleList.add(cmdNameStr_killMonstersAroundLamps);
java.util.Collections.sort(cmdVisibleList);
}

Expand Down Expand Up @@ -214,24 +212,9 @@ public void processCommand(ICommandSender ics, String[] astring) {
cprint(ics, Color.COLOR_DARK_CYAN + "ELN > " + Color.COLOR_DARK_YELLOW + cmdNameStr_generateLangFileTemplate);
cprint(ics, strOffsetL0 + "New language system parses source code, see here how to generate language " +
"files: https://github.com/Electrical-Age/ElectricalAge");
} else if (cmd.equalsIgnoreCase(cmdNameStr_killMonstersAroundLamps)) {
cprint(ics, Color.COLOR_DARK_CYAN + "ELN > " + Color.COLOR_DARK_YELLOW + cmdNameStr_killMonstersAroundLamps);
if (!checkArgCount(ics, astring, 1))
return;
ConsoleArg<Boolean> arg0 = getArgBool(ics, astring[1]);
if (!arg0.valid)
return;
Eln.instance.killMonstersAroundLamps = arg0.value;
cprint(ics, strOffsetL0 + "Avoid monsters spawning around lamps : " + Color.COLOR_DARK_GREEN + boolToStr(arg0.value));
cprint(ics, strOffsetL0 + "Warning: Command effective to this game instance only.");
} else {
cprint(ics, Color.COLOR_DARK_CYAN + "ELN > " + Color.COLOR_DARK_RED + "Error: Unknown command.");
}

return;

//Eln.simulator.setSimplify(!astring[1].equals("0"));
//Eln.simulator.pleaseCrash = true;
}

private boolean checkArgCount(ICommandSender ics, String[] args, int exceptedArgc) {
Expand Down Expand Up @@ -343,15 +326,6 @@ private void commandMan(ICommandSender ics, String cmd) {
cprint(ics, strOffsetL0 + "Parameters :");
cprint(ics, strOffsetL1 + "@0:string : full file path.");
cprint(ics, "");
} else if (cmd.equalsIgnoreCase(cmdNameStr_killMonstersAroundLamps)) {
cprint(ics, strOffsetL0 + "When set, monsters don't spawn around the lamps (default).");
cprint(ics, strOffsetL0 + "When clear, leaving lights on in dark zones is recommended...");
cprint(ics, strOffsetL0 + "Effective only during this game instance.");
cprint(ics, strOffsetL0 + "(See \"Eln.cfg\" for permanent effect.)");
cprint(ics, "");
cprint(ics, strOffsetL0 + "Parameters :");
cprint(ics, strOffsetL1 + "@0:bool : Enable/disable.");
cprint(ics, "");
} else {
cprint(ics, Color.COLOR_DARK_RED + strOffsetL0 + "Error : Unknown/Undocumented command.");
}
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/mods/eln/server/ServerEventListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
import cpw.mods.fml.common.gameevent.TickEvent.ServerTickEvent;
import mods.eln.Eln;
import mods.eln.eventhandlers.MonsterEventHandler;
import mods.eln.item.electricalitem.TreeCapitation;
import mods.eln.misc.Coordonate;
import mods.eln.misc.Utils;
import mods.eln.node.NodeManager;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.EntityEvent.EntityConstructing;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.event.world.WorldEvent.Load;
import net.minecraftforge.event.world.WorldEvent.Save;
Expand Down Expand Up @@ -46,9 +50,11 @@ public void tick(ServerTickEvent event) {
}

@SubscribeEvent
public void onNewEntity(EntityConstructing event) {
public void onNewEntity(EntityJoinWorldEvent event) {
if (event.entity instanceof EntityLightningBolt) {
lightningListNext.add((EntityLightningBolt) event.entity);
} else if (event.entity instanceof EntityMob) {
MonsterEventHandler.INSTANCE.onSpawn(event);
}
}

Expand Down
56 changes: 0 additions & 56 deletions src/main/java/mods/eln/sim/MonsterPopFreeProcess.java

This file was deleted.

Loading

0 comments on commit ae15706

Please sign in to comment.