mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-17 03:05:30 -04:00
Started to modularize robots, making experience an upgrade and introducing a bunch of events.
This commit is contained in:
parent
9264d3c3d0
commit
f2798786c0
21
src/main/java/li/cil/oc/api/event/RobotAnalyzeEvent.java
Normal file
21
src/main/java/li/cil/oc/api/event/RobotAnalyzeEvent.java
Normal file
@ -0,0 +1,21 @@
|
||||
package li.cil.oc.api.event;
|
||||
|
||||
import li.cil.oc.api.machine.Robot;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
|
||||
/**
|
||||
* Fired when an analyzer is used on a robot.
|
||||
* <p/>
|
||||
* Use this to echo additional information for custom components.
|
||||
*/
|
||||
public class RobotAnalyzeEvent extends RobotEvent {
|
||||
/**
|
||||
* The player that used the analyzer.
|
||||
*/
|
||||
public final EntityPlayer player;
|
||||
|
||||
public RobotAnalyzeEvent(Robot robot, EntityPlayer player) {
|
||||
super(robot);
|
||||
this.player = player;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package li.cil.oc.api.event;
|
||||
|
||||
import li.cil.oc.api.machine.Robot;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraftforge.event.Cancelable;
|
||||
|
||||
public class RobotAttackEntityEvent extends RobotEvent {
|
||||
/**
|
||||
* The entity that the robot will attack.
|
||||
*/
|
||||
public final Entity target;
|
||||
|
||||
protected RobotAttackEntityEvent(Robot robot, Entity target) {
|
||||
super(robot);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a robot is about to attack an entity.
|
||||
* <p/>
|
||||
* Canceling this event will prevent the attack.
|
||||
*/
|
||||
@Cancelable
|
||||
public static class Pre extends RobotAttackEntityEvent {
|
||||
public Pre(Robot robot, Entity target) {
|
||||
super(robot, target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired after a robot has attacked an entity.
|
||||
*/
|
||||
public static class Post extends RobotAttackEntityEvent {
|
||||
public Post(Robot robot, Entity target) {
|
||||
super(robot, target);
|
||||
}
|
||||
}
|
||||
}
|
79
src/main/java/li/cil/oc/api/event/RobotBreakBlockEvent.java
Normal file
79
src/main/java/li/cil/oc/api/event/RobotBreakBlockEvent.java
Normal file
@ -0,0 +1,79 @@
|
||||
package li.cil.oc.api.event;
|
||||
|
||||
import li.cil.oc.api.machine.Robot;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.event.Cancelable;
|
||||
|
||||
public abstract class RobotBreakBlockEvent extends RobotEvent {
|
||||
protected RobotBreakBlockEvent(Robot robot) {
|
||||
super(robot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a robot is about to break a block.
|
||||
* <p/>
|
||||
* Canceling this event will prevent the block from getting broken.
|
||||
*/
|
||||
@Cancelable
|
||||
public static class Pre extends RobotBreakBlockEvent {
|
||||
/**
|
||||
* The world in which the block will be broken.
|
||||
*/
|
||||
public final World world;
|
||||
|
||||
/**
|
||||
* The coordinates at which the block will be broken.
|
||||
*/
|
||||
public final int x, y, z;
|
||||
|
||||
/**
|
||||
* The time it takes to break the block.
|
||||
*/
|
||||
private double breakTime;
|
||||
|
||||
public Pre(Robot robot, World world, int x, int y, int z, double breakTime) {
|
||||
super(robot);
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.breakTime = breakTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time it should take the robot to break the block.
|
||||
* <p/>
|
||||
* Note that the robot will still break the block instantly, but the
|
||||
* robot's execution is paused for the specified amount of time.
|
||||
*
|
||||
* @param breakTime the time in seconds the break operation takes.
|
||||
*/
|
||||
public void setBreakTime(double breakTime) {
|
||||
this.breakTime = Math.max(0.05, breakTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time that it will take to break the block.
|
||||
*
|
||||
* @see #setBreakTime(double)
|
||||
*/
|
||||
public double getBreakTime() {
|
||||
return breakTime;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired after a robot broke a block.
|
||||
*/
|
||||
public static class Post extends RobotBreakBlockEvent {
|
||||
/**
|
||||
* The amount of experience the block that was broken generated (e.g. certain ores).
|
||||
*/
|
||||
public final double experience;
|
||||
|
||||
public Post(Robot robot, double experience) {
|
||||
super(robot);
|
||||
this.experience = experience;
|
||||
}
|
||||
}
|
||||
}
|
18
src/main/java/li/cil/oc/api/event/RobotEvent.java
Normal file
18
src/main/java/li/cil/oc/api/event/RobotEvent.java
Normal file
@ -0,0 +1,18 @@
|
||||
package li.cil.oc.api.event;
|
||||
|
||||
import li.cil.oc.api.machine.Robot;
|
||||
import net.minecraftforge.event.Event;
|
||||
|
||||
/**
|
||||
* Base class for events generated by robots.
|
||||
*/
|
||||
public abstract class RobotEvent extends Event {
|
||||
/**
|
||||
* The robot for which this event was fired.
|
||||
*/
|
||||
public final Robot robot;
|
||||
|
||||
protected RobotEvent(Robot robot) {
|
||||
this.robot = robot;
|
||||
}
|
||||
}
|
19
src/main/java/li/cil/oc/api/event/RobotExhaustionEvent.java
Normal file
19
src/main/java/li/cil/oc/api/event/RobotExhaustionEvent.java
Normal file
@ -0,0 +1,19 @@
|
||||
package li.cil.oc.api.event;
|
||||
|
||||
import li.cil.oc.api.machine.Robot;
|
||||
|
||||
/**
|
||||
* Fired when a robot performed an action that would cause exhaustion for a
|
||||
* player. Used for the experience upgrade, for example.
|
||||
*/
|
||||
public class RobotExhaustionEvent extends RobotEvent {
|
||||
/**
|
||||
* The amount of exhaustion that was generated.
|
||||
*/
|
||||
public final double exhaustion;
|
||||
|
||||
public RobotExhaustionEvent(Robot robot, double exhaustion) {
|
||||
super(robot);
|
||||
this.exhaustion = exhaustion;
|
||||
}
|
||||
}
|
38
src/main/java/li/cil/oc/api/event/RobotMoveEvent.java
Normal file
38
src/main/java/li/cil/oc/api/event/RobotMoveEvent.java
Normal file
@ -0,0 +1,38 @@
|
||||
package li.cil.oc.api.event;
|
||||
|
||||
import li.cil.oc.api.machine.Robot;
|
||||
import net.minecraftforge.common.ForgeDirection;
|
||||
import net.minecraftforge.event.Cancelable;
|
||||
|
||||
public abstract class RobotMoveEvent extends RobotEvent {
|
||||
/**
|
||||
* The direction in which the robot will be moving.
|
||||
*/
|
||||
public final ForgeDirection direction;
|
||||
|
||||
protected RobotMoveEvent(Robot robot, ForgeDirection direction) {
|
||||
super(robot);
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a robot is about to move.
|
||||
* <p/>
|
||||
* Canceling the event will prevent the robot from moving.
|
||||
*/
|
||||
@Cancelable
|
||||
public static class Pre extends RobotMoveEvent {
|
||||
public Pre(Robot robot, ForgeDirection direction) {
|
||||
super(robot, direction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired after a robot moved.
|
||||
*/
|
||||
public static class Post extends RobotMoveEvent {
|
||||
public Post(Robot robot, ForgeDirection direction) {
|
||||
super(robot, direction);
|
||||
}
|
||||
}
|
||||
}
|
53
src/main/java/li/cil/oc/api/event/RobotPlaceBlockEvent.java
Normal file
53
src/main/java/li/cil/oc/api/event/RobotPlaceBlockEvent.java
Normal file
@ -0,0 +1,53 @@
|
||||
package li.cil.oc.api.event;
|
||||
|
||||
import li.cil.oc.api.machine.Robot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.event.Cancelable;
|
||||
|
||||
public abstract class RobotPlaceBlockEvent extends RobotEvent {
|
||||
/**
|
||||
* The item that is used to place the block.
|
||||
*/
|
||||
public final ItemStack stack;
|
||||
|
||||
/**
|
||||
* The world in which the block will be placed.
|
||||
*/
|
||||
public final World world;
|
||||
|
||||
/**
|
||||
* The coordinates at which the block will be placed.
|
||||
*/
|
||||
public final int x, y, z;
|
||||
|
||||
protected RobotPlaceBlockEvent(Robot robot, ItemStack stack, World world, int x, int y, int z) {
|
||||
super(robot);
|
||||
this.stack = stack;
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a robot is about to place a block.
|
||||
* <p/>
|
||||
* Canceling this event will prevent the block from being placed.
|
||||
*/
|
||||
@Cancelable
|
||||
public static class Pre extends RobotPlaceBlockEvent {
|
||||
public Pre(Robot robot, ItemStack stack, World world, int x, int y, int z) {
|
||||
super(robot, stack, world, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired after a robot placed a block.
|
||||
*/
|
||||
public static class Post extends RobotPlaceBlockEvent {
|
||||
public Post(Robot robot, ItemStack stack, World world, int x, int y, int z) {
|
||||
super(robot, stack, world, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
51
src/main/java/li/cil/oc/api/event/RobotRenderEvent.java
Normal file
51
src/main/java/li/cil/oc/api/event/RobotRenderEvent.java
Normal file
@ -0,0 +1,51 @@
|
||||
package li.cil.oc.api.event;
|
||||
|
||||
import li.cil.oc.api.machine.Robot;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraftforge.event.Cancelable;
|
||||
|
||||
/**
|
||||
* Fired directly before the robot's chassis is rendered.
|
||||
* <p/>
|
||||
* If this event is canceled, the chassis will <em>not</em> be rendered.
|
||||
* Component items' item renderes will still be invoked, at the possibly
|
||||
* modified mount points.
|
||||
* <p/>
|
||||
* <em>Important</em>: the robot instance may be null in this event, in
|
||||
* case the render pass is for rendering the robot in an inventory.
|
||||
*/
|
||||
@Cancelable
|
||||
public class RobotRenderEvent extends RobotEvent {
|
||||
/**
|
||||
* Points on the robot at which component models may be rendered.
|
||||
* <p/>
|
||||
* By convention, components should be rendered in order of their slots,
|
||||
* meaning that some components may not be rendered at all, if there are
|
||||
* not enough mount points.
|
||||
* <p/>
|
||||
* The equipped tool is rendered at a fixed position, this list does not
|
||||
* contain a mount point for it.
|
||||
*/
|
||||
public final MountPoint[] mountPoints;
|
||||
|
||||
public RobotRenderEvent(Robot robot, MountPoint[] mountPoints) {
|
||||
super(robot);
|
||||
this.mountPoints = mountPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes points on the robot model at which components are "mounted",
|
||||
* i.e. where component models may be rendered.
|
||||
*/
|
||||
public static class MountPoint {
|
||||
/**
|
||||
* The position of the mount point, relative to the robot's center.
|
||||
*/
|
||||
public final Vec3 offset = Vec3.createVectorHelper(0, 0, 0);
|
||||
|
||||
/**
|
||||
* The vector the mount point is facing.
|
||||
*/
|
||||
public final Vec3 normal = Vec3.createVectorHelper(0, 0, 0);
|
||||
}
|
||||
}
|
70
src/main/java/li/cil/oc/api/event/RobotUsedTool.java
Normal file
70
src/main/java/li/cil/oc/api/event/RobotUsedTool.java
Normal file
@ -0,0 +1,70 @@
|
||||
package li.cil.oc.api.event;
|
||||
|
||||
import li.cil.oc.api.machine.Robot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class RobotUsedTool extends RobotEvent {
|
||||
/**
|
||||
* The tool that was used, before and after use.
|
||||
*/
|
||||
public final ItemStack toolBeforeUse, toolAfterUse;
|
||||
|
||||
protected double damageRate;
|
||||
|
||||
protected RobotUsedTool(Robot robot, ItemStack toolBeforeUse, ItemStack toolAfterUse, double damageRate) {
|
||||
super(robot);
|
||||
this.toolBeforeUse = toolBeforeUse;
|
||||
this.toolAfterUse = toolAfterUse;
|
||||
this.damageRate = damageRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rate at which the used tool should lose durability, where one means
|
||||
* it loses durability at full speed, zero means it doesn't lose durability
|
||||
* at all.
|
||||
* <p/>
|
||||
* This value is in an interval of [0, 1].
|
||||
*/
|
||||
public double getDamageRate() {
|
||||
return damageRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a robot used a tool and is about to apply the damage rate to
|
||||
* partially undo the durability loss. This step is used to compute the
|
||||
* rate at which the tool should lose durability, which is used by the
|
||||
* experience upgrade, for example.
|
||||
*/
|
||||
public static class ComputeDamageRate extends RobotUsedTool {
|
||||
public ComputeDamageRate(Robot robot, ItemStack toolBeforeUse, ItemStack toolAfterUse, double damageRate) {
|
||||
super(robot, toolBeforeUse, toolAfterUse, damageRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rate at which the tool actually gets damaged.
|
||||
* <p/>
|
||||
* This will be clamped to an iterval of [0, 1].
|
||||
*
|
||||
* @param damageRate the new damage rate.
|
||||
*/
|
||||
public void setDamageRate(double damageRate) {
|
||||
this.damageRate = Math.max(0, Math.min(1, damageRate));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a robot used a tool and the previously fired damage rate
|
||||
* computation returned a value smaller than one. The callbacks of this
|
||||
* method are responsible for applying the inverse damage the tool took.
|
||||
* The <tt>toolAfterUse</tt> item stack represents the actual tool, any
|
||||
* changes must be applied to that variable. The <tt>toolBeforeUse</tt>
|
||||
* item stack is passed for reference, to compute the actual amount of
|
||||
* durability that was lost. This may be required for tools where the
|
||||
* durability is stored in the item's NBT tag.
|
||||
*/
|
||||
public static class ApplyDamageRate extends RobotUsedTool {
|
||||
public ApplyDamageRate(Robot robot, ItemStack toolBeforeUse, ItemStack toolAfterUse, double damageRate) {
|
||||
super(robot, toolBeforeUse, toolAfterUse, damageRate);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
package li.cil.oc.api.machine;
|
||||
|
||||
import li.cil.oc.api.Rotatable;
|
||||
import li.cil.oc.api.network.Environment;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
/**
|
||||
* This interface allows interaction with robots.
|
||||
@ -9,6 +11,18 @@ import net.minecraft.entity.player.EntityPlayer;
|
||||
* It is intended to be used by components when installed in a robot. In that
|
||||
* case, the robot in question is the tile entity passed to item driver when
|
||||
* asked to create the component's environment.
|
||||
* <p/>
|
||||
* A robot's inventory contains component items and items in the actual
|
||||
* inventory. The physical layout in the underlying 'real' inventory is as
|
||||
* follows:
|
||||
* <ul>
|
||||
* <li>Slot 0: Tool</li>
|
||||
* <li>Slot [1, dynamicComponentCapacity + 1): hot-swappable components.</li>
|
||||
* <li>Slot [dynamicComponentCapacity + 1, componentCapacity + 1): hard-wired components.</li>
|
||||
* <li>Slot [componentCapacity + 1, inventorySize): actual inventory.</li>
|
||||
* </ul>
|
||||
* Note that either of these intervals may be empty, depending on the parts
|
||||
* the robot is built from.
|
||||
*/
|
||||
public interface Robot extends Rotatable {
|
||||
/**
|
||||
@ -17,18 +31,59 @@ public interface Robot extends Rotatable {
|
||||
* <p/>
|
||||
* This will automatically be positioned and rotated to represent the
|
||||
* robot's current position and rotation in the world. Use this to trigger
|
||||
* events involving the robot that require a player entity, and for
|
||||
* interacting with the robots' inventory.
|
||||
* <p/>
|
||||
* Note that the inventory of each robot is structured such that the first
|
||||
* four slots are the "equipment" slots, from left to right, i.e. slot one
|
||||
* is the tool slot, slot two is the card slot, three the disk slot and
|
||||
* slot four is for upgrades. The inventory proper starts after that.
|
||||
* events involving the robot that require a player entity, and for more
|
||||
* in-depth interaction with the robots' inventory.
|
||||
*
|
||||
* @return the fake player for the robot.
|
||||
*/
|
||||
EntityPlayer player();
|
||||
|
||||
/**
|
||||
* The number of hot-swappable component slots in this robot.
|
||||
*/
|
||||
int dynamicComponentCapacity();
|
||||
|
||||
/**
|
||||
* The <em>total</em> number of component slots in this robot, including
|
||||
* hot-swappable component slots.
|
||||
*/
|
||||
int componentCapacity();
|
||||
|
||||
/**
|
||||
* The <em>total</em> inventory space in this robot, including tool and
|
||||
* component slots.
|
||||
*/
|
||||
int inventorySize();
|
||||
|
||||
/**
|
||||
* Get the item stack in the specified inventory slot.
|
||||
* <p/>
|
||||
* This operates on the underlying, real inventory, as described in the
|
||||
* comment on top of this class. The starting index of the part of the
|
||||
* inventory that is accessible to the robot for manipulation is at
|
||||
* <tt>componentCapacity + 1</tt>.
|
||||
* <p/>
|
||||
* This will return <tt>null</tt> for empty slots.
|
||||
*
|
||||
* @param index the index of the slot from which to get the stack.
|
||||
* @return the content of that slot, or <tt>null</tt>.
|
||||
*/
|
||||
ItemStack getStackInSlot(int index);
|
||||
|
||||
/**
|
||||
* Get the environment for the component in the specified slot.
|
||||
* <p/>
|
||||
* This operates on the underlying, real inventory, as described in the
|
||||
* comment on top of this class.
|
||||
* <p/>
|
||||
* This will return <tt>null</tt> for slots that do not contain components,
|
||||
* or components that do not have an environment (on the calling side).
|
||||
*
|
||||
* @param index the index of the slot from which to get the environment.
|
||||
* @return the environment for that slot, or <tt>null</tt>.
|
||||
*/
|
||||
Environment getComponentInSlot(int index);
|
||||
|
||||
/**
|
||||
* Gets the index of the currently selected slot in the robot's inventory.
|
||||
*
|
||||
|
@ -123,6 +123,11 @@ craftingUpgrade {
|
||||
["oc:circuitChip1", workbench, "oc:circuitChip1"]
|
||||
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
|
||||
}
|
||||
experienceUpgrade {
|
||||
input: [[ingotIron, "", ingotIron]
|
||||
["oc:circuitChip1", expBottle, "oc:circuitChip1"]
|
||||
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
|
||||
}
|
||||
generatorUpgrade {
|
||||
input: [[ingotIron, "", ingotIron]
|
||||
["oc:circuitChip1", craftingPiston, "oc:circuitChip1"]
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 325 B |
Binary file not shown.
After Width: | Height: | Size: 483 B |
@ -172,5 +172,6 @@ object Items extends ItemAPI {
|
||||
|
||||
// v1.3.0
|
||||
Recipes.addItemDelegate(new item.LinkedCard(multi), "linkedCard", "oc:linkedCard")
|
||||
Recipes.addItemDelegate(new item.UpgradeExperience(multi), "experienceUpgrade", "oc:experienceUpgrade")
|
||||
}
|
||||
}
|
@ -42,7 +42,6 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case PacketType.RobotEquippedUpgradeChange => onRobotEquippedUpgradeChange(p)
|
||||
case PacketType.RobotMove => onRobotMove(p)
|
||||
case PacketType.RobotSelectedSlotChange => onRobotSelectedSlotChange(p)
|
||||
case PacketType.RobotXp => onRobotXp(p)
|
||||
case PacketType.RotatableState => onRotatableState(p)
|
||||
case PacketType.RouterActivity => onRouterActivity(p)
|
||||
case PacketType.TextBufferColorChange => onTextBufferColorChange(p)
|
||||
@ -230,14 +229,6 @@ class PacketHandler extends CommonPacketHandler {
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRobotXp(p: PacketParser) =
|
||||
p.readTileEntity[RobotProxy]() match {
|
||||
case Some(t) =>
|
||||
t.robot.xp = p.readDouble()
|
||||
t.robot.updateXpInfo()
|
||||
case _ => // Invalid packet.
|
||||
}
|
||||
|
||||
def onRotatableState(p: PacketParser) =
|
||||
p.readTileEntity[Rotatable]() match {
|
||||
case Some(t) =>
|
||||
|
@ -2,6 +2,7 @@ package li.cil.oc.client.renderer.tileentity
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import java.util.logging.Level
|
||||
import li.cil.oc.api.event.RobotRenderEvent
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.util.RenderState
|
||||
@ -17,12 +18,14 @@ import net.minecraftforge.client.IItemRenderer.ItemRendererHelper._
|
||||
import net.minecraftforge.client.IItemRenderer.ItemRenderType
|
||||
import net.minecraftforge.client.IItemRenderer.ItemRenderType._
|
||||
import net.minecraftforge.client.MinecraftForgeClient
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import net.minecraftforge.common.{MinecraftForge, ForgeDirection}
|
||||
import org.lwjgl.opengl.{GL12, GL11}
|
||||
|
||||
object RobotRenderer extends TileEntitySpecialRenderer {
|
||||
private val displayList = GLAllocation.generateDisplayLists(2)
|
||||
|
||||
private val mountPoints = Array.fill(7)(new RobotRenderEvent.MountPoint())
|
||||
|
||||
private val gap = 1.0f / 28.0f
|
||||
private val gt = 0.5f + gap
|
||||
private val gb = 0.5f - gap
|
||||
@ -104,7 +107,64 @@ object RobotRenderer extends TileEntitySpecialRenderer {
|
||||
|
||||
compileList()
|
||||
|
||||
def renderChassis(isRunning: Boolean = false, level: Int = 0, offset: Double = 0) {
|
||||
def resetMountPoints() {
|
||||
// Back.
|
||||
mountPoints(0).offset.xCoord = 0
|
||||
mountPoints(0).offset.yCoord = 0.33
|
||||
mountPoints(0).offset.zCoord = -0.33
|
||||
mountPoints(0).normal.xCoord = 0
|
||||
mountPoints(0).normal.yCoord = 0
|
||||
mountPoints(0).normal.zCoord = -1
|
||||
|
||||
mountPoints(0).offset.xCoord = 0
|
||||
mountPoints(0).offset.yCoord = -0.33
|
||||
mountPoints(0).offset.zCoord = -0.33
|
||||
mountPoints(0).normal.xCoord = 0
|
||||
mountPoints(0).normal.yCoord = 0
|
||||
mountPoints(0).normal.zCoord = -1
|
||||
|
||||
// Front.
|
||||
mountPoints(0).offset.xCoord = 0
|
||||
mountPoints(0).offset.yCoord = -0.33
|
||||
mountPoints(0).offset.zCoord = 0.33
|
||||
mountPoints(0).normal.xCoord = 0
|
||||
mountPoints(0).normal.yCoord = 0
|
||||
mountPoints(0).normal.zCoord = 1
|
||||
|
||||
// Left.
|
||||
mountPoints(0).offset.xCoord = -0.33
|
||||
mountPoints(0).offset.yCoord = 0.33
|
||||
mountPoints(0).offset.zCoord = 0
|
||||
mountPoints(0).normal.xCoord = -1
|
||||
mountPoints(0).normal.yCoord = 0
|
||||
mountPoints(0).normal.zCoord = 0
|
||||
|
||||
mountPoints(0).offset.xCoord = -0.33
|
||||
mountPoints(0).offset.yCoord = -0.33
|
||||
mountPoints(0).offset.zCoord = 0
|
||||
mountPoints(0).normal.xCoord = -1
|
||||
mountPoints(0).normal.yCoord = 0
|
||||
mountPoints(0).normal.zCoord = 0
|
||||
|
||||
// Right.
|
||||
mountPoints(0).offset.xCoord = 0.33
|
||||
mountPoints(0).offset.yCoord = 0.33
|
||||
mountPoints(0).offset.zCoord = 0
|
||||
mountPoints(0).normal.xCoord = 1
|
||||
mountPoints(0).normal.yCoord = 0
|
||||
mountPoints(0).normal.zCoord = 0
|
||||
|
||||
mountPoints(0).offset.xCoord = 0.33
|
||||
mountPoints(0).offset.yCoord = -0.33
|
||||
mountPoints(0).offset.zCoord = 0
|
||||
mountPoints(0).normal.xCoord = 1
|
||||
mountPoints(0).normal.yCoord = 0
|
||||
mountPoints(0).normal.zCoord = 0
|
||||
}
|
||||
|
||||
def renderChassis(robot: tileentity.Robot = null, offset: Double = 0) {
|
||||
val isRunning = if (robot == null) false else robot.isRunning
|
||||
|
||||
val size = 0.3f
|
||||
val l = 0.5f - size
|
||||
val h = 0.5f + size
|
||||
@ -118,57 +178,53 @@ object RobotRenderer extends TileEntitySpecialRenderer {
|
||||
(0.25f - vStep, 0.25f + vStep, 0.75f - vStep, 0.75f + vStep)
|
||||
}
|
||||
|
||||
bindTexture(Textures.blockRobot)
|
||||
if (level > 19) {
|
||||
GL11.glColor3f(0.4f, 1, 1)
|
||||
}
|
||||
else if (level > 9) {
|
||||
GL11.glColor3f(1, 1, 0.4f)
|
||||
}
|
||||
else {
|
||||
GL11.glColor3f(0.5f, 0.5f, 0.5f)
|
||||
}
|
||||
if (!isRunning) {
|
||||
GL11.glTranslatef(0, -2 * gap, 0)
|
||||
}
|
||||
GL11.glCallList(displayList)
|
||||
if (!isRunning) {
|
||||
GL11.glTranslatef(0, 2 * gap, 0)
|
||||
}
|
||||
GL11.glCallList(displayList + 1)
|
||||
GL11.glColor3f(1, 1, 1)
|
||||
resetMountPoints()
|
||||
val event = new RobotRenderEvent(robot, mountPoints)
|
||||
MinecraftForge.EVENT_BUS.post(event)
|
||||
if (!event.isCanceled) {
|
||||
bindTexture(Textures.blockRobot)
|
||||
if (!isRunning) {
|
||||
GL11.glTranslatef(0, -2 * gap, 0)
|
||||
}
|
||||
GL11.glCallList(displayList)
|
||||
if (!isRunning) {
|
||||
GL11.glTranslatef(0, 2 * gap, 0)
|
||||
}
|
||||
GL11.glCallList(displayList + 1)
|
||||
GL11.glColor3f(1, 1, 1)
|
||||
|
||||
if (MinecraftForgeClient.getRenderPass == 0) {
|
||||
RenderState.disableLighting()
|
||||
}
|
||||
if (isRunning) {
|
||||
if (MinecraftForgeClient.getRenderPass == 0) {
|
||||
RenderState.disableLighting()
|
||||
}
|
||||
|
||||
if (isRunning) {
|
||||
val t = Tessellator.instance
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(l, gt, l, u0, v0)
|
||||
t.addVertexWithUV(l, gb, l, u0, v1)
|
||||
t.addVertexWithUV(l, gb, h, u1, v1)
|
||||
t.addVertexWithUV(l, gt, h, u1, v0)
|
||||
val t = Tessellator.instance
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(l, gt, l, u0, v0)
|
||||
t.addVertexWithUV(l, gb, l, u0, v1)
|
||||
t.addVertexWithUV(l, gb, h, u1, v1)
|
||||
t.addVertexWithUV(l, gt, h, u1, v0)
|
||||
|
||||
t.addVertexWithUV(l, gt, h, u0, v0)
|
||||
t.addVertexWithUV(l, gb, h, u0, v1)
|
||||
t.addVertexWithUV(h, gb, h, u1, v1)
|
||||
t.addVertexWithUV(h, gt, h, u1, v0)
|
||||
t.addVertexWithUV(l, gt, h, u0, v0)
|
||||
t.addVertexWithUV(l, gb, h, u0, v1)
|
||||
t.addVertexWithUV(h, gb, h, u1, v1)
|
||||
t.addVertexWithUV(h, gt, h, u1, v0)
|
||||
|
||||
t.addVertexWithUV(h, gt, h, u0, v0)
|
||||
t.addVertexWithUV(h, gb, h, u0, v1)
|
||||
t.addVertexWithUV(h, gb, l, u1, v1)
|
||||
t.addVertexWithUV(h, gt, l, u1, v0)
|
||||
t.addVertexWithUV(h, gt, h, u0, v0)
|
||||
t.addVertexWithUV(h, gb, h, u0, v1)
|
||||
t.addVertexWithUV(h, gb, l, u1, v1)
|
||||
t.addVertexWithUV(h, gt, l, u1, v0)
|
||||
|
||||
t.addVertexWithUV(h, gt, l, u0, v0)
|
||||
t.addVertexWithUV(h, gb, l, u0, v1)
|
||||
t.addVertexWithUV(l, gb, l, u1, v1)
|
||||
t.addVertexWithUV(l, gt, l, u1, v0)
|
||||
t.draw()
|
||||
}
|
||||
t.addVertexWithUV(h, gt, l, u0, v0)
|
||||
t.addVertexWithUV(h, gb, l, u0, v1)
|
||||
t.addVertexWithUV(l, gb, l, u1, v1)
|
||||
t.addVertexWithUV(l, gt, l, u1, v0)
|
||||
t.draw()
|
||||
|
||||
if (MinecraftForgeClient.getRenderPass == 0) {
|
||||
RenderState.enableLighting()
|
||||
if (MinecraftForgeClient.getRenderPass == 0) {
|
||||
RenderState.enableLighting()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,7 +280,7 @@ object RobotRenderer extends TileEntitySpecialRenderer {
|
||||
|
||||
if (MinecraftForgeClient.getRenderPass == 0) {
|
||||
val offset = timeJitter + worldTime / 20.0
|
||||
renderChassis(robot.isRunning, robot.level, offset)
|
||||
renderChassis(robot, offset)
|
||||
}
|
||||
|
||||
robot.equippedItem match {
|
||||
|
@ -22,7 +22,6 @@ object PacketType extends Enumeration {
|
||||
RobotEquippedUpgradeChange,
|
||||
RobotMove,
|
||||
RobotSelectedSlotChange,
|
||||
RobotXp,
|
||||
RotatableState,
|
||||
RouterActivity,
|
||||
TextBufferColorChange,
|
||||
|
@ -21,6 +21,7 @@ import net.minecraft.item.{Item, ItemStack}
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraftforge.oredict.OreDictionary
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
import li.cil.oc.common.event.{ExperienceUpgradeHandler, UniversalElectricityToolHandler, RobotCommonHandler}
|
||||
|
||||
class Proxy {
|
||||
def preInit(e: FMLPreInitializationEvent) {
|
||||
@ -77,6 +78,7 @@ class Proxy {
|
||||
api.Driver.add(driver.item.RedstoneCard)
|
||||
api.Driver.add(driver.item.Screen)
|
||||
api.Driver.add(driver.item.UpgradeCrafting)
|
||||
api.Driver.add(driver.item.UpgradeExperience)
|
||||
api.Driver.add(driver.item.UpgradeGenerator)
|
||||
api.Driver.add(driver.item.UpgradeNavigation)
|
||||
api.Driver.add(driver.item.UpgradeSign)
|
||||
@ -94,6 +96,12 @@ class Proxy {
|
||||
api.Driver.add(driver.converter.FluidTankInfo)
|
||||
api.Driver.add(driver.converter.ItemStack)
|
||||
|
||||
MinecraftForge.EVENT_BUS.register(RobotCommonHandler)
|
||||
MinecraftForge.EVENT_BUS.register(ExperienceUpgradeHandler)
|
||||
if (Mods.UniversalElectricity.isAvailable) {
|
||||
MinecraftForge.EVENT_BUS.register(UniversalElectricityToolHandler)
|
||||
}
|
||||
|
||||
Recipes.init()
|
||||
GameRegistry.registerCraftingHandler(CraftingHandler)
|
||||
|
||||
|
@ -162,7 +162,7 @@ class RobotProxy(val parent: SpecialDelegator) extends RedstoneAware with Specia
|
||||
case proxy: tileentity.RobotProxy =>
|
||||
val robot = proxy.robot
|
||||
if (robot.player == player) return false
|
||||
if (!world.isRemote && (!player.capabilities.isCreativeMode || proxy.globalBuffer > 1 || proxy.robot.xp > 0)) {
|
||||
if (!world.isRemote) {
|
||||
parent.dropBlockAsItem(world, x, y, z, robot.createItemStack())
|
||||
}
|
||||
if (Blocks.blockSpecial.subBlock(world, robot.moveFromX, robot.moveFromY, robot.moveFromZ).exists(_ == Blocks.robotAfterimage)) {
|
||||
|
@ -0,0 +1,109 @@
|
||||
package li.cil.oc.common.event
|
||||
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api.event._
|
||||
import li.cil.oc.api.machine.Robot
|
||||
import li.cil.oc.server.component
|
||||
import net.minecraft.util.ChatMessageComponent
|
||||
import net.minecraftforge.event.ForgeSubscribe
|
||||
import org.lwjgl.opengl.GL11
|
||||
|
||||
object ExperienceUpgradeHandler {
|
||||
@ForgeSubscribe
|
||||
def onRobotAnalyze(e: RobotAnalyzeEvent) {
|
||||
val (level, experience) = getLevelAndExperience(e.robot)
|
||||
// This is basically a 'does it have an experience upgrade' check.
|
||||
if (experience != 0.0) {
|
||||
e.player.sendChatToPlayer(ChatMessageComponent.createFromTranslationWithSubstitutions(
|
||||
Settings.namespace + "gui.Analyzer.RobotXp", "%.2f".format(experience), level: Integer))
|
||||
}
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
def onRobotComputeDamageRate(e: RobotUsedTool.ComputeDamageRate) {
|
||||
e.setDamageRate(e.getDamageRate * math.max(0, 1 - getLevel(e.robot) * Settings.get.toolEfficiencyPerLevel))
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
def onRobotBreakBlockPre(e: RobotBreakBlockEvent.Pre) {
|
||||
val boost = math.max(0, 1 - getLevel(e.robot) * Settings.get.harvestSpeedBoostPerLevel)
|
||||
e.setBreakTime(e.getBreakTime * boost)
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
def onRobotAttackEntityPost(e: RobotAttackEntityEvent.Post) {
|
||||
if (e.robot.getComponentInSlot(e.robot.selectedSlot()) != null && e.target.isDead) {
|
||||
addExperience(e.robot, Settings.get.robotActionXp)
|
||||
}
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
def onRobotBreakBlockPost(e: RobotBreakBlockEvent.Post) {
|
||||
addExperience(e.robot, e.experience * Settings.get.robotOreXpRate + Settings.get.robotActionXp)
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
def onRobotPlaceBlockPost(e: RobotPlaceBlockEvent.Post) {
|
||||
addExperience(e.robot, Settings.get.robotActionXp)
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
def onRobotMovePost(e: RobotMoveEvent.Post) {
|
||||
addExperience(e.robot, Settings.get.robotExhaustionXpRate * 0.01)
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
def onRobotExhaustion(e: RobotExhaustionEvent) {
|
||||
addExperience(e.robot, Settings.get.robotExhaustionXpRate * e.exhaustion)
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
def onRobotRender(e: RobotRenderEvent) {
|
||||
val level = if (e.robot != null) getLevel(e.robot) else 0
|
||||
if (level > 19) {
|
||||
GL11.glColor3f(0.4f, 1, 1)
|
||||
}
|
||||
else if (level > 9) {
|
||||
GL11.glColor3f(1, 1, 0.4f)
|
||||
}
|
||||
else {
|
||||
GL11.glColor3f(0.5f, 0.5f, 0.5f)
|
||||
}
|
||||
}
|
||||
|
||||
private def getLevel(robot: Robot) = {
|
||||
var level = 0
|
||||
for (index <- 1 to robot.componentCapacity) {
|
||||
robot.getComponentInSlot(index) match {
|
||||
case upgrade: component.UpgradeExperience =>
|
||||
level += upgrade.level
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
level
|
||||
}
|
||||
|
||||
private def getLevelAndExperience(robot: Robot) = {
|
||||
var level = 0
|
||||
var experience = 0.0
|
||||
for (index <- 1 to robot.componentCapacity) {
|
||||
robot.getComponentInSlot(index) match {
|
||||
case upgrade: component.UpgradeExperience =>
|
||||
level += upgrade.level
|
||||
experience += upgrade.experience
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
(level, experience)
|
||||
}
|
||||
|
||||
private def addExperience(robot: Robot, amount: Double) {
|
||||
for (index <- 1 to robot.componentCapacity) {
|
||||
robot.getComponentInSlot(index) match {
|
||||
case upgrade: component.UpgradeExperience =>
|
||||
upgrade.addExperience(amount)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package li.cil.oc.common.event
|
||||
|
||||
import net.minecraftforge.event.ForgeSubscribe
|
||||
import li.cil.oc.api.event.RobotUsedTool
|
||||
|
||||
object RobotCommonHandler {
|
||||
@ForgeSubscribe
|
||||
def onRobotApplyDamageRate(e: RobotUsedTool.ApplyDamageRate) {
|
||||
if (e.toolAfterUse.isItemStackDamageable) {
|
||||
val damage = e.toolAfterUse.getItemDamage - e.toolBeforeUse.getItemDamage
|
||||
if (damage > 0) {
|
||||
val actualDamage = damage * e.getDamageRate
|
||||
val repairedDamage = if (e.robot.player.getRNG.nextDouble() > 0.5) damage - math.floor(actualDamage).toInt else damage - math.ceil(actualDamage).toInt
|
||||
e.toolAfterUse.setItemDamage(e.toolAfterUse.getItemDamage - repairedDamage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package li.cil.oc.common.event
|
||||
|
||||
import net.minecraftforge.event.ForgeSubscribe
|
||||
import li.cil.oc.api.event.RobotUsedTool
|
||||
import li.cil.oc.util.mods.UniversalElectricity
|
||||
|
||||
object UniversalElectricityToolHandler {
|
||||
@ForgeSubscribe
|
||||
def onRobotApplyDamageRate(e: RobotUsedTool.ApplyDamageRate) {
|
||||
if (UniversalElectricity.isEnergyItem(e.toolAfterUse)) {
|
||||
val damage = UniversalElectricity.getEnergyInItem(e.toolBeforeUse) - UniversalElectricity.getEnergyInItem(e.toolAfterUse)
|
||||
if (damage > 0) {
|
||||
val actualDamage = damage * e.getDamageRate
|
||||
val repairedDamage = if (e.robot.player.getRNG.nextDouble() > 0.5) damage - math.floor(actualDamage).toLong else damage - math.ceil(actualDamage).toLong
|
||||
UniversalElectricity.chargeItem(e.toolAfterUse, repairedDamage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
src/main/scala/li/cil/oc/common/item/UpgradeExperience.scala
Normal file
25
src/main/scala/li/cil/oc/common/item/UpgradeExperience.scala
Normal file
@ -0,0 +1,25 @@
|
||||
package li.cil.oc.common.item
|
||||
|
||||
import java.util
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.util.Tooltip
|
||||
import net.minecraft.client.renderer.texture.IconRegister
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.{ItemStack, EnumRarity}
|
||||
|
||||
class UpgradeExperience(val parent: Delegator) extends Delegate {
|
||||
val unlocalizedName = "UpgradeExperience"
|
||||
|
||||
override def rarity = EnumRarity.epic
|
||||
|
||||
override def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
|
||||
tooltip.addAll(Tooltip.get(unlocalizedName))
|
||||
super.tooltipLines(stack, player, tooltip, advanced)
|
||||
}
|
||||
|
||||
override def registerIcons(iconRegister: IconRegister) = {
|
||||
super.registerIcons(iconRegister)
|
||||
|
||||
icon = iconRegister.registerIcon(Settings.resourceDomain + ":upgrade_experience")
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import java.util.logging.Level
|
||||
import li.cil.oc._
|
||||
import li.cil.oc.api.Driver
|
||||
import li.cil.oc.api.driver.Slot
|
||||
import li.cil.oc.api.event.{RobotAnalyzeEvent, RobotMoveEvent}
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.client.gui
|
||||
import li.cil.oc.common.block.Delegator
|
||||
@ -18,7 +19,7 @@ import net.minecraft.inventory.ISidedInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.ChatMessageComponent
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import net.minecraftforge.common.{MinecraftForge, ForgeDirection}
|
||||
import net.minecraftforge.fluids.{BlockFluidBase, FluidRegistry}
|
||||
import scala.io.Source
|
||||
|
||||
@ -39,8 +40,13 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
// Note: we implement IRobotContext in the TE to allow external components
|
||||
//to cast their owner to it (to allow interacting with their owning robot).
|
||||
override def dynamicComponentCapacity = 3
|
||||
|
||||
override def componentCapacity = 3
|
||||
|
||||
override def inventorySize = getSizeInventory
|
||||
|
||||
override def getComponentInSlot(index: Int) = components(index).orNull
|
||||
|
||||
var selectedSlot = actualSlot(0)
|
||||
|
||||
@ -92,16 +98,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
|
||||
var tag: NBTTagCompound = _
|
||||
|
||||
var xp = 0.0
|
||||
|
||||
def xpForNextLevel = xpForLevel(level + 1)
|
||||
|
||||
def xpForLevel(level: Int) = Settings.get.baseXpToLevel + Math.pow(level * Settings.get.constantXpGrowth, Settings.get.exponentialXpGrowth)
|
||||
|
||||
var level = 0
|
||||
|
||||
var xpChanged = false
|
||||
|
||||
var globalBuffer, globalBufferSize = 0.0
|
||||
|
||||
var equippedItem: Option[ItemStack] = None
|
||||
@ -120,25 +116,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
|
||||
private lazy val player_ = new robot.Player(this)
|
||||
|
||||
def addXp(value: Double) {
|
||||
if (level < 30 && isServer) {
|
||||
xp = xp + value
|
||||
xpChanged = true
|
||||
if (xp >= xpForNextLevel) {
|
||||
updateXpInfo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def updateXpInfo() {
|
||||
// xp(level) = base + (level * const) ^ exp
|
||||
// pow(xp(level) - base, 1/exp) / const = level
|
||||
level = math.min((Math.pow(xp - Settings.get.baseXpToLevel, 1 / Settings.get.exponentialXpGrowth) / Settings.get.constantXpGrowth).toInt, 30)
|
||||
if (isServer) {
|
||||
bot.node.setLocalBufferSize(Settings.get.bufferRobot + Settings.get.bufferPerLevel * level)
|
||||
}
|
||||
}
|
||||
|
||||
override def maxComponents = 8
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -148,8 +125,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
Settings.namespace + "gui.Analyzer.RobotOwner", owner))
|
||||
player.sendChatToPlayer(ChatMessageComponent.createFromTranslationWithSubstitutions(
|
||||
Settings.namespace + "gui.Analyzer.RobotName", player_.getCommandSenderName))
|
||||
player.sendChatToPlayer(ChatMessageComponent.createFromTranslationWithSubstitutions(
|
||||
Settings.namespace + "gui.Analyzer.RobotXp", xp.formatted("%.2f"), level: Integer))
|
||||
MinecraftForge.EVENT_BUS.post(new RobotAnalyzeEvent(this, player))
|
||||
super.onAnalyze(player, side, hitX, hitY, hitZ)
|
||||
}
|
||||
|
||||
@ -166,6 +142,13 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
if (!world.blockExists(nx, ny, nz)) {
|
||||
return false // Don't fall off the earth.
|
||||
}
|
||||
|
||||
if (isServer) {
|
||||
val event = new RobotMoveEvent.Pre(this, direction)
|
||||
MinecraftForge.EVENT_BUS.post(event)
|
||||
if (event.isCanceled) return false
|
||||
}
|
||||
|
||||
val blockId = world.getBlockId(nx, ny, nz)
|
||||
val metadata = world.getBlockMetadata(nx, ny, nz)
|
||||
try {
|
||||
@ -193,6 +176,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
if (isServer) {
|
||||
ServerPacketSender.sendRobotMove(this, ox, oy, oz, direction)
|
||||
checkRedstoneInputChanged()
|
||||
MinecraftForge.EVENT_BUS.post(new RobotMoveEvent.Post(this, direction))
|
||||
}
|
||||
else {
|
||||
// If we broke some replaceable block (like grass) play its break sound.
|
||||
@ -226,9 +210,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
val stack = Blocks.robotProxy.createItemStack()
|
||||
val tag = if (this.tag != null) this.tag.copy.asInstanceOf[NBTTagCompound] else new NBTTagCompound("tag")
|
||||
stack.setTagCompound(tag)
|
||||
if (xp > 0) {
|
||||
tag.setDouble(Settings.namespace + "xp", xp)
|
||||
}
|
||||
if (globalBuffer > 1) {
|
||||
tag.setInteger(Settings.namespace + "storedEnergy", globalBuffer.toInt)
|
||||
}
|
||||
@ -238,9 +219,9 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
def parseItemStack(stack: ItemStack) {
|
||||
if (stack.hasTagCompound) {
|
||||
tag = stack.getTagCompound.copy.asInstanceOf[NBTTagCompound]
|
||||
xp = tag.getDouble(Settings.namespace + "xp")
|
||||
updateXpInfo()
|
||||
bot.node.changeBuffer(stack.getTagCompound.getInteger(Settings.namespace + "storedEnergy"))
|
||||
// TODO migration: xp to xp upgrade
|
||||
// xp = tag.getDouble(Settings.namespace + "xp")
|
||||
}
|
||||
else {
|
||||
tag = new NBTTagCompound("tag")
|
||||
@ -323,10 +304,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
globalBuffer = bot.node.globalBuffer
|
||||
globalBufferSize = bot.node.globalBufferSize
|
||||
updatePowerInformation()
|
||||
if (xpChanged && world.getWorldInfo.getWorldTotalTime % 200 == 0) {
|
||||
xpChanged = false
|
||||
ServerPacketSender.sendRobotXp(this)
|
||||
}
|
||||
}
|
||||
else if (isRunning && isAnimatingMove) {
|
||||
client.Sound.updatePosition(this)
|
||||
@ -339,7 +316,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
case Some(item) => player_.getAttributeMap.applyAttributeModifiers(item.getAttributeModifiers)
|
||||
case _ =>
|
||||
}
|
||||
updateXpInfo()
|
||||
|
||||
// Ensure we have a node address, because the proxy needs this to initialize
|
||||
// its own node to the same address ours has.
|
||||
@ -372,8 +348,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
if (nbt.hasKey(Settings.namespace + "tag")) {
|
||||
tag = nbt.getCompoundTag(Settings.namespace + "tag")
|
||||
}
|
||||
xp = nbt.getDouble(Settings.namespace + "xp") max 0
|
||||
updateXpInfo()
|
||||
selectedSlot = nbt.getInteger(Settings.namespace + "selectedSlot") max actualSlot(0) min (getSizeInventory - 1)
|
||||
animationTicksTotal = nbt.getInteger(Settings.namespace + "animationTicksTotal")
|
||||
animationTicksLeft = nbt.getInteger(Settings.namespace + "animationTicksLeft")
|
||||
@ -384,6 +358,9 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
swingingTool = nbt.getBoolean(Settings.namespace + "swingingTool")
|
||||
turnAxis = nbt.getByte(Settings.namespace + "turnAxis")
|
||||
}
|
||||
|
||||
// TODO migration: xp to xp upgrade
|
||||
// xp = nbt.getDouble(Settings.namespace + "xp") max 0
|
||||
}
|
||||
|
||||
// Side check for Waila (and other mods that may call this client side).
|
||||
@ -398,7 +375,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
if (tag != null) {
|
||||
nbt.setCompoundTag(Settings.namespace + "tag", tag)
|
||||
}
|
||||
nbt.setDouble(Settings.namespace + "xp", xp)
|
||||
nbt.setInteger(Settings.namespace + "selectedSlot", selectedSlot)
|
||||
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
||||
nbt.setInteger(Settings.namespace + "animationTicksTotal", animationTicksTotal)
|
||||
@ -424,8 +400,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
if (nbt.hasKey("upgrade")) {
|
||||
equippedUpgrade = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("upgrade")))
|
||||
}
|
||||
xp = nbt.getDouble(Settings.namespace + "xp")
|
||||
updateXpInfo()
|
||||
animationTicksTotal = nbt.getInteger("animationTicksTotal")
|
||||
animationTicksLeft = nbt.getInteger("animationTicksLeft")
|
||||
moveFromX = nbt.getInteger("moveFromX")
|
||||
@ -459,7 +433,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
||||
}
|
||||
nbt.setNewCompoundTag("upgrade", getStackInSlot(3).writeToNBT)
|
||||
}
|
||||
nbt.setDouble(Settings.namespace + "xp", xp)
|
||||
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
||||
nbt.setInteger("animationTicksTotal", animationTicksTotal)
|
||||
nbt.setInteger("animationTicksLeft", animationTicksLeft)
|
||||
|
@ -29,17 +29,22 @@ class RobotProxy(val robot: Robot) extends traits.Computer with traits.TextBuffe
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
// Note: we implement IRobotContext in the TE to allow external components
|
||||
//to cast their owner to it (to allow interacting with their owning robot).
|
||||
|
||||
override def isRunning = robot.isRunning
|
||||
|
||||
override def setRunning(value: Boolean) = robot.setRunning(value)
|
||||
|
||||
override def selectedSlot() = robot.selectedSlot
|
||||
|
||||
override def player() = robot.player()
|
||||
|
||||
override def dynamicComponentCapacity = robot.dynamicComponentCapacity
|
||||
|
||||
override def componentCapacity = robot.componentCapacity
|
||||
|
||||
override def inventorySize = robot.inventorySize
|
||||
|
||||
override def getComponentInSlot(index: Int) = robot.getComponentInSlot(index)
|
||||
|
||||
override def selectedSlot() = robot.selectedSlot
|
||||
|
||||
override def saveUpgrade() = robot.saveUpgrade()
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
@ -201,15 +201,6 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t, 16)
|
||||
}
|
||||
|
||||
def sendRobotXp(t: tileentity.Robot) {
|
||||
val pb = new PacketBuilder(PacketType.RobotXp)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
pb.writeDouble(t.xp)
|
||||
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendRotatableState(t: Rotatable) {
|
||||
val pb = new PacketBuilder(PacketType.RotatableState)
|
||||
|
||||
|
@ -0,0 +1,58 @@
|
||||
package li.cil.oc.server.component
|
||||
|
||||
import li.cil.oc.{Settings, api}
|
||||
import li.cil.oc.api.network.{Arguments, Context, Callback, Visibility}
|
||||
import li.cil.oc.common.component.ManagedComponent
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
class UpgradeExperience extends ManagedComponent {
|
||||
def node = api.Network.newNode(this, Visibility.Network).
|
||||
withComponent("experience").
|
||||
withConnector(30 * Settings.get.bufferPerLevel).
|
||||
create()
|
||||
|
||||
var experience = 0.0
|
||||
|
||||
var level = 0
|
||||
|
||||
def xpForLevel(level: Int) = Settings.get.baseXpToLevel + Math.pow(level * Settings.get.constantXpGrowth, Settings.get.exponentialXpGrowth)
|
||||
|
||||
def xpForNextLevel = xpForLevel(level + 1)
|
||||
|
||||
def addExperience(value: Double) {
|
||||
if (level < 30) {
|
||||
experience = experience + value
|
||||
if (experience >= xpForNextLevel) {
|
||||
updateXpInfo()
|
||||
}
|
||||
// ServerPacketSender.sendRobotXp(this)
|
||||
}
|
||||
}
|
||||
|
||||
def updateXpInfo() {
|
||||
// xp(level) = base + (level * const) ^ exp
|
||||
// pow(xp(level) - base, 1/exp) / const = level
|
||||
level = math.min((Math.pow(experience - Settings.get.baseXpToLevel, 1 / Settings.get.exponentialXpGrowth) / Settings.get.constantXpGrowth).toInt, 30)
|
||||
if (node != null) {
|
||||
node.setLocalBufferSize(Settings.get.bufferPerLevel * level)
|
||||
}
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def level(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val xpNeeded = xpForNextLevel - xpForLevel(level)
|
||||
val xpProgress = math.max(0, experience - xpForLevel(level))
|
||||
result(level + xpProgress / xpNeeded)
|
||||
}
|
||||
|
||||
override def save(nbt: NBTTagCompound) {
|
||||
super.save(nbt)
|
||||
nbt.setDouble(Settings.namespace + "xp", experience)
|
||||
}
|
||||
|
||||
override def load(nbt: NBTTagCompound) {
|
||||
super.load(nbt)
|
||||
experience = nbt.getDouble(Settings.namespace + "xp") max 0
|
||||
updateXpInfo()
|
||||
}
|
||||
}
|
@ -2,8 +2,9 @@ package li.cil.oc.server.component.robot
|
||||
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper
|
||||
import java.util.logging.Level
|
||||
import li.cil.oc.api.event._
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.util.mods.{Mods, UniversalElectricity, TinkersConstruct, PortalGun}
|
||||
import li.cil.oc.util.mods.{Mods, TinkersConstruct, PortalGun}
|
||||
import li.cil.oc.{OpenComputers, Settings}
|
||||
import net.minecraft.block.{BlockPistonBase, BlockFluid, Block}
|
||||
import net.minecraft.entity.item.EntityItem
|
||||
@ -99,9 +100,11 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Sett
|
||||
callUsingItemInSlot(0, stack => entity match {
|
||||
case player: EntityPlayer if !canAttackPlayer(player) => // Avoid player damage.
|
||||
case _ =>
|
||||
super.attackTargetEntityWithCurrentItem(entity)
|
||||
if (stack != null && entity.isDead) {
|
||||
robot.addXp(Settings.get.robotActionXp)
|
||||
val event = new RobotAttackEntityEvent.Pre(robot, entity)
|
||||
MinecraftForge.EVENT_BUS.post(event)
|
||||
if (!event.isCanceled) {
|
||||
super.attackTargetEntityWithCurrentItem(entity)
|
||||
MinecraftForge.EVENT_BUS.post(new RobotAttackEntityEvent.Post(robot, entity))
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -262,7 +265,11 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Sett
|
||||
val breakTime =
|
||||
if (cobwebOverride) Settings.get.swingDelay
|
||||
else hardness * 1.5 / strength
|
||||
val adjustedBreakTime = math.max(0.05, breakTime * Settings.get.harvestRatio * math.max(1 - robot.level * Settings.get.harvestSpeedBoostPerLevel, 0))
|
||||
|
||||
val preEvent = new RobotBreakBlockEvent.Pre(robot, world, x, y, z, breakTime * Settings.get.harvestRatio)
|
||||
MinecraftForge.EVENT_BUS.post(preEvent)
|
||||
if (preEvent.isCanceled) return 0
|
||||
val adjustedBreakTime = math.max(0.05, preEvent.getBreakTime)
|
||||
|
||||
// Special handling for Tinkers Construct - tools like the hammers do
|
||||
// their break logic in onBlockStartBreak but return true to cancel
|
||||
@ -295,10 +302,10 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Sett
|
||||
// check only serves to test whether the block can drop anything at all.
|
||||
if (block.canHarvestBlock(this, metadata)) {
|
||||
block.harvestBlock(world, this, x, y, z, metadata)
|
||||
robot.addXp(breakEvent.getExpToDrop * Settings.get.robotOreXpRate)
|
||||
MinecraftForge.EVENT_BUS.post(new RobotBreakBlockEvent.Post(robot, breakEvent.getExpToDrop))
|
||||
}
|
||||
if (stack != null) {
|
||||
robot.addXp(Settings.get.robotActionXp)
|
||||
else if (stack != null) {
|
||||
MinecraftForge.EVENT_BUS.post(new RobotBreakBlockEvent.Post(robot, 0))
|
||||
}
|
||||
return adjustedBreakTime
|
||||
}
|
||||
@ -351,37 +358,28 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Sett
|
||||
}
|
||||
|
||||
private def tryRepair(stack: ItemStack, oldStack: ItemStack) {
|
||||
def repair(high: Long, low: Long) = {
|
||||
val needsRepairing = low < high
|
||||
val damageRate = Settings.get.itemDamageRate * math.max(1 - robot.level * Settings.get.toolEfficiencyPerLevel, 0)
|
||||
val shouldRepair = needsRepairing && getRNG.nextDouble() >= damageRate
|
||||
if (shouldRepair) {
|
||||
// If an item takes a lot of damage at once we don't necessarily want to
|
||||
// make *all* of that damage go away. Instead we scale it according to
|
||||
// our damage probability. This makes sure we don't discard massive
|
||||
// damage spikes (e.g. on axes when using the TreeCapitator mod or such).
|
||||
math.ceil((high - low) * (1 - damageRate)).toInt
|
||||
}
|
||||
else 0
|
||||
}
|
||||
if (Mods.UniversalElectricity.isAvailable && UniversalElectricity.isEnergyItem(stack)) {
|
||||
UniversalElectricity.chargeItem(stack, repair(UniversalElectricity.getEnergyInItem(oldStack), UniversalElectricity.getEnergyInItem(stack)))
|
||||
}
|
||||
else if (stack.isItemStackDamageable) {
|
||||
stack.setItemDamage(stack.getItemDamage - repair(stack.getItemDamage, oldStack.getItemDamage))
|
||||
val damageRate = new RobotUsedTool.ComputeDamageRate(robot, stack, oldStack, Settings.get.itemDamageRate)
|
||||
MinecraftForge.EVENT_BUS.post(damageRate)
|
||||
if (damageRate.getDamageRate < 1) {
|
||||
MinecraftForge.EVENT_BUS.post(new RobotUsedTool.ApplyDamageRate(robot, stack, oldStack, damageRate.getDamageRate))
|
||||
}
|
||||
}
|
||||
|
||||
private def tryPlaceBlockWhileHandlingFunnySpecialCases(stack: ItemStack, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float) = {
|
||||
stack != null && stack.stackSize > 0 && {
|
||||
val fakeEyeHeight = if (rotationPitch < 0 && isSomeKindOfPiston(stack)) 1.82 else 0
|
||||
setPosition(posX, posY - fakeEyeHeight, posZ)
|
||||
val didPlace = stack.tryPlaceItemIntoWorld(this, world, x, y, z, side, hitX, hitY, hitZ)
|
||||
setPosition(posX, posY + fakeEyeHeight, posZ)
|
||||
if (didPlace) {
|
||||
robot.addXp(Settings.get.robotActionXp)
|
||||
val event = new RobotPlaceBlockEvent.Pre(robot, stack, world, x, y, z)
|
||||
MinecraftForge.EVENT_BUS.post(event)
|
||||
if (event.isCanceled) false
|
||||
else {
|
||||
val fakeEyeHeight = if (rotationPitch < 0 && isSomeKindOfPiston(stack)) 1.82 else 0
|
||||
setPosition(posX, posY - fakeEyeHeight, posZ)
|
||||
val didPlace = stack.tryPlaceItemIntoWorld(this, world, x, y, z, side, hitX, hitY, hitZ)
|
||||
setPosition(posX, posY + fakeEyeHeight, posZ)
|
||||
if (didPlace) {
|
||||
MinecraftForge.EVENT_BUS.post(new RobotPlaceBlockEvent.Post(robot, stack, world, x, y, z))
|
||||
}
|
||||
didPlace
|
||||
}
|
||||
didPlace
|
||||
}
|
||||
}
|
||||
|
||||
@ -409,7 +407,7 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Sett
|
||||
if (Settings.get.robotExhaustionCost > 0) {
|
||||
robot.bot.node.changeBuffer(-Settings.get.robotExhaustionCost * amount)
|
||||
}
|
||||
robot.addXp(Settings.get.robotExhaustionXpRate * amount)
|
||||
MinecraftForge.EVENT_BUS.post(new RobotExhaustionEvent(robot, amount))
|
||||
}
|
||||
|
||||
override def openGui(mod: AnyRef, modGuiId: Int, world: World, x: Int, y: Int, z: Int) {}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package li.cil.oc.server.component.robot
|
||||
|
||||
import li.cil.oc.{Items, api, OpenComputers, Settings}
|
||||
import li.cil.oc.{api, OpenComputers, Settings}
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||
@ -22,7 +22,7 @@ import li.cil.oc.common.component.ManagedComponent
|
||||
class Robot(val robot: tileentity.Robot) extends ManagedComponent {
|
||||
val node = api.Network.newNode(this, Visibility.Neighbors).
|
||||
withComponent("robot").
|
||||
withConnector(Settings.get.bufferRobot + 30 * Settings.get.bufferPerLevel).
|
||||
withConnector(Settings.get.bufferRobot).
|
||||
create()
|
||||
|
||||
def actualSlot(n: Int) = robot.actualSlot(n)
|
||||
@ -48,13 +48,6 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent {
|
||||
|
||||
def hasAngelUpgrade = api.Items.get(robot.getStackInSlot(3)) == api.Items.get("angelUpgrade")
|
||||
|
||||
@Callback(direct = true)
|
||||
def level(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val xpNeeded = robot.xpForNextLevel - robot.xpForLevel(robot.level)
|
||||
val xpProgress = math.max(0, robot.xp - robot.xpForLevel(robot.level))
|
||||
result(robot.level + xpProgress / xpNeeded)
|
||||
}
|
||||
|
||||
@Callback
|
||||
def name(context: Context, args: Arguments): Array[AnyRef] = result(robot.name)
|
||||
|
||||
@ -521,7 +514,6 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent {
|
||||
}
|
||||
else if (robot.move(direction)) {
|
||||
context.pause(Settings.get.moveDelay)
|
||||
robot.addXp(Settings.get.robotExhaustionXpRate * 0.01)
|
||||
result(true)
|
||||
}
|
||||
else {
|
||||
|
@ -0,0 +1,20 @@
|
||||
package li.cil.oc.server.driver.item
|
||||
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.driver.Slot
|
||||
import li.cil.oc.api.machine.Robot
|
||||
import li.cil.oc.server.component
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
|
||||
object UpgradeExperience extends Item {
|
||||
override def worksWith(stack: ItemStack) = isOneOf(stack, api.Items.get("experienceUpgrade"))
|
||||
|
||||
override def createEnvironment(stack: ItemStack, container: component.Container) =
|
||||
container.tileEntity match {
|
||||
case Some(robot: Robot) => new component.UpgradeExperience()
|
||||
case _ => null
|
||||
}
|
||||
|
||||
override def slot(stack: ItemStack) = Slot.Upgrade
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user