1.12: v1.0.18 release commit. 1.14/1.15: Slab placement improved, Milking Machine cow tracking added, AI goals fixed.
This commit is contained in:
parent
0f05f8e112
commit
216c1259e2
21 changed files with 404 additions and 156 deletions
|
@ -4,4 +4,4 @@ org.gradle.jvmargs=-Xmx8G
|
|||
version_minecraft=1.12.2
|
||||
version_forge=14.23.5.2768
|
||||
version_jei=4.10.0.198
|
||||
version_engineersdecor=1.0.18-b3
|
||||
version_engineersdecor=1.0.18
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
|
||||
"1.12.2": {
|
||||
"1.0.18": "[R] Release based on v1.0.18-b2. Release-to-release changes: * Tree cutter config fixes. * Treated Wood Crafting Table mouse tweaks. * Lang updates.\n[M] Lang update ru_ru (PR#77, thanks Smollet777).",
|
||||
"1.0.18-b2": "[A] Added Treated Wood Crafting table tweaks (ctrl-shift moves all same stacks from the inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).\n[F] EN Lang file fixed (issue #76, thx Riverstar907).\n[F] Fixed Tree Cutter not respecting power-required config (thx federsavo, issue #77).",
|
||||
"1.0.18-b1": "[M] Lang ru_ru updated (Smollet777).",
|
||||
"1.0.17": "[R] Release based on v1.0.17-b3. Release-to-release changes: * Milking machine added. * Reverse recipes for slab slices added. * Texture and model improvements. * Lang file updates. * Minor bug fixes. * Config options added.\n[M] Updated zh_cn lang file (scikirbypoke).\n[A] Added opt-out config for the Small Tree Cutter.",
|
||||
|
@ -75,7 +76,7 @@
|
|||
"1.0.0-b1": "[A] Initial structure.\n[A] Added clinker bricks and clinker brick stairs.\n[A] Added slag bricks and slag brick stairs.\n[A] Added metal rung ladder.\n[A] Added staggered metal steps ladder.\n[A] Added treated wood ladder.\n[A] Added treated wood pole.\n[A] Added treated wood table."
|
||||
},
|
||||
"promos": {
|
||||
"1.12.2-recommended": "1.0.17",
|
||||
"1.12.2-latest": "1.0.18-b2"
|
||||
"1.12.2-recommended": "1.0.18",
|
||||
"1.12.2-latest": "1.0.18"
|
||||
}
|
||||
}
|
|
@ -10,7 +10,13 @@ Mod sources for Minecraft version 1.12.2.
|
|||
----
|
||||
## Version history
|
||||
|
||||
~ v1.0.18-b3
|
||||
-------------------------------------------------------------------
|
||||
- v1.0.18 [R] Release based on v1.0.18-b2. Release-to-release changes:
|
||||
* Tree cutter config fixes.
|
||||
* Treated Wood Crafting Table mouse tweaks.
|
||||
* Lang updates.
|
||||
-------------------------------------------------------------------
|
||||
[M] Lang update ru_ru (PR#77, thanks Smollet777).
|
||||
|
||||
- v1.0.18-b2 [A] Added Treated Wood Crafting table tweaks (ctrl-shift moves all same stacks from the
|
||||
inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
org.gradle.daemon=false
|
||||
org.gradle.jvmargs=-Xmx8G
|
||||
version_minecraft=1.14.4
|
||||
version_forge_minecraft=1.14.4-28.1.111
|
||||
version_forge_minecraft=1.14.4-28.1.116
|
||||
version_fml_mappings=20190719-1.14.3
|
||||
version_jei=1.14.4:6.0.0.10
|
||||
version_engineersdecor=1.0.18-b4
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
|
||||
"1.14.4": {
|
||||
"1.0.18-b4": "[M] Lang update ru_ru (PR#77, thanks Smollet777).\n[F] Fixed Milking machine cow path issue, added milking delay cow tracking.\n[F] Slab / Slab Slice placement adapted to vanilla standard.",
|
||||
"1.0.18-b3": "[A] Added Treated Wood Crafting table tweaks (ctrl-shift moves all same stacks from the inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).\n[F] EN Lang file fixed (issue #76, thx Riverstar907).\n[F] Fixed Tree Cutter not respecting power-required config (thx federsavo, issue #77).\n[F] Fixed Small Solar Panel not exposing energy capability (thx MatthiasMann, issue #78).",
|
||||
"1.0.18-b2": "[F] Fixed JEI integration warning if nothing is opt'ed out (thx @SDUBZ for reporting).\n[M] Lang ru_ru updated (Smollet777).",
|
||||
"1.0.18-b1": "[U] Updated to Forge 1.14.4-28.1.109/20190719-1.14.3.\n[A] Added opt-out config for the Small Tree Cutter.",
|
||||
|
@ -43,6 +44,6 @@
|
|||
},
|
||||
"promos": {
|
||||
"1.14.4-recommended": "",
|
||||
"1.14.4-latest": "1.0.18-b3"
|
||||
"1.14.4-latest": "1.0.18-b4"
|
||||
}
|
||||
}
|
|
@ -11,7 +11,9 @@ Mod sources for Minecraft version 1.14.4.
|
|||
|
||||
## Version history
|
||||
|
||||
~ v1.0.18-b4
|
||||
- v1.0.18-b4 [M] Lang update ru_ru (PR#77, thanks Smollet777).
|
||||
[F] Fixed Milking machine cow path issue, added milking delay cow tracking.
|
||||
[F] Slab / Slab Slice placement adapted to vanilla standard.
|
||||
|
||||
- v1.0.18-b3 [A] Added Treated Wood Crafting table tweaks (ctrl-shift moves all same stacks from the
|
||||
inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
*/
|
||||
package wile.engineersdecor.blocks;
|
||||
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.world.IWorld;
|
||||
import wile.engineersdecor.detail.ModAuxiliaries;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
|
@ -40,7 +43,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
public class BlockDecorHalfSlab extends BlockDecor implements IWaterLoggable
|
||||
public class BlockDecorHalfSlab extends BlockDecor.WaterLoggable
|
||||
{
|
||||
public static final IntegerProperty PARTS = IntegerProperty.create("parts", 0, 14);
|
||||
|
||||
|
@ -103,7 +106,7 @@ public class BlockDecorHalfSlab extends BlockDecor implements IWaterLoggable
|
|||
|
||||
@Override
|
||||
protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder)
|
||||
{ super.fillStateContainer(builder); builder.add(PARTS, WATERLOGGED); }
|
||||
{ super.fillStateContainer(builder); builder.add(PARTS); }
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
|
@ -193,4 +196,13 @@ public class BlockDecorHalfSlab extends BlockDecor implements IWaterLoggable
|
|||
SoundType st = this.getSoundType(state, world, pos, null);
|
||||
world.playSound(player, pos, st.getPlaceSound(), SoundCategory.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean receiveFluid(IWorld world, BlockPos pos, BlockState state, IFluidState fluidState)
|
||||
{ return (state.get(PARTS)==14) ? false : super.receiveFluid(world, pos, state, fluidState); }
|
||||
|
||||
@Override
|
||||
public boolean canContainFluid(IBlockReader world, BlockPos pos, BlockState state, Fluid fluid)
|
||||
{ return (state.get(PARTS)==14) ? false : super.canContainFluid(world, pos, state, fluid); }
|
||||
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import javax.annotation.Nonnull;
|
|||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
||||
|
@ -143,12 +144,14 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
public static final int MAX_ENERGY_BUFFER = 16000;
|
||||
public static final int MAX_ENERGY_TRANSFER = 512;
|
||||
public static final int DEFAULT_ENERGY_CONSUMPTION = 0;
|
||||
public static final int DEFAULT_MILKING_DELAY_PER_COW = 4000;
|
||||
private static final Direction FLUID_TRANSFER_DIRECTRIONS[] = {Direction.DOWN,Direction.EAST,Direction.SOUTH,Direction.WEST,Direction.NORTH};
|
||||
private enum MilkingState { IDLE, PICKED, COMING, POSITIONING, MILKING, LEAVING, WAITING }
|
||||
|
||||
private static FluidStack milk_fluid_ = new FluidStack(Fluids.WATER, 0);
|
||||
private static HashMap<ItemStack, ItemStack> milk_containers_ = new HashMap<>();
|
||||
private static int energy_consumption = DEFAULT_ENERGY_CONSUMPTION;
|
||||
private static long min_milking_delay_per_cow_ticks = DEFAULT_MILKING_DELAY_PER_COW;
|
||||
private int tick_timer_;
|
||||
private int energy_stored_;
|
||||
private int tank_level_ = 0;
|
||||
|
@ -158,9 +161,10 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
private int state_timer_ = 0;
|
||||
private BlockPos tracked_cow_original_position_ = null;
|
||||
|
||||
public static void on_config(int energy_consumption_per_tick)
|
||||
public static void on_config(int energy_consumption_per_tick, int min_milking_delay_per_cow)
|
||||
{
|
||||
energy_consumption = MathHelper.clamp(energy_consumption_per_tick, 0, 128);
|
||||
min_milking_delay_per_cow_ticks = MathHelper.clamp(min_milking_delay_per_cow, 1000, 24000);
|
||||
{
|
||||
Fluid milk = null; // FluidRe.getFluid("milk");
|
||||
if(milk != null) milk_fluid_ = new FluidStack(milk, BUCKET_SIZE);
|
||||
|
@ -299,8 +303,9 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
|
||||
// ITickable ------------------------------------------------------------------------------------
|
||||
|
||||
private void log(String s)
|
||||
{} // println("Milker|" + s); may be enabled with config, for dev was println
|
||||
private void log(String s) {} // println("Milker|" + s); may be enabled with config, for dev was println
|
||||
|
||||
private static final HashMap<Integer, Long> tracked_cows_ = new HashMap<Integer, Long>();
|
||||
|
||||
private static ItemStack milk_filled_container_item(ItemStack stack)
|
||||
{ return milk_containers_.entrySet().stream().filter(e->e.getKey().isItemEqual(stack)).map(Map.Entry::getValue).findFirst().orElse(ItemStack.EMPTY); }
|
||||
|
@ -331,6 +336,10 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
if(cow != null) {
|
||||
cow.setNoAI(false);
|
||||
SingleMoveGoal.abortFor(cow);
|
||||
tracked_cows_.remove(cow.getEntityId());
|
||||
for(int id:tracked_cows_.keySet().stream().filter(i->cow.getEntityWorld().getEntityByID(i)==null).collect(Collectors.toList())) {
|
||||
tracked_cows_.remove(id);
|
||||
}
|
||||
}
|
||||
tracked_cow_ = null;
|
||||
state_ = MilkingState.IDLE;
|
||||
|
@ -345,8 +354,15 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
CowEntity cow = null;
|
||||
{
|
||||
AxisAlignedBB aabb = new AxisAlignedBB(pos.offset(facing, 3)).grow(4, 2, 4);
|
||||
final long t = world.getGameTime();
|
||||
final List<CowEntity> cows = world.getEntitiesWithinAABB(CowEntity.class, aabb,
|
||||
e->( ((tracked_cow_==null) && ((!e.isChild()) && (!e.isInLove()) && (!e.isBeingRidden()))) || (e.getUniqueID().equals(tracked_cow_)) )
|
||||
e-> {
|
||||
if(e.getUniqueID().equals(tracked_cow_)) return true;
|
||||
if((tracked_cow_!=null) || e.isChild() || e.isInLove() || e.isBeingRidden()) return false;
|
||||
if(!e.getNavigator().noPath()) return false;
|
||||
if(Math.abs(tracked_cows_.getOrDefault(e.getEntityId(), 0L)-t) < min_milking_delay_per_cow_ticks) return false;
|
||||
return true;
|
||||
}
|
||||
);
|
||||
if(cows.size() == 1) {
|
||||
cow = cows.get(0); // tracked or only one
|
||||
|
@ -372,11 +388,12 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
BlockPos p = getPos().offset(facing,2);
|
||||
log("Idle: Shove off");
|
||||
blocker.setNoAI(false);
|
||||
SingleMoveGoal.startFor(blocker, p, 2, 1.0, (goal, world, pos)->(pos.distanceSq(goal.getCreature().getPosition())>49));
|
||||
SingleMoveGoal.startFor(blocker, p, 2, 1.0, (goal, world, pos)->(pos.distanceSq(goal.getCreature().getPosition())>100));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(cow.getLeashed() || cow.isChild() || cow.isInLove() || (!cow.onGround) || cow.isBeingRidden() || cow.isSprinting()) return false;
|
||||
tracked_cows_.put(cow.getEntityId(), cow.getEntityWorld().getGameTime());
|
||||
tracked_cow_ = cow.getUniqueID();
|
||||
state_ = MilkingState.PICKED;
|
||||
state_timeout_ = 200;
|
||||
|
@ -387,13 +404,7 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
case PICKED: {
|
||||
SingleMoveGoal.startFor(
|
||||
cow, target_pos, 2, 1.0,
|
||||
(goal, world, pos)->{
|
||||
if(pos.distanceSq(goal.getCreature().getPosition())>100) return true;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if(world.getBlockState(pos.offset(Direction.byHorizontalIndex(i))).getBlock() instanceof BlockDecorMilker) return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
(goal, world, pos)->(pos.distanceSq(goal.getCreature().getPosition())>100),
|
||||
(goal, world, pos)->{
|
||||
log("move: position reached");
|
||||
goal.getCreature().setLocationAndAngles(goal.getTargetPosition().getX(), goal.getTargetPosition().getY(), goal.getTargetPosition().getZ(), facing.getHorizontalAngle(), 0);
|
||||
|
@ -422,6 +433,7 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
}
|
||||
case POSITIONING: {
|
||||
log("Positioning: start milking");
|
||||
SingleMoveGoal.abortFor(cow);
|
||||
cow.setNoAI(true);
|
||||
cow.setLocationAndAngles(target_pos.getX(), target_pos.getY(), target_pos.getZ(), facing.getHorizontalAngle(), 0);
|
||||
world.playSound(null, pos, SoundEvents.ENTITY_COW_MILK, SoundCategory.BLOCKS, 0.5f, 1f);
|
||||
|
@ -447,13 +459,18 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
state_timer_ = 500;
|
||||
tick_timer_ = TICK_INTERVAL;
|
||||
state_ = MilkingState.WAITING;
|
||||
tracked_cows_.put(cow.getEntityId(), cow.getEntityWorld().getGameTime());
|
||||
log("Leaving: process done");
|
||||
return true;
|
||||
}
|
||||
case WAITING: {
|
||||
// wait for the timeout to kick in until starting with the next.
|
||||
tick_timer_ = TICK_INTERVAL;
|
||||
log("Waiting: ...");
|
||||
if(state_timer_ < 40) {
|
||||
tracked_cow_ = null;
|
||||
release_cow(null);
|
||||
}
|
||||
log("Waiting time elapsed");
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
|
@ -510,8 +527,9 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
{
|
||||
@FunctionalInterface public interface TargetPositionInValidCheck { boolean test(SingleMoveGoal goal, IWorldReader world, BlockPos pos); }
|
||||
@FunctionalInterface public interface StrollEvent { void apply(SingleMoveGoal goal, IWorldReader world, Vec3d pos); }
|
||||
private static void log(String s) {} // println(s);
|
||||
private static void log(String s) {} // println("SingleMoveGoal: "+s);
|
||||
|
||||
private static final HashMap<Integer, SingleMoveGoal> tracked_entities_ = new HashMap<Integer, SingleMoveGoal>();
|
||||
private static final int motion_timeout = 20*20;
|
||||
private boolean aborted_;
|
||||
private boolean in_position_;
|
||||
|
@ -538,14 +556,40 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
public static void startFor(CreatureEntity entity, BlockPos target_pos, int priority, double speed, TargetPositionInValidCheck abort_condition)
|
||||
{ startFor(entity, new Vec3d(target_pos.getX(),target_pos.getY(),target_pos.getZ()), priority, speed, abort_condition, null, null); }
|
||||
|
||||
public static void startFor(CreatureEntity entity, Vec3d target_pos, int priority, double speed, TargetPositionInValidCheck abort_condition, @Nullable StrollEvent on_position_reached, @Nullable StrollEvent on_aborted)
|
||||
{ entity.goalSelector.addGoal(priority, new SingleMoveGoal(entity, target_pos, speed, abort_condition, on_position_reached, on_aborted)); }
|
||||
public static boolean startFor(CreatureEntity entity, Vec3d target_pos, int priority, double speed, TargetPositionInValidCheck abort_condition, @Nullable StrollEvent on_position_reached, @Nullable StrollEvent on_aborted)
|
||||
{
|
||||
synchronized(tracked_entities_) {
|
||||
SingleMoveGoal goal = tracked_entities_.getOrDefault(entity.getEntityId(), null);
|
||||
if(goal != null) {
|
||||
if(!goal.aborted()) return false; // that is still running.
|
||||
entity.goalSelector.removeGoal(goal);
|
||||
}
|
||||
log("::start("+entity.getEntityId()+")");
|
||||
goal = new SingleMoveGoal(entity, target_pos, speed, abort_condition, on_position_reached, on_aborted);
|
||||
tracked_entities_.put(entity.getEntityId(), goal);
|
||||
entity.goalSelector.addGoal(priority, goal);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isActiveFor(CreatureEntity entity)
|
||||
{ return (entity != null) && (entity.goalSelector.getRunningGoals().anyMatch(g->(g.getGoal()) instanceof SingleMoveGoal)); }
|
||||
{ return (entity != null) && (entity.goalSelector.getRunningGoals().anyMatch(
|
||||
g->((g.getGoal()) instanceof SingleMoveGoal) && (!((SingleMoveGoal)(g.getGoal())).aborted())
|
||||
)); }
|
||||
|
||||
public static void abortFor(CreatureEntity entity)
|
||||
{ entity.goalSelector.getRunningGoals().filter(g->(g.getGoal()) instanceof SingleMoveGoal).forEach(g->((SingleMoveGoal)g.getGoal()).abort()); }
|
||||
{
|
||||
log("::abort("+entity.getEntityId()+")");
|
||||
if(entity.isAlive()) {
|
||||
entity.goalSelector.getRunningGoals().filter(g->(g.getGoal()) instanceof SingleMoveGoal).forEach(g->((SingleMoveGoal)g.getGoal()).abort());
|
||||
}
|
||||
final World world = entity.getEntityWorld();
|
||||
if(world != null) {
|
||||
// @todo: check nicer way to filter a map.
|
||||
List<Integer> to_remove = tracked_entities_.keySet().stream().filter(i->(world.getEntityByID(i) == null)).collect(Collectors.toList());
|
||||
for(int id:to_remove)tracked_entities_.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
public Vec3d getTargetPosition()
|
||||
{ return target_pos_; }
|
||||
|
@ -553,34 +597,48 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
public CreatureEntity getCreature()
|
||||
{ return creature; }
|
||||
|
||||
public void abort()
|
||||
public synchronized void abort()
|
||||
{ aborted_ = true; }
|
||||
|
||||
public synchronized boolean aborted()
|
||||
{ return aborted_; }
|
||||
|
||||
public synchronized void initialize(Vec3d target_pos, double speed, TargetPositionInValidCheck abort_condition, @Nullable StrollEvent on_position_reached, @Nullable StrollEvent on_aborted)
|
||||
{
|
||||
abort_condition_ = abort_condition;
|
||||
on_target_position_reached_ = on_position_reached;
|
||||
on_aborted_ = on_aborted;
|
||||
destinationBlock = new BlockPos(target_pos.getX(), target_pos.getY(), target_pos.getZ());
|
||||
timeoutCounter = 0;
|
||||
runDelay = 0;
|
||||
aborted_ = false;
|
||||
was_aborted_ = false;
|
||||
target_pos_ = new Vec3d(target_pos.getX(), target_pos.getY(), target_pos.getZ());
|
||||
// this.movementSpeed = speed; -> that is final, need to override tick and func_whatever
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTask()
|
||||
{ runDelay = 0; timeoutCounter = 0; }
|
||||
|
||||
@Override
|
||||
public double getTargetDistanceSq()
|
||||
{ return 1.2; }
|
||||
{ return 0.7; }
|
||||
|
||||
@Override
|
||||
public boolean shouldMove()
|
||||
{ return (timeoutCounter & 0x7) == 0; }
|
||||
{ return (!aborted()) && (timeoutCounter & 0x7) == 0; }
|
||||
|
||||
@Override
|
||||
public boolean shouldExecute()
|
||||
{
|
||||
if(!shouldMoveTo(creature.world, destinationBlock)) {
|
||||
aborted_ = true;
|
||||
return false;
|
||||
} else if(aborted_) {
|
||||
// shouldExecute is the point where in GoalSelector.tick() the goal is not in flagGoals and can be removed.
|
||||
creature.goalSelector.getRunningGoals().filter(g->(g.getGoal()) instanceof SingleMoveGoal).forEach(g->creature.goalSelector.removeGoal(g));
|
||||
creature.goalSelector.removeGoal(this);
|
||||
if(aborted_) {
|
||||
if((!was_aborted_) && (on_aborted_!=null)) on_aborted_.apply(this, creature.world, target_pos_);
|
||||
was_aborted_ = true;
|
||||
return false;
|
||||
} else if(!shouldMoveTo(creature.world, destinationBlock)) {
|
||||
synchronized(this) { aborted_ = true; }
|
||||
return false;
|
||||
} else if(--runDelay > 0) {
|
||||
return false;
|
||||
} else {
|
||||
|
@ -592,32 +650,69 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
@Override
|
||||
public void startExecuting()
|
||||
{
|
||||
log("startExecuting()");
|
||||
timeoutCounter = 0;
|
||||
if(!creature.getNavigator().tryMoveToXYZ(target_pos_.getX(), target_pos_.getY(), target_pos_.getZ(), this.movementSpeed)) abort();
|
||||
if(!creature.getNavigator().tryMoveToXYZ(target_pos_.getX(), target_pos_.getY(), target_pos_.getZ(), this.movementSpeed)) {
|
||||
abort();
|
||||
log("startExecuting() -> abort, no path");
|
||||
} else {
|
||||
log("startExecuting() -> started");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldContinueExecuting()
|
||||
{
|
||||
if((aborted_) || (creature.getNavigator().noPath()) || (timeoutCounter > motion_timeout) || (!shouldMoveTo(creature.world, destinationBlock))) {
|
||||
if(aborted()) {
|
||||
log("shouldContinueExecuting() -> already aborted");
|
||||
return false;
|
||||
} else if(creature.getNavigator().noPath()) {
|
||||
if((!creature.getNavigator().setPath(creature.getNavigator().func_225466_a(target_pos_.getX(), target_pos_.getY(), target_pos_.getZ(), 0), movementSpeed))) {
|
||||
log("shouldContinueExecuting() -> abort, no path");
|
||||
abort();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else if(timeoutCounter > motion_timeout) {
|
||||
log("shouldContinueExecuting() -> abort, timeout");
|
||||
abort();
|
||||
return false;
|
||||
} else if(!shouldMoveTo(creature.world, destinationBlock)) {
|
||||
log("shouldContinueExecuting() -> abort, !shouldMoveTo()");
|
||||
abort();
|
||||
return false;
|
||||
} else {
|
||||
log("shouldContinueExecuting() -> yes");
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldMoveTo(IWorldReader world, BlockPos pos)
|
||||
{ if(!abort_condition_.test(this, world, pos)) { return true; } abort(); return false; }
|
||||
{
|
||||
if(abort_condition_.test(this, world, pos)) {
|
||||
log("shouldMoveTo() -> abort_condition");
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
BlockPos testpos = new BlockPos(target_pos_.getX(), creature.getPositionVec().getY(), target_pos_.getZ());
|
||||
if(!testpos.withinDistance(creature.getPositionVec(), getTargetDistanceSq())) {
|
||||
if((++timeoutCounter > motion_timeout)) { abort(); return; }
|
||||
if(shouldMove() && (!creature.getNavigator().tryMoveToXYZ(target_pos_.getX(), target_pos_.getY(), target_pos_.getZ(), movementSpeed))) abort();
|
||||
if((++timeoutCounter > motion_timeout)) {
|
||||
log("tick() -> abort, timeoutCounter");
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
if(shouldMove() && (!creature.getNavigator().tryMoveToXYZ(target_pos_.getX(), target_pos_.getY(), target_pos_.getZ(), movementSpeed))) {
|
||||
log("tick() -> abort, !tryMoveToXYZ()");
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
log("tick() -> abort, in position)");
|
||||
in_position_ = true;
|
||||
abort();
|
||||
if(on_target_position_reached_ != null) on_target_position_reached_.apply(this, creature.world, target_pos_);
|
||||
|
|
|
@ -8,7 +8,10 @@
|
|||
*/
|
||||
package wile.engineersdecor.blocks;
|
||||
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.world.IWorld;
|
||||
import wile.engineersdecor.detail.ModAuxiliaries;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
|
@ -36,7 +39,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
public class BlockDecorSlab extends BlockDecor implements IWaterLoggable
|
||||
public class BlockDecorSlab extends BlockDecor.WaterLoggable
|
||||
{
|
||||
public static final IntegerProperty PARTS = IntegerProperty.create("parts", 0, 2);
|
||||
public static final IntegerProperty TEXTURE_VARIANT = IntegerProperty.create("tvariant", 0, 3);
|
||||
|
@ -93,16 +96,37 @@ public class BlockDecorSlab extends BlockDecor implements IWaterLoggable
|
|||
|
||||
@Override
|
||||
protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder)
|
||||
{ super.fillStateContainer(builder); builder.add(PARTS, TEXTURE_VARIANT, WATERLOGGED); }
|
||||
{ super.fillStateContainer(builder); builder.add(PARTS, TEXTURE_VARIANT); }
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public BlockState getStateForPlacement(BlockItemUseContext context)
|
||||
{
|
||||
final Direction facing = context.getFace();
|
||||
double y = context.getHitVec().getY();
|
||||
int rnd = MathHelper.clamp((int)(MathHelper.getPositionRandom(context.getPos()) % 4), 0, 3);
|
||||
return super.getStateForPlacement(context).with(PARTS, ((facing==Direction.UP) || ((facing!=Direction.DOWN) && (y < 0.6))) ? 0 : 1).with(TEXTURE_VARIANT, rnd);
|
||||
BlockPos pos = context.getPos();
|
||||
if(context.getWorld().getBlockState(pos).getBlock() == this) return context.getWorld().getBlockState(pos).with(PARTS, 2).with(WATERLOGGED, false);
|
||||
final int rnd = MathHelper.clamp((int)(MathHelper.getPositionRandom(context.getPos()) & 0x3), 0, 3);
|
||||
final Direction face = context.getFace();
|
||||
final BlockState placement_state = super.getStateForPlacement(context).with(TEXTURE_VARIANT, rnd); // fluid state
|
||||
if(face == Direction.UP) return placement_state.with(PARTS, 0);
|
||||
if(face == Direction.DOWN) return placement_state.with(PARTS, 1);
|
||||
if(!face.getAxis().isHorizontal()) return placement_state;
|
||||
final boolean isupper = ((context.getHitVec().getY() - context.getPos().getY()) > 0.5);
|
||||
return placement_state.with(PARTS, isupper ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean isReplaceable(BlockState state, BlockItemUseContext context)
|
||||
{
|
||||
if(context.getItem().getItem() != this.asItem()) return false;
|
||||
if(!context.replacingClickedOnBlock()) return true;
|
||||
final Direction face = context.getFace();
|
||||
final int parts = state.get(PARTS);
|
||||
if((face == Direction.UP) && (parts==0)) return true;
|
||||
if((face == Direction.DOWN) && (parts==1)) return true;
|
||||
if(!face.getAxis().isHorizontal()) return false;
|
||||
final boolean isupper = ((context.getHitVec().getY() - context.getPos().getY()) > 0.5);
|
||||
return isupper ? (parts==0) : (parts==1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -123,29 +147,6 @@ public class BlockDecorSlab extends BlockDecor implements IWaterLoggable
|
|||
public List<ItemStack> dropList(BlockState state, World world, BlockPos pos, boolean explosion)
|
||||
{ return new ArrayList<ItemStack>(Collections.singletonList(new ItemStack(this.asItem(), num_slabs_contained_in_parts_[state.get(PARTS) & 0x3]))); }
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult rayTraceResult)
|
||||
{
|
||||
Direction face = rayTraceResult.getFace();
|
||||
final ItemStack stack = player.getHeldItem(hand);
|
||||
if(stack.isEmpty() || (Block.getBlockFromItem(stack.getItem()) != this)) return false;
|
||||
int parts = state.get(PARTS);
|
||||
if(((face == Direction.UP) && (parts == 0)) || ((face == Direction.DOWN) && (parts == 1))) {
|
||||
world.setBlockState(pos, state.with(PARTS, 2), 3);
|
||||
} else {
|
||||
return false; // "not handled" -> let parent decide if a new slab has to be placed on top/bottom.
|
||||
}
|
||||
if(world.isRemote) return true;
|
||||
if(!player.isCreative()) {
|
||||
stack.shrink(1);
|
||||
if(player.inventory != null) player.inventory.markDirty();
|
||||
}
|
||||
SoundType st = this.getSoundType(state, world, pos, null);
|
||||
world.playSound(null, pos, st.getPlaceSound(), SoundCategory.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void onBlockClicked(BlockState state, World world, BlockPos pos, PlayerEntity player)
|
||||
|
@ -180,4 +181,11 @@ public class BlockDecorSlab extends BlockDecor implements IWaterLoggable
|
|||
world.playSound(player, pos, st.getPlaceSound(), SoundCategory.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean receiveFluid(IWorld world, BlockPos pos, BlockState state, IFluidState fluidState)
|
||||
{ return (state.get(PARTS)==2) ? false : super.receiveFluid(world, pos, state, fluidState); }
|
||||
|
||||
public boolean canContainFluid(IBlockReader world, BlockPos pos, BlockState state, Fluid fluid)
|
||||
{ return (state.get(PARTS)==2) ? false : super.canContainFluid(world, pos, state, fluid); }
|
||||
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ public class ModConfig
|
|||
public final ForgeConfigSpec.IntValue tree_cuttter_cutting_time_needed;
|
||||
public final ForgeConfigSpec.BooleanValue tree_cuttter_requires_power;
|
||||
public final ForgeConfigSpec.IntValue milking_machine_energy_consumption;
|
||||
public final ForgeConfigSpec.IntValue milking_machine_milking_delay;
|
||||
|
||||
CommonConfig(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
|
@ -476,6 +477,10 @@ public class ModConfig
|
|||
"Use zero to disable energy dependency and energy handling of the machine. " +
|
||||
"The config value can be changed on-the-fly for tuning.")
|
||||
.defineInRange("milking_machine_energy_consumption", BlockDecorMilker.BTileEntity.DEFAULT_ENERGY_CONSUMPTION, 0, 128);
|
||||
milking_machine_milking_delay = builder
|
||||
.translation(ModEngineersDecor.MODID + ".config.milking_machine_milking_delay")
|
||||
.comment("Defines (for each individual cow) the minimum time between milking." )
|
||||
.defineInRange("milking_machine_milking_delay", BlockDecorMilker.BTileEntity.DEFAULT_MILKING_DELAY_PER_COW, 1000, 24000);
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
@ -609,7 +614,7 @@ public class ModConfig
|
|||
BlockDecorSolarPanel.BTileEntity.on_config(COMMON.small_solar_panel_peak_production.get());
|
||||
BlockDecorBreaker.BTileEntity.on_config(COMMON.block_breaker_power_consumption.get(), COMMON.block_breaker_reluctance.get(), COMMON.block_breaker_min_breaking_time.get(), COMMON.block_breaker_requires_power.get());
|
||||
BlockDecorTreeCutter.BTileEntity.on_config(COMMON.tree_cuttter_energy_consumption.get(), COMMON.tree_cuttter_cutting_time_needed.get(), COMMON.tree_cuttter_requires_power.get());
|
||||
BlockDecorMilker.BTileEntity.on_config(COMMON.milking_machine_energy_consumption.get());
|
||||
BlockDecorMilker.BTileEntity.on_config(COMMON.milking_machine_energy_consumption.get(), COMMON.milking_machine_milking_delay.get());
|
||||
without_crafting_table = isOptedOut(ModContent.TREATED_WOOD_CRAFTING_TABLE);
|
||||
immersiveengineering_installed = ModAuxiliaries.isModLoaded("immersiveengineering");
|
||||
with_experimental_features_ = COMMON.with_experimental.get();
|
||||
|
|
|
@ -101,8 +101,8 @@
|
|||
"block.engineersdecor.clinker_brick_stairs.help": "§6По цвету выглядят немного темнее и интенсивнее, чем Кирпичный блок",
|
||||
"block.engineersdecor.clinker_brick_stained_stairs": "Грязные кирпичные ступеньки",
|
||||
"block.engineersdecor.clinker_brick_stained_stairs.help": "§6Выглядят немного темнее и интенсивнее, чем Кирпичный блок. Имеют более заметные следы грязи или пятен.",
|
||||
"block.engineersdecor.slag_brick_stairs": "Клинкерные кирпичные ступеньки",
|
||||
"block.engineersdecor.slag_brick_stairs.help": "§6По цвету выглядят немного темнее и интенсивнее, чем Кирпичный блок.",
|
||||
"block.engineersdecor.slag_brick_stairs": "Кирпичные ступеньки из шлакоблока",
|
||||
"block.engineersdecor.slag_brick_stairs.help": "§6Серо-коричневые кирпичные ступеньки.",
|
||||
"block.engineersdecor.rebar_concrete_stairs": "Железобетонные ступеньки",
|
||||
"block.engineersdecor.rebar_concrete_stairs.help": "§6Железобетонные ступеньки.§r Дорогие, но взрывоустойчивые, как обсидиан.",
|
||||
"block.engineersdecor.rebar_concrete_tile_stairs": "Ступеньки из железобетонной плитки",
|
||||
|
@ -134,7 +134,7 @@
|
|||
"block.engineersdecor.treated_wood_stool": "Табурет из обработанного дерева",
|
||||
"block.engineersdecor.treated_wood_stool.help": "§6Крепкий деревянный табурет.§r Для использования в помещении и на улице.",
|
||||
"block.engineersdecor.treated_wood_crafting_table": "Верстак из обработанного дерева",
|
||||
"block.engineersdecor.treated_wood_crafting_table.help": "§6Прочный и устойчивый к погодным условиям. Восемь слотов для хранения. Хранит инвентарь. Нажимайте кнопки со стрелками вверх/вниз для выбора из истории, выходной слот для размещения предметов, X-кнопка очистить сетку крафта и историю. Shift-клик по стеку: передача стека от игрока в хранилище при создании если сетка пуста, в противном случае перенос от игрока в сетку. Автоматически распределяет кликаемый стек.",
|
||||
"block.engineersdecor.treated_wood_crafting_table.help": "§6Прочный и устойчивый к погодным условиям. Восемь слотов для хранения. Хранит инвентарь. Нажимайте кнопки со стрелками вверх/вниз для выбора из истории, выходной слот для размещения предметов, X-кнопка очистить сетку крафта и историю. Shift-клик по стеку: передача стека от игрока в хранилище при создании если сетка пуста, в противном случае перенос от игрока в сетку. Автоматически распределяет кликаемый стек. Shift-Ctrl-клик по стаку: перемещает одинаковые стаки. Колёсико мыши: добавляет/отнимает предметы в сетке.",
|
||||
"block.engineersdecor.treated_wood_side_table": "Столик из обработанного дерева",
|
||||
"block.engineersdecor.treated_wood_side_table.help": "§6Нужен после того, как работа выполнена.",
|
||||
"block.engineersdecor.iron_inset_light": "Встраиваемый осветитель",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
org.gradle.daemon=false
|
||||
org.gradle.jvmargs=-Xmx8G
|
||||
version_minecraft=1.15.1
|
||||
version_forge_minecraft=1.15.1-30.0.36
|
||||
version_forge_minecraft=1.15.1-30.0.51
|
||||
version_fml_mappings=20191105-1.14.3
|
||||
version_jei=1.15.1-6.0.0.1
|
||||
version_engineersdecor=1.0.18-b4
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
|
||||
"1.15.1": {
|
||||
"1.0.18-b4": "[A] Ported Treated Wood Crafting Table item rendering.\n[F] Fixed Milking machine cow path issue, added milking delay cow tracking.\n[F] Slab / Slab Slice placement adapted to vanilla standard.\n[M] Lang update ru_ru (PR#77, thanks Smollet777).",
|
||||
"1.0.18-b3": "[A] Added Treated Wood Crafting Table tweaks (ctrl-shift moves all same stacks from the inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).\n[F] EN Lang file fixed (issue #76, thx Riverstar907).\n[F] Fixed Tree Cutter not respecting power-required config (thx federsavo, issue #77).\n[F] Fixed Small Solar Panel not exposing energy capability (thx MatthiasMann, issue #78).",
|
||||
"1.0.18-b2": "[M] Lang ru_ru updated (Smollet777).",
|
||||
"1.0.18-b1": "[U] Updated to Forge 1.15.1-30.0.16/20190719-1.14.3.\n[F] Client setup Dist annotation fixed (issue #73, thx hitsu420).\n[F] Double newline escapes in lang files fixed (\"\\n\" in a tooltip).\n[M] Updated zh_cn lang file (scikirbypoke).\n[A] Added opt-out config for the Small Tree Cutter",
|
||||
|
@ -8,6 +9,6 @@
|
|||
},
|
||||
"promos": {
|
||||
"1.15.1-recommended": "",
|
||||
"1.15.1-latest": "1.0.18-b3"
|
||||
"1.15.1-latest": "1.0.18-b4"
|
||||
}
|
||||
}
|
|
@ -11,7 +11,10 @@ Mod sources for Minecraft version 1.15.1.
|
|||
|
||||
## Version history
|
||||
|
||||
~ v1.0.18-b4 [A] Ported Treated Wood Crafting Table item rendering.
|
||||
- v1.0.18-b4 [A] Ported Treated Wood Crafting Table item rendering.
|
||||
[F] Fixed Milking machine cow path issue, added milking delay cow tracking.
|
||||
[F] Slab / Slab Slice placement adapted to vanilla standard.
|
||||
[M] Lang update ru_ru (PR#77, thanks Smollet777).
|
||||
|
||||
- v1.0.18-b3 [A] Added Treated Wood Crafting Table tweaks (ctrl-shift moves all same stacks from the
|
||||
inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).
|
||||
|
|
|
@ -124,7 +124,7 @@ public class ModEngineersDecor
|
|||
{ config_loaded = true; }
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onConfigFileChange(net.minecraftforge.fml.config.ModConfig.ConfigReloading configEvent)
|
||||
public static void onConfigReload(net.minecraftforge.fml.config.ModConfig.Reloading configEvent)
|
||||
{
|
||||
try {
|
||||
ModEngineersDecor.logger().info("Config file changed {}", configEvent.getConfig().getFileName());
|
||||
|
|
|
@ -11,7 +11,7 @@ package wile.engineersdecor.blocks;
|
|||
|
||||
import wile.engineersdecor.detail.ModAuxiliaries;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.state.IntegerProperty;
|
||||
|
@ -20,9 +20,12 @@ import net.minecraft.util.math.BlockRayTraceResult;
|
|||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.state.StateContainer;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
import net.minecraft.item.BlockItemUseContext;
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -40,7 +43,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
public class BlockDecorHalfSlab extends BlockDecor implements IWaterLoggable
|
||||
public class BlockDecorHalfSlab extends BlockDecor.WaterLoggable
|
||||
{
|
||||
public static final IntegerProperty PARTS = IntegerProperty.create("parts", 0, 14);
|
||||
|
||||
|
@ -102,7 +105,7 @@ public class BlockDecorHalfSlab extends BlockDecor implements IWaterLoggable
|
|||
|
||||
@Override
|
||||
protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder)
|
||||
{ super.fillStateContainer(builder); builder.add(PARTS, WATERLOGGED); }
|
||||
{ super.fillStateContainer(builder); builder.add(PARTS); }
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
|
@ -192,4 +195,13 @@ public class BlockDecorHalfSlab extends BlockDecor implements IWaterLoggable
|
|||
SoundType st = this.getSoundType(state, world, pos, null);
|
||||
world.playSound(player, pos, st.getPlaceSound(), SoundCategory.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean receiveFluid(IWorld world, BlockPos pos, BlockState state, IFluidState fluidState)
|
||||
{ return (state.get(PARTS)==14) ? false : super.receiveFluid(world, pos, state, fluidState); }
|
||||
|
||||
@Override
|
||||
public boolean canContainFluid(IBlockReader world, BlockPos pos, BlockState state, Fluid fluid)
|
||||
{ return (state.get(PARTS)==14) ? false : super.canContainFluid(world, pos, state, fluid); }
|
||||
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import javax.annotation.Nonnull;
|
|||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
||||
|
@ -143,12 +144,14 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
public static final int MAX_ENERGY_BUFFER = 16000;
|
||||
public static final int MAX_ENERGY_TRANSFER = 512;
|
||||
public static final int DEFAULT_ENERGY_CONSUMPTION = 0;
|
||||
public static final int DEFAULT_MILKING_DELAY_PER_COW = 4000;
|
||||
private static final Direction FLUID_TRANSFER_DIRECTRIONS[] = {Direction.DOWN,Direction.EAST,Direction.SOUTH,Direction.WEST,Direction.NORTH};
|
||||
private enum MilkingState { IDLE, PICKED, COMING, POSITIONING, MILKING, LEAVING, WAITING }
|
||||
|
||||
private static FluidStack milk_fluid_ = new FluidStack(Fluids.WATER, 0);
|
||||
private static HashMap<ItemStack, ItemStack> milk_containers_ = new HashMap<>();
|
||||
private static int energy_consumption = DEFAULT_ENERGY_CONSUMPTION;
|
||||
private static long min_milking_delay_per_cow_ticks = DEFAULT_MILKING_DELAY_PER_COW;
|
||||
private int tick_timer_;
|
||||
private int energy_stored_;
|
||||
private int tank_level_ = 0;
|
||||
|
@ -158,9 +161,10 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
private int state_timer_ = 0;
|
||||
private BlockPos tracked_cow_original_position_ = null;
|
||||
|
||||
public static void on_config(int energy_consumption_per_tick)
|
||||
public static void on_config(int energy_consumption_per_tick, int min_milking_delay_per_cow)
|
||||
{
|
||||
energy_consumption = MathHelper.clamp(energy_consumption_per_tick, 0, 128);
|
||||
min_milking_delay_per_cow_ticks = MathHelper.clamp(min_milking_delay_per_cow, 1000, 24000);
|
||||
{
|
||||
Fluid milk = null; // FluidRe.getFluid("milk");
|
||||
if(milk != null) milk_fluid_ = new FluidStack(milk, BUCKET_SIZE);
|
||||
|
@ -299,8 +303,10 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
|
||||
// ITickable ------------------------------------------------------------------------------------
|
||||
|
||||
private static final HashMap<Integer, Long> tracked_cows_ = new HashMap<Integer, Long>();
|
||||
|
||||
private void log(String s)
|
||||
{} // println("Milker|" + s); may be enabled with config, for dev was println
|
||||
{ System.out.println("Milker|" + s); } // println("Milker|" + s); may be enabled with config, for dev was println
|
||||
|
||||
private static ItemStack milk_filled_container_item(ItemStack stack)
|
||||
{ return milk_containers_.entrySet().stream().filter(e->e.getKey().isItemEqual(stack)).map(Map.Entry::getValue).findFirst().orElse(ItemStack.EMPTY); }
|
||||
|
@ -331,6 +337,10 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
if(cow != null) {
|
||||
cow.setNoAI(false);
|
||||
SingleMoveGoal.abortFor(cow);
|
||||
tracked_cows_.remove(cow.getEntityId());
|
||||
for(int id:tracked_cows_.keySet().stream().filter(i->cow.getEntityWorld().getEntityByID(i)==null).collect(Collectors.toList())) {
|
||||
tracked_cows_.remove(id);
|
||||
}
|
||||
}
|
||||
tracked_cow_ = null;
|
||||
state_ = MilkingState.IDLE;
|
||||
|
@ -345,8 +355,15 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
CowEntity cow = null;
|
||||
{
|
||||
AxisAlignedBB aabb = new AxisAlignedBB(pos.offset(facing, 3)).grow(4, 2, 4);
|
||||
final long t = world.getGameTime();
|
||||
final List<CowEntity> cows = world.getEntitiesWithinAABB(CowEntity.class, aabb,
|
||||
e->( ((tracked_cow_==null) && ((!e.isChild()) && (!e.isInLove()) && (!e.isBeingRidden()))) || (e.getUniqueID().equals(tracked_cow_)) )
|
||||
e-> {
|
||||
if(e.getUniqueID().equals(tracked_cow_)) return true;
|
||||
if((tracked_cow_!=null) || e.isChild() || e.isInLove() || e.isBeingRidden()) return false;
|
||||
if(!e.getNavigator().noPath()) return false;
|
||||
if(Math.abs(tracked_cows_.getOrDefault(e.getEntityId(), 0L)-t) < min_milking_delay_per_cow_ticks) return false;
|
||||
return true;
|
||||
}
|
||||
);
|
||||
if(cows.size() == 1) {
|
||||
cow = cows.get(0); // tracked or only one
|
||||
|
@ -372,11 +389,12 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
BlockPos p = getPos().offset(facing,2);
|
||||
log("Idle: Shove off");
|
||||
blocker.setNoAI(false);
|
||||
SingleMoveGoal.startFor(blocker, p, 2, 1.0, (goal, world, pos)->(pos.distanceSq(goal.getCreature().getPosition())>49));
|
||||
SingleMoveGoal.startFor(blocker, p, 2, 1.0, (goal, world, pos)->(pos.distanceSq(goal.getCreature().getPosition())>100));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(cow.getLeashed() || cow.isChild() || cow.isInLove() || (!cow.onGround) || cow.isBeingRidden() || cow.isSprinting()) return false;
|
||||
tracked_cows_.put(cow.getEntityId(), cow.getEntityWorld().getGameTime());
|
||||
tracked_cow_ = cow.getUniqueID();
|
||||
state_ = MilkingState.PICKED;
|
||||
state_timeout_ = 200;
|
||||
|
@ -387,13 +405,7 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
case PICKED: {
|
||||
SingleMoveGoal.startFor(
|
||||
cow, target_pos, 2, 1.0,
|
||||
(goal, world, pos)->{
|
||||
if(pos.distanceSq(goal.getCreature().getPosition())>100) return true;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if(world.getBlockState(pos.offset(Direction.byHorizontalIndex(i))).getBlock() instanceof BlockDecorMilker) return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
(goal, world, pos)->(pos.distanceSq(goal.getCreature().getPosition())>100),
|
||||
(goal, world, pos)->{
|
||||
log("move: position reached");
|
||||
goal.getCreature().setLocationAndAngles(goal.getTargetPosition().getX(), goal.getTargetPosition().getY(), goal.getTargetPosition().getZ(), facing.getHorizontalAngle(), 0);
|
||||
|
@ -422,6 +434,7 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
}
|
||||
case POSITIONING: {
|
||||
log("Positioning: start milking");
|
||||
SingleMoveGoal.abortFor(cow);
|
||||
cow.setNoAI(true);
|
||||
cow.setLocationAndAngles(target_pos.getX(), target_pos.getY(), target_pos.getZ(), facing.getHorizontalAngle(), 0);
|
||||
world.playSound(null, pos, SoundEvents.ENTITY_COW_MILK, SoundCategory.BLOCKS, 0.5f, 1f);
|
||||
|
@ -447,13 +460,18 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
state_timer_ = 500;
|
||||
tick_timer_ = TICK_INTERVAL;
|
||||
state_ = MilkingState.WAITING;
|
||||
tracked_cows_.put(cow.getEntityId(), cow.getEntityWorld().getGameTime());
|
||||
log("Leaving: process done");
|
||||
return true;
|
||||
}
|
||||
case WAITING: {
|
||||
// wait for the timeout to kick in until starting with the next.
|
||||
tick_timer_ = TICK_INTERVAL;
|
||||
log("Waiting: ...");
|
||||
if(state_timer_ < 40) {
|
||||
tracked_cow_ = null;
|
||||
release_cow(null);
|
||||
}
|
||||
log("Waiting time elapsed");
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
|
@ -510,8 +528,9 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
{
|
||||
@FunctionalInterface public interface TargetPositionInValidCheck { boolean test(SingleMoveGoal goal, IWorldReader world, BlockPos pos); }
|
||||
@FunctionalInterface public interface StrollEvent { void apply(SingleMoveGoal goal, IWorldReader world, Vec3d pos); }
|
||||
private static void log(String s) {} // println(s);
|
||||
private static void log(String s) {} // println("SingleMoveGoal: "+s);
|
||||
|
||||
private static final HashMap<Integer, SingleMoveGoal> tracked_entities_ = new HashMap<Integer, SingleMoveGoal>();
|
||||
private static final int motion_timeout = 20*20;
|
||||
private boolean aborted_;
|
||||
private boolean in_position_;
|
||||
|
@ -538,14 +557,40 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
public static void startFor(CreatureEntity entity, BlockPos target_pos, int priority, double speed, TargetPositionInValidCheck abort_condition)
|
||||
{ startFor(entity, new Vec3d(target_pos.getX(),target_pos.getY(),target_pos.getZ()), priority, speed, abort_condition, null, null); }
|
||||
|
||||
public static void startFor(CreatureEntity entity, Vec3d target_pos, int priority, double speed, TargetPositionInValidCheck abort_condition, @Nullable StrollEvent on_position_reached, @Nullable StrollEvent on_aborted)
|
||||
{ entity.goalSelector.addGoal(priority, new SingleMoveGoal(entity, target_pos, speed, abort_condition, on_position_reached, on_aborted)); }
|
||||
public static boolean startFor(CreatureEntity entity, Vec3d target_pos, int priority, double speed, TargetPositionInValidCheck abort_condition, @Nullable StrollEvent on_position_reached, @Nullable StrollEvent on_aborted)
|
||||
{
|
||||
synchronized(tracked_entities_) {
|
||||
SingleMoveGoal goal = tracked_entities_.getOrDefault(entity.getEntityId(), null);
|
||||
if(goal != null) {
|
||||
if(!goal.aborted()) return false; // that is still running.
|
||||
entity.goalSelector.removeGoal(goal);
|
||||
}
|
||||
log("::start("+entity.getEntityId()+")");
|
||||
goal = new SingleMoveGoal(entity, target_pos, speed, abort_condition, on_position_reached, on_aborted);
|
||||
tracked_entities_.put(entity.getEntityId(), goal);
|
||||
entity.goalSelector.addGoal(priority, goal);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isActiveFor(CreatureEntity entity)
|
||||
{ return (entity != null) && (entity.goalSelector.getRunningGoals().anyMatch(g->(g.getGoal()) instanceof SingleMoveGoal)); }
|
||||
{ return (entity != null) && (entity.goalSelector.getRunningGoals().anyMatch(
|
||||
g->((g.getGoal()) instanceof SingleMoveGoal) && (!((SingleMoveGoal)(g.getGoal())).aborted())
|
||||
)); }
|
||||
|
||||
public static void abortFor(CreatureEntity entity)
|
||||
{ entity.goalSelector.getRunningGoals().filter(g->(g.getGoal()) instanceof SingleMoveGoal).forEach(g->((SingleMoveGoal)g.getGoal()).abort()); }
|
||||
{
|
||||
log("::abort("+entity.getEntityId()+")");
|
||||
if(entity.isAlive()) {
|
||||
entity.goalSelector.getRunningGoals().filter(g->(g.getGoal()) instanceof SingleMoveGoal).forEach(g->((SingleMoveGoal)g.getGoal()).abort());
|
||||
}
|
||||
final World world = entity.getEntityWorld();
|
||||
if(world != null) {
|
||||
// @todo: check nicer way to filter a map.
|
||||
List<Integer> to_remove = tracked_entities_.keySet().stream().filter(i->(world.getEntityByID(i) == null)).collect(Collectors.toList());
|
||||
for(int id:to_remove)tracked_entities_.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
public Vec3d getTargetPosition()
|
||||
{ return target_pos_; }
|
||||
|
@ -553,34 +598,48 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
public CreatureEntity getCreature()
|
||||
{ return creature; }
|
||||
|
||||
public void abort()
|
||||
public synchronized void abort()
|
||||
{ aborted_ = true; }
|
||||
|
||||
public synchronized boolean aborted()
|
||||
{ return aborted_; }
|
||||
|
||||
public synchronized void initialize(Vec3d target_pos, double speed, TargetPositionInValidCheck abort_condition, @Nullable StrollEvent on_position_reached, @Nullable StrollEvent on_aborted)
|
||||
{
|
||||
abort_condition_ = abort_condition;
|
||||
on_target_position_reached_ = on_position_reached;
|
||||
on_aborted_ = on_aborted;
|
||||
destinationBlock = new BlockPos(target_pos.getX(), target_pos.getY(), target_pos.getZ());
|
||||
timeoutCounter = 0;
|
||||
runDelay = 0;
|
||||
aborted_ = false;
|
||||
was_aborted_ = false;
|
||||
target_pos_ = new Vec3d(target_pos.getX(), target_pos.getY(), target_pos.getZ());
|
||||
// this.movementSpeed = speed; -> that is final, need to override tick and func_whatever
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTask()
|
||||
{ runDelay = 0; timeoutCounter = 0; }
|
||||
|
||||
@Override
|
||||
public double getTargetDistanceSq()
|
||||
{ return 1.2; }
|
||||
{ return 0.7; }
|
||||
|
||||
@Override
|
||||
public boolean shouldMove()
|
||||
{ return (timeoutCounter & 0x7) == 0; }
|
||||
{ return (!aborted()) && (timeoutCounter & 0x7) == 0; }
|
||||
|
||||
@Override
|
||||
public boolean shouldExecute()
|
||||
{
|
||||
if(!shouldMoveTo(creature.world, destinationBlock)) {
|
||||
aborted_ = true;
|
||||
return false;
|
||||
} else if(aborted_) {
|
||||
// shouldExecute is the point where in GoalSelector.tick() the goal is not in flagGoals and can be removed.
|
||||
creature.goalSelector.getRunningGoals().filter(g->(g.getGoal()) instanceof SingleMoveGoal).forEach(g->creature.goalSelector.removeGoal(g));
|
||||
creature.goalSelector.removeGoal(this);
|
||||
if(aborted_) {
|
||||
if((!was_aborted_) && (on_aborted_!=null)) on_aborted_.apply(this, creature.world, target_pos_);
|
||||
was_aborted_ = true;
|
||||
return false;
|
||||
} else if(!shouldMoveTo(creature.world, destinationBlock)) {
|
||||
synchronized(this) { aborted_ = true; }
|
||||
return false;
|
||||
} else if(--runDelay > 0) {
|
||||
return false;
|
||||
} else {
|
||||
|
@ -592,32 +651,69 @@ public class BlockDecorMilker extends BlockDecorDirectedHorizontal
|
|||
@Override
|
||||
public void startExecuting()
|
||||
{
|
||||
log("startExecuting()");
|
||||
timeoutCounter = 0;
|
||||
if(!creature.getNavigator().tryMoveToXYZ(target_pos_.getX(), target_pos_.getY(), target_pos_.getZ(), this.movementSpeed)) abort();
|
||||
if(!creature.getNavigator().tryMoveToXYZ(target_pos_.getX(), target_pos_.getY(), target_pos_.getZ(), this.movementSpeed)) {
|
||||
abort();
|
||||
log("startExecuting() -> abort, no path");
|
||||
} else {
|
||||
log("startExecuting() -> started");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldContinueExecuting()
|
||||
{
|
||||
if((aborted_) || (creature.getNavigator().noPath()) || (timeoutCounter > motion_timeout) || (!shouldMoveTo(creature.world, destinationBlock))) {
|
||||
if(aborted()) {
|
||||
log("shouldContinueExecuting() -> already aborted");
|
||||
return false;
|
||||
} else if(creature.getNavigator().noPath()) {
|
||||
if((!creature.getNavigator().setPath(creature.getNavigator().func_225466_a(target_pos_.getX(), target_pos_.getY(), target_pos_.getZ(), 0), movementSpeed))) {
|
||||
log("shouldContinueExecuting() -> abort, no path");
|
||||
abort();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else if(timeoutCounter > motion_timeout) {
|
||||
log("shouldContinueExecuting() -> abort, timeout");
|
||||
abort();
|
||||
return false;
|
||||
} else if(!shouldMoveTo(creature.world, destinationBlock)) {
|
||||
log("shouldContinueExecuting() -> abort, !shouldMoveTo()");
|
||||
abort();
|
||||
return false;
|
||||
} else {
|
||||
log("shouldContinueExecuting() -> yes");
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldMoveTo(IWorldReader world, BlockPos pos)
|
||||
{ if(!abort_condition_.test(this, world, pos)) { return true; } abort(); return false; }
|
||||
{
|
||||
if(abort_condition_.test(this, world, pos)) {
|
||||
log("shouldMoveTo() -> abort_condition");
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
BlockPos testpos = new BlockPos(target_pos_.getX(), creature.getPositionVec().getY(), target_pos_.getZ());
|
||||
if(!testpos.withinDistance(creature.getPositionVec(), getTargetDistanceSq())) {
|
||||
if((++timeoutCounter > motion_timeout)) { abort(); return; }
|
||||
if(shouldMove() && (!creature.getNavigator().tryMoveToXYZ(target_pos_.getX(), target_pos_.getY(), target_pos_.getZ(), movementSpeed))) abort();
|
||||
if((++timeoutCounter > motion_timeout)) {
|
||||
log("tick() -> abort, timeoutCounter");
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
if(shouldMove() && (!creature.getNavigator().tryMoveToXYZ(target_pos_.getX(), target_pos_.getY(), target_pos_.getZ(), movementSpeed))) {
|
||||
log("tick() -> abort, !tryMoveToXYZ()");
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
log("tick() -> abort, in position)");
|
||||
in_position_ = true;
|
||||
abort();
|
||||
if(on_target_position_reached_ != null) on_target_position_reached_.apply(this, creature.world, target_pos_);
|
||||
|
|
|
@ -36,7 +36,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
public class BlockDecorSlab extends BlockDecor implements IWaterLoggable
|
||||
public class BlockDecorSlab extends BlockDecor.WaterLoggable
|
||||
{
|
||||
public static final IntegerProperty PARTS = IntegerProperty.create("parts", 0, 2);
|
||||
public static final IntegerProperty TEXTURE_VARIANT = IntegerProperty.create("tvariant", 0, 3);
|
||||
|
@ -92,16 +92,37 @@ public class BlockDecorSlab extends BlockDecor implements IWaterLoggable
|
|||
|
||||
@Override
|
||||
protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder)
|
||||
{ super.fillStateContainer(builder); builder.add(PARTS, TEXTURE_VARIANT, WATERLOGGED); }
|
||||
{ super.fillStateContainer(builder); builder.add(PARTS, TEXTURE_VARIANT); }
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public BlockState getStateForPlacement(BlockItemUseContext context)
|
||||
{
|
||||
final Direction facing = context.getFace();
|
||||
double y = context.getHitVec().getY();
|
||||
int rnd = MathHelper.clamp((int)(MathHelper.getPositionRandom(context.getPos()) % 4), 0, 3);
|
||||
return super.getStateForPlacement(context).with(PARTS, ((facing==Direction.UP) || ((facing!=Direction.DOWN) && (y < 0.6))) ? 0 : 1).with(TEXTURE_VARIANT, rnd);
|
||||
BlockPos pos = context.getPos();
|
||||
if(context.getWorld().getBlockState(pos).getBlock() == this) return context.getWorld().getBlockState(pos).with(PARTS, 2).with(WATERLOGGED, false);
|
||||
final int rnd = MathHelper.clamp((int)(MathHelper.getPositionRandom(context.getPos()) & 0x3), 0, 3);
|
||||
final Direction face = context.getFace();
|
||||
final BlockState placement_state = super.getStateForPlacement(context).with(TEXTURE_VARIANT, rnd); // fluid state
|
||||
if(face == Direction.UP) return placement_state.with(PARTS, 0);
|
||||
if(face == Direction.DOWN) return placement_state.with(PARTS, 1);
|
||||
if(!face.getAxis().isHorizontal()) return placement_state;
|
||||
final boolean isupper = ((context.getHitVec().getY() - context.getPos().getY()) > 0.5);
|
||||
return placement_state.with(PARTS, isupper ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean isReplaceable(BlockState state, BlockItemUseContext context)
|
||||
{
|
||||
if(context.getItem().getItem() != this.asItem()) return false;
|
||||
if(!context.replacingClickedOnBlock()) return true;
|
||||
final Direction face = context.getFace();
|
||||
final int parts = state.get(PARTS);
|
||||
if((face == Direction.UP) && (parts==0)) return true;
|
||||
if((face == Direction.DOWN) && (parts==1)) return true;
|
||||
if(!face.getAxis().isHorizontal()) return false;
|
||||
final boolean isupper = ((context.getHitVec().getY() - context.getPos().getY()) > 0.5);
|
||||
return isupper ? (parts==0) : (parts==1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -122,29 +143,6 @@ public class BlockDecorSlab extends BlockDecor implements IWaterLoggable
|
|||
public List<ItemStack> dropList(BlockState state, World world, BlockPos pos, boolean explosion)
|
||||
{ return new ArrayList<ItemStack>(Collections.singletonList(new ItemStack(this.asItem(), num_slabs_contained_in_parts_[state.get(PARTS) & 0x3]))); }
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult rayTraceResult)
|
||||
{
|
||||
Direction face = rayTraceResult.getFace();
|
||||
final ItemStack stack = player.getHeldItem(hand);
|
||||
if(stack.isEmpty() || (Block.getBlockFromItem(stack.getItem()) != this)) return false;
|
||||
int parts = state.get(PARTS);
|
||||
if(((face == Direction.UP) && (parts == 0)) || ((face == Direction.DOWN) && (parts == 1))) {
|
||||
world.setBlockState(pos, state.with(PARTS, 2), 3);
|
||||
} else {
|
||||
return false; // "not handled" -> let parent decide if a new slab has to be placed on top/bottom.
|
||||
}
|
||||
if(world.isRemote) return true;
|
||||
if(!player.isCreative()) {
|
||||
stack.shrink(1);
|
||||
if(player.inventory != null) player.inventory.markDirty();
|
||||
}
|
||||
SoundType st = this.getSoundType(state, world, pos, null);
|
||||
world.playSound(null, pos, st.getPlaceSound(), SoundCategory.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void onBlockClicked(BlockState state, World world, BlockPos pos, PlayerEntity player)
|
||||
|
|
|
@ -154,6 +154,7 @@ public class ModConfig
|
|||
public final ForgeConfigSpec.IntValue tree_cuttter_cutting_time_needed;
|
||||
public final ForgeConfigSpec.BooleanValue tree_cuttter_requires_power;
|
||||
public final ForgeConfigSpec.IntValue milking_machine_energy_consumption;
|
||||
public final ForgeConfigSpec.IntValue milking_machine_milking_delay;
|
||||
|
||||
CommonConfig(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
|
@ -476,6 +477,10 @@ public class ModConfig
|
|||
"Use zero to disable energy dependency and energy handling of the machine. " +
|
||||
"The config value can be changed on-the-fly for tuning.")
|
||||
.defineInRange("milking_machine_energy_consumption", BlockDecorMilker.BTileEntity.DEFAULT_ENERGY_CONSUMPTION, 0, 128);
|
||||
milking_machine_milking_delay = builder
|
||||
.translation(ModEngineersDecor.MODID + ".config.milking_machine_milking_delay")
|
||||
.comment("Defines (for each individual cow) the minimum time between milking." )
|
||||
.defineInRange("milking_machine_milking_delay", BlockDecorMilker.BTileEntity.DEFAULT_MILKING_DELAY_PER_COW, 1000, 24000);
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
@ -609,7 +614,7 @@ public class ModConfig
|
|||
BlockDecorSolarPanel.BTileEntity.on_config(COMMON.small_solar_panel_peak_production.get());
|
||||
BlockDecorBreaker.BTileEntity.on_config(COMMON.block_breaker_power_consumption.get(), COMMON.block_breaker_reluctance.get(), COMMON.block_breaker_min_breaking_time.get(), COMMON.block_breaker_requires_power.get());
|
||||
BlockDecorTreeCutter.BTileEntity.on_config(COMMON.tree_cuttter_energy_consumption.get(), COMMON.tree_cuttter_cutting_time_needed.get(), COMMON.tree_cuttter_requires_power.get());
|
||||
BlockDecorMilker.BTileEntity.on_config(COMMON.milking_machine_energy_consumption.get());
|
||||
BlockDecorMilker.BTileEntity.on_config(COMMON.milking_machine_energy_consumption.get(), COMMON.milking_machine_milking_delay.get());
|
||||
without_crafting_table = isOptedOut(ModContent.TREATED_WOOD_CRAFTING_TABLE);
|
||||
immersiveengineering_installed = ModAuxiliaries.isModLoaded("immersiveengineering");
|
||||
with_experimental_features_ = COMMON.with_experimental.get();
|
||||
|
|
|
@ -101,8 +101,8 @@
|
|||
"block.engineersdecor.clinker_brick_stairs.help": "§6По цвету выглядят немного темнее и интенсивнее, чем Кирпичный блок",
|
||||
"block.engineersdecor.clinker_brick_stained_stairs": "Грязные кирпичные ступеньки",
|
||||
"block.engineersdecor.clinker_brick_stained_stairs.help": "§6Выглядят немного темнее и интенсивнее, чем Кирпичный блок. Имеют более заметные следы грязи или пятен.",
|
||||
"block.engineersdecor.slag_brick_stairs": "Клинкерные кирпичные ступеньки",
|
||||
"block.engineersdecor.slag_brick_stairs.help": "§6По цвету выглядят немного темнее и интенсивнее, чем Кирпичный блок.",
|
||||
"block.engineersdecor.slag_brick_stairs": "Кирпичные ступеньки из шлакоблока",
|
||||
"block.engineersdecor.slag_brick_stairs.help": "§6Серо-коричневые кирпичные ступеньки.",
|
||||
"block.engineersdecor.rebar_concrete_stairs": "Железобетонные ступеньки",
|
||||
"block.engineersdecor.rebar_concrete_stairs.help": "§6Железобетонные ступеньки.§r Дорогие, но взрывоустойчивые, как обсидиан.",
|
||||
"block.engineersdecor.rebar_concrete_tile_stairs": "Ступеньки из железобетонной плитки",
|
||||
|
@ -134,7 +134,7 @@
|
|||
"block.engineersdecor.treated_wood_stool": "Табурет из обработанного дерева",
|
||||
"block.engineersdecor.treated_wood_stool.help": "§6Крепкий деревянный табурет.§r Для использования в помещении и на улице.",
|
||||
"block.engineersdecor.treated_wood_crafting_table": "Верстак из обработанного дерева",
|
||||
"block.engineersdecor.treated_wood_crafting_table.help": "§6Прочный и устойчивый к погодным условиям. Восемь слотов для хранения. Хранит инвентарь. Нажимайте кнопки со стрелками вверх/вниз для выбора из истории, выходной слот для размещения предметов, X-кнопка очистить сетку крафта и историю. Shift-клик по стеку: передача стека от игрока в хранилище при создании если сетка пуста, в противном случае перенос от игрока в сетку. Автоматически распределяет кликаемый стек.",
|
||||
"block.engineersdecor.treated_wood_crafting_table.help": "§6Прочный и устойчивый к погодным условиям. Восемь слотов для хранения. Хранит инвентарь. Нажимайте кнопки со стрелками вверх/вниз для выбора из истории, выходной слот для размещения предметов, X-кнопка очистить сетку крафта и историю. Shift-клик по стеку: передача стека от игрока в хранилище при создании если сетка пуста, в противном случае перенос от игрока в сетку. Автоматически распределяет кликаемый стек. Shift-Ctrl-клик по стаку: перемещает одинаковые стаки. Колёсико мыши: добавляет/отнимает предметы в сетке.",
|
||||
"block.engineersdecor.treated_wood_side_table": "Столик из обработанного дерева",
|
||||
"block.engineersdecor.treated_wood_side_table.help": "§6Нужен после того, как работа выполнена.",
|
||||
"block.engineersdecor.iron_inset_light": "Встраиваемый осветитель",
|
||||
|
@ -217,4 +217,4 @@
|
|||
"block.engineersdecor.halfslab_sheetmetal_aluminum.help": "§6Вертикально наращиваемая часть.§rПравый/левый щелчок со стеком частей на верхней или нижней поверхности для добавления/удаления частей.",
|
||||
"block.engineersdecor.testblock": "ED тестовый блок (НЕ ИСПОЛЬЗОВАТЬ)",
|
||||
"block.engineersdecor.testblock.help": "§6Несоздаваемый тестовый блок с изменениемизменяющейся экспериментальной функциональностью. НЕ ИСПОЛЬЗОВАТЬ, может даже крашнуть игру в худшем случае!!"
|
||||
}
|
||||
}
|
|
@ -1,14 +1,15 @@
|
|||
{
|
||||
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
|
||||
"promos": {
|
||||
"1.12.2-recommended": "1.0.17",
|
||||
"1.12.2-latest": "1.0.18-b2",
|
||||
"1.12.2-recommended": "1.0.18",
|
||||
"1.12.2-latest": "1.0.18",
|
||||
"1.14.4-recommended": "",
|
||||
"1.14.4-latest": "1.0.18-b3",
|
||||
"1.14.4-latest": "1.0.18-b4",
|
||||
"1.15.1-recommended": "",
|
||||
"1.15.1-latest": "1.0.18-b3"
|
||||
"1.15.1-latest": "1.0.18-b4"
|
||||
},
|
||||
"1.12.2": {
|
||||
"1.0.18": "[R] Release based on v1.0.18-b2. Release-to-release changes: * Tree cutter config fixes. * Treated Wood Crafting Table mouse tweaks. * Lang updates.\n[M] Lang update ru_ru (PR#77, thanks Smollet777).",
|
||||
"1.0.18-b2": "[A] Added Treated Wood Crafting table tweaks (ctrl-shift moves all same stacks from the inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).\n[F] EN Lang file fixed (issue #76, thx Riverstar907).\n[F] Fixed Tree Cutter not respecting power-required config (thx federsavo, issue #77).",
|
||||
"1.0.18-b1": "[M] Lang ru_ru updated (Smollet777).",
|
||||
"1.0.17": "[R] Release based on v1.0.17-b3. Release-to-release changes: * Milking machine added. * Reverse recipes for slab slices added. * Texture and model improvements. * Lang file updates. * Minor bug fixes. * Config options added.\n[M] Updated zh_cn lang file (scikirbypoke).\n[A] Added opt-out config for the Small Tree Cutter.",
|
||||
|
@ -83,6 +84,7 @@
|
|||
"1.0.0-b1": "[A] Initial structure.\n[A] Added clinker bricks and clinker brick stairs.\n[A] Added slag bricks and slag brick stairs.\n[A] Added metal rung ladder.\n[A] Added staggered metal steps ladder.\n[A] Added treated wood ladder.\n[A] Added treated wood pole.\n[A] Added treated wood table."
|
||||
},
|
||||
"1.14.4": {
|
||||
"1.0.18-b4": "[M] Lang update ru_ru (PR#77, thanks Smollet777).\n[F] Fixed Milking machine cow path issue, added milking delay cow tracking.\n[F] Slab / Slab Slice placement adapted to vanilla standard.",
|
||||
"1.0.18-b3": "[A] Added Treated Wood Crafting table tweaks (ctrl-shift moves all same stacks from the inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).\n[F] EN Lang file fixed (issue #76, thx Riverstar907).\n[F] Fixed Tree Cutter not respecting power-required config (thx federsavo, issue #77).\n[F] Fixed Small Solar Panel not exposing energy capability (thx MatthiasMann, issue #78).",
|
||||
"1.0.18-b2": "[F] Fixed JEI integration warning if nothing is opt'ed out (thx @SDUBZ for reporting).\n[M] Lang ru_ru updated (Smollet777).",
|
||||
"1.0.18-b1": "[U] Updated to Forge 1.14.4-28.1.109/20190719-1.14.3.\n[A] Added opt-out config for the Small Tree Cutter.",
|
||||
|
@ -124,6 +126,7 @@
|
|||
"1.0.7-b3": "[A] Initial 1.14.2 port of decorative blocks."
|
||||
},
|
||||
"1.15.1": {
|
||||
"1.0.18-b4": "[A] Ported Treated Wood Crafting Table item rendering.\n[F] Fixed Milking machine cow path issue, added milking delay cow tracking.\n[F] Slab / Slab Slice placement adapted to vanilla standard.\n[M] Lang update ru_ru (PR#77, thanks Smollet777).",
|
||||
"1.0.18-b3": "[A] Added Treated Wood Crafting Table tweaks (ctrl-shift moves all same stacks from the inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).\n[F] EN Lang file fixed (issue #76, thx Riverstar907).\n[F] Fixed Tree Cutter not respecting power-required config (thx federsavo, issue #77).\n[F] Fixed Small Solar Panel not exposing energy capability (thx MatthiasMann, issue #78).",
|
||||
"1.0.18-b2": "[M] Lang ru_ru updated (Smollet777).",
|
||||
"1.0.18-b1": "[U] Updated to Forge 1.15.1-30.0.16/20190719-1.14.3.\n[F] Client setup Dist annotation fixed (issue #73, thx hitsu420).\n[F] Double newline escapes in lang files fixed (\"\\n\" in a tooltip).\n[M] Updated zh_cn lang file (scikirbypoke).\n[A] Added opt-out config for the Small Tree Cutter",
|
||||
|
|
Loading…
Reference in a new issue