mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-17 11:15:12 -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;
|
package li.cil.oc.api.machine;
|
||||||
|
|
||||||
import li.cil.oc.api.Rotatable;
|
import li.cil.oc.api.Rotatable;
|
||||||
|
import li.cil.oc.api.network.Environment;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface allows interaction with robots.
|
* 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
|
* 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
|
* case, the robot in question is the tile entity passed to item driver when
|
||||||
* asked to create the component's environment.
|
* 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 {
|
public interface Robot extends Rotatable {
|
||||||
/**
|
/**
|
||||||
@ -17,18 +31,59 @@ public interface Robot extends Rotatable {
|
|||||||
* <p/>
|
* <p/>
|
||||||
* This will automatically be positioned and rotated to represent the
|
* This will automatically be positioned and rotated to represent the
|
||||||
* robot's current position and rotation in the world. Use this to trigger
|
* robot's current position and rotation in the world. Use this to trigger
|
||||||
* events involving the robot that require a player entity, and for
|
* events involving the robot that require a player entity, and for more
|
||||||
* interacting with the robots' inventory.
|
* in-depth interaction 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.
|
|
||||||
*
|
*
|
||||||
* @return the fake player for the robot.
|
* @return the fake player for the robot.
|
||||||
*/
|
*/
|
||||||
EntityPlayer player();
|
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.
|
* Gets the index of the currently selected slot in the robot's inventory.
|
||||||
*
|
*
|
||||||
|
@ -123,6 +123,11 @@ craftingUpgrade {
|
|||||||
["oc:circuitChip1", workbench, "oc:circuitChip1"]
|
["oc:circuitChip1", workbench, "oc:circuitChip1"]
|
||||||
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
|
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
|
||||||
}
|
}
|
||||||
|
experienceUpgrade {
|
||||||
|
input: [[ingotIron, "", ingotIron]
|
||||||
|
["oc:circuitChip1", expBottle, "oc:circuitChip1"]
|
||||||
|
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
|
||||||
|
}
|
||||||
generatorUpgrade {
|
generatorUpgrade {
|
||||||
input: [[ingotIron, "", ingotIron]
|
input: [[ingotIron, "", ingotIron]
|
||||||
["oc:circuitChip1", craftingPiston, "oc:circuitChip1"]
|
["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
|
// v1.3.0
|
||||||
Recipes.addItemDelegate(new item.LinkedCard(multi), "linkedCard", "oc:linkedCard")
|
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.RobotEquippedUpgradeChange => onRobotEquippedUpgradeChange(p)
|
||||||
case PacketType.RobotMove => onRobotMove(p)
|
case PacketType.RobotMove => onRobotMove(p)
|
||||||
case PacketType.RobotSelectedSlotChange => onRobotSelectedSlotChange(p)
|
case PacketType.RobotSelectedSlotChange => onRobotSelectedSlotChange(p)
|
||||||
case PacketType.RobotXp => onRobotXp(p)
|
|
||||||
case PacketType.RotatableState => onRotatableState(p)
|
case PacketType.RotatableState => onRotatableState(p)
|
||||||
case PacketType.RouterActivity => onRouterActivity(p)
|
case PacketType.RouterActivity => onRouterActivity(p)
|
||||||
case PacketType.TextBufferColorChange => onTextBufferColorChange(p)
|
case PacketType.TextBufferColorChange => onTextBufferColorChange(p)
|
||||||
@ -230,14 +229,6 @@ class PacketHandler extends CommonPacketHandler {
|
|||||||
case _ => // Invalid packet.
|
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) =
|
def onRotatableState(p: PacketParser) =
|
||||||
p.readTileEntity[Rotatable]() match {
|
p.readTileEntity[Rotatable]() match {
|
||||||
case Some(t) =>
|
case Some(t) =>
|
||||||
|
@ -2,6 +2,7 @@ package li.cil.oc.client.renderer.tileentity
|
|||||||
|
|
||||||
import com.google.common.base.Strings
|
import com.google.common.base.Strings
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
import li.cil.oc.api.event.RobotRenderEvent
|
||||||
import li.cil.oc.client.Textures
|
import li.cil.oc.client.Textures
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.util.RenderState
|
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.IItemRenderer.ItemRenderType._
|
import net.minecraftforge.client.IItemRenderer.ItemRenderType._
|
||||||
import net.minecraftforge.client.MinecraftForgeClient
|
import net.minecraftforge.client.MinecraftForgeClient
|
||||||
import net.minecraftforge.common.ForgeDirection
|
import net.minecraftforge.common.{MinecraftForge, ForgeDirection}
|
||||||
import org.lwjgl.opengl.{GL12, GL11}
|
import org.lwjgl.opengl.{GL12, GL11}
|
||||||
|
|
||||||
object RobotRenderer extends TileEntitySpecialRenderer {
|
object RobotRenderer extends TileEntitySpecialRenderer {
|
||||||
private val displayList = GLAllocation.generateDisplayLists(2)
|
private val displayList = GLAllocation.generateDisplayLists(2)
|
||||||
|
|
||||||
|
private val mountPoints = Array.fill(7)(new RobotRenderEvent.MountPoint())
|
||||||
|
|
||||||
private val gap = 1.0f / 28.0f
|
private val gap = 1.0f / 28.0f
|
||||||
private val gt = 0.5f + gap
|
private val gt = 0.5f + gap
|
||||||
private val gb = 0.5f - gap
|
private val gb = 0.5f - gap
|
||||||
@ -104,7 +107,64 @@ object RobotRenderer extends TileEntitySpecialRenderer {
|
|||||||
|
|
||||||
compileList()
|
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 size = 0.3f
|
||||||
val l = 0.5f - size
|
val l = 0.5f - size
|
||||||
val h = 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)
|
(0.25f - vStep, 0.25f + vStep, 0.75f - vStep, 0.75f + vStep)
|
||||||
}
|
}
|
||||||
|
|
||||||
bindTexture(Textures.blockRobot)
|
resetMountPoints()
|
||||||
if (level > 19) {
|
val event = new RobotRenderEvent(robot, mountPoints)
|
||||||
GL11.glColor3f(0.4f, 1, 1)
|
MinecraftForge.EVENT_BUS.post(event)
|
||||||
}
|
if (!event.isCanceled) {
|
||||||
else if (level > 9) {
|
bindTexture(Textures.blockRobot)
|
||||||
GL11.glColor3f(1, 1, 0.4f)
|
if (!isRunning) {
|
||||||
}
|
GL11.glTranslatef(0, -2 * gap, 0)
|
||||||
else {
|
}
|
||||||
GL11.glColor3f(0.5f, 0.5f, 0.5f)
|
GL11.glCallList(displayList)
|
||||||
}
|
if (!isRunning) {
|
||||||
if (!isRunning) {
|
GL11.glTranslatef(0, 2 * gap, 0)
|
||||||
GL11.glTranslatef(0, -2 * gap, 0)
|
}
|
||||||
}
|
GL11.glCallList(displayList + 1)
|
||||||
GL11.glCallList(displayList)
|
GL11.glColor3f(1, 1, 1)
|
||||||
if (!isRunning) {
|
|
||||||
GL11.glTranslatef(0, 2 * gap, 0)
|
|
||||||
}
|
|
||||||
GL11.glCallList(displayList + 1)
|
|
||||||
GL11.glColor3f(1, 1, 1)
|
|
||||||
|
|
||||||
if (MinecraftForgeClient.getRenderPass == 0) {
|
if (isRunning) {
|
||||||
RenderState.disableLighting()
|
if (MinecraftForgeClient.getRenderPass == 0) {
|
||||||
}
|
RenderState.disableLighting()
|
||||||
|
}
|
||||||
|
|
||||||
if (isRunning) {
|
val t = Tessellator.instance
|
||||||
val t = Tessellator.instance
|
t.startDrawingQuads()
|
||||||
t.startDrawingQuads()
|
t.addVertexWithUV(l, gt, l, u0, v0)
|
||||||
t.addVertexWithUV(l, gt, l, u0, v0)
|
t.addVertexWithUV(l, gb, l, u0, v1)
|
||||||
t.addVertexWithUV(l, gb, l, u0, v1)
|
t.addVertexWithUV(l, gb, h, u1, v1)
|
||||||
t.addVertexWithUV(l, gb, h, u1, v1)
|
t.addVertexWithUV(l, gt, h, u1, v0)
|
||||||
t.addVertexWithUV(l, gt, h, u1, v0)
|
|
||||||
|
|
||||||
t.addVertexWithUV(l, gt, h, u0, v0)
|
t.addVertexWithUV(l, gt, h, u0, v0)
|
||||||
t.addVertexWithUV(l, gb, h, u0, v1)
|
t.addVertexWithUV(l, gb, h, u0, v1)
|
||||||
t.addVertexWithUV(h, gb, h, u1, v1)
|
t.addVertexWithUV(h, gb, h, u1, v1)
|
||||||
t.addVertexWithUV(h, gt, h, u1, v0)
|
t.addVertexWithUV(h, gt, h, u1, v0)
|
||||||
|
|
||||||
t.addVertexWithUV(h, gt, h, u0, v0)
|
t.addVertexWithUV(h, gt, h, u0, v0)
|
||||||
t.addVertexWithUV(h, gb, h, u0, v1)
|
t.addVertexWithUV(h, gb, h, u0, v1)
|
||||||
t.addVertexWithUV(h, gb, l, u1, v1)
|
t.addVertexWithUV(h, gb, l, u1, v1)
|
||||||
t.addVertexWithUV(h, gt, l, u1, v0)
|
t.addVertexWithUV(h, gt, l, u1, v0)
|
||||||
|
|
||||||
t.addVertexWithUV(h, gt, l, u0, v0)
|
t.addVertexWithUV(h, gt, l, u0, v0)
|
||||||
t.addVertexWithUV(h, gb, l, u0, v1)
|
t.addVertexWithUV(h, gb, l, u0, v1)
|
||||||
t.addVertexWithUV(l, gb, l, u1, v1)
|
t.addVertexWithUV(l, gb, l, u1, v1)
|
||||||
t.addVertexWithUV(l, gt, l, u1, v0)
|
t.addVertexWithUV(l, gt, l, u1, v0)
|
||||||
t.draw()
|
t.draw()
|
||||||
}
|
|
||||||
|
|
||||||
if (MinecraftForgeClient.getRenderPass == 0) {
|
if (MinecraftForgeClient.getRenderPass == 0) {
|
||||||
RenderState.enableLighting()
|
RenderState.enableLighting()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +280,7 @@ object RobotRenderer extends TileEntitySpecialRenderer {
|
|||||||
|
|
||||||
if (MinecraftForgeClient.getRenderPass == 0) {
|
if (MinecraftForgeClient.getRenderPass == 0) {
|
||||||
val offset = timeJitter + worldTime / 20.0
|
val offset = timeJitter + worldTime / 20.0
|
||||||
renderChassis(robot.isRunning, robot.level, offset)
|
renderChassis(robot, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
robot.equippedItem match {
|
robot.equippedItem match {
|
||||||
|
@ -22,7 +22,6 @@ object PacketType extends Enumeration {
|
|||||||
RobotEquippedUpgradeChange,
|
RobotEquippedUpgradeChange,
|
||||||
RobotMove,
|
RobotMove,
|
||||||
RobotSelectedSlotChange,
|
RobotSelectedSlotChange,
|
||||||
RobotXp,
|
|
||||||
RotatableState,
|
RotatableState,
|
||||||
RouterActivity,
|
RouterActivity,
|
||||||
TextBufferColorChange,
|
TextBufferColorChange,
|
||||||
|
@ -21,6 +21,7 @@ import net.minecraft.item.{Item, ItemStack}
|
|||||||
import net.minecraft.block.Block
|
import net.minecraft.block.Block
|
||||||
import net.minecraftforge.oredict.OreDictionary
|
import net.minecraftforge.oredict.OreDictionary
|
||||||
import scala.collection.convert.WrapAsScala._
|
import scala.collection.convert.WrapAsScala._
|
||||||
|
import li.cil.oc.common.event.{ExperienceUpgradeHandler, UniversalElectricityToolHandler, RobotCommonHandler}
|
||||||
|
|
||||||
class Proxy {
|
class Proxy {
|
||||||
def preInit(e: FMLPreInitializationEvent) {
|
def preInit(e: FMLPreInitializationEvent) {
|
||||||
@ -77,6 +78,7 @@ class Proxy {
|
|||||||
api.Driver.add(driver.item.RedstoneCard)
|
api.Driver.add(driver.item.RedstoneCard)
|
||||||
api.Driver.add(driver.item.Screen)
|
api.Driver.add(driver.item.Screen)
|
||||||
api.Driver.add(driver.item.UpgradeCrafting)
|
api.Driver.add(driver.item.UpgradeCrafting)
|
||||||
|
api.Driver.add(driver.item.UpgradeExperience)
|
||||||
api.Driver.add(driver.item.UpgradeGenerator)
|
api.Driver.add(driver.item.UpgradeGenerator)
|
||||||
api.Driver.add(driver.item.UpgradeNavigation)
|
api.Driver.add(driver.item.UpgradeNavigation)
|
||||||
api.Driver.add(driver.item.UpgradeSign)
|
api.Driver.add(driver.item.UpgradeSign)
|
||||||
@ -94,6 +96,12 @@ class Proxy {
|
|||||||
api.Driver.add(driver.converter.FluidTankInfo)
|
api.Driver.add(driver.converter.FluidTankInfo)
|
||||||
api.Driver.add(driver.converter.ItemStack)
|
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()
|
Recipes.init()
|
||||||
GameRegistry.registerCraftingHandler(CraftingHandler)
|
GameRegistry.registerCraftingHandler(CraftingHandler)
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ class RobotProxy(val parent: SpecialDelegator) extends RedstoneAware with Specia
|
|||||||
case proxy: tileentity.RobotProxy =>
|
case proxy: tileentity.RobotProxy =>
|
||||||
val robot = proxy.robot
|
val robot = proxy.robot
|
||||||
if (robot.player == player) return false
|
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())
|
parent.dropBlockAsItem(world, x, y, z, robot.createItemStack())
|
||||||
}
|
}
|
||||||
if (Blocks.blockSpecial.subBlock(world, robot.moveFromX, robot.moveFromY, robot.moveFromZ).exists(_ == Blocks.robotAfterimage)) {
|
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._
|
||||||
import li.cil.oc.api.Driver
|
import li.cil.oc.api.Driver
|
||||||
import li.cil.oc.api.driver.Slot
|
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.api.network._
|
||||||
import li.cil.oc.client.gui
|
import li.cil.oc.client.gui
|
||||||
import li.cil.oc.common.block.Delegator
|
import li.cil.oc.common.block.Delegator
|
||||||
@ -18,7 +19,7 @@ import net.minecraft.inventory.ISidedInventory
|
|||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
import net.minecraft.util.ChatMessageComponent
|
import net.minecraft.util.ChatMessageComponent
|
||||||
import net.minecraftforge.common.ForgeDirection
|
import net.minecraftforge.common.{MinecraftForge, ForgeDirection}
|
||||||
import net.minecraftforge.fluids.{BlockFluidBase, FluidRegistry}
|
import net.minecraftforge.fluids.{BlockFluidBase, FluidRegistry}
|
||||||
import scala.io.Source
|
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
|
override def dynamicComponentCapacity = 3
|
||||||
//to cast their owner to it (to allow interacting with their owning robot).
|
|
||||||
|
override def componentCapacity = 3
|
||||||
|
|
||||||
|
override def inventorySize = getSizeInventory
|
||||||
|
|
||||||
|
override def getComponentInSlot(index: Int) = components(index).orNull
|
||||||
|
|
||||||
var selectedSlot = actualSlot(0)
|
var selectedSlot = actualSlot(0)
|
||||||
|
|
||||||
@ -92,16 +98,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
|||||||
|
|
||||||
var tag: NBTTagCompound = _
|
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 globalBuffer, globalBufferSize = 0.0
|
||||||
|
|
||||||
var equippedItem: Option[ItemStack] = None
|
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)
|
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
|
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))
|
Settings.namespace + "gui.Analyzer.RobotOwner", owner))
|
||||||
player.sendChatToPlayer(ChatMessageComponent.createFromTranslationWithSubstitutions(
|
player.sendChatToPlayer(ChatMessageComponent.createFromTranslationWithSubstitutions(
|
||||||
Settings.namespace + "gui.Analyzer.RobotName", player_.getCommandSenderName))
|
Settings.namespace + "gui.Analyzer.RobotName", player_.getCommandSenderName))
|
||||||
player.sendChatToPlayer(ChatMessageComponent.createFromTranslationWithSubstitutions(
|
MinecraftForge.EVENT_BUS.post(new RobotAnalyzeEvent(this, player))
|
||||||
Settings.namespace + "gui.Analyzer.RobotXp", xp.formatted("%.2f"), level: Integer))
|
|
||||||
super.onAnalyze(player, side, hitX, hitY, hitZ)
|
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)) {
|
if (!world.blockExists(nx, ny, nz)) {
|
||||||
return false // Don't fall off the earth.
|
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 blockId = world.getBlockId(nx, ny, nz)
|
||||||
val metadata = world.getBlockMetadata(nx, ny, nz)
|
val metadata = world.getBlockMetadata(nx, ny, nz)
|
||||||
try {
|
try {
|
||||||
@ -193,6 +176,7 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
|||||||
if (isServer) {
|
if (isServer) {
|
||||||
ServerPacketSender.sendRobotMove(this, ox, oy, oz, direction)
|
ServerPacketSender.sendRobotMove(this, ox, oy, oz, direction)
|
||||||
checkRedstoneInputChanged()
|
checkRedstoneInputChanged()
|
||||||
|
MinecraftForge.EVENT_BUS.post(new RobotMoveEvent.Post(this, direction))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// If we broke some replaceable block (like grass) play its break sound.
|
// 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 stack = Blocks.robotProxy.createItemStack()
|
||||||
val tag = if (this.tag != null) this.tag.copy.asInstanceOf[NBTTagCompound] else new NBTTagCompound("tag")
|
val tag = if (this.tag != null) this.tag.copy.asInstanceOf[NBTTagCompound] else new NBTTagCompound("tag")
|
||||||
stack.setTagCompound(tag)
|
stack.setTagCompound(tag)
|
||||||
if (xp > 0) {
|
|
||||||
tag.setDouble(Settings.namespace + "xp", xp)
|
|
||||||
}
|
|
||||||
if (globalBuffer > 1) {
|
if (globalBuffer > 1) {
|
||||||
tag.setInteger(Settings.namespace + "storedEnergy", globalBuffer.toInt)
|
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) {
|
def parseItemStack(stack: ItemStack) {
|
||||||
if (stack.hasTagCompound) {
|
if (stack.hasTagCompound) {
|
||||||
tag = stack.getTagCompound.copy.asInstanceOf[NBTTagCompound]
|
tag = stack.getTagCompound.copy.asInstanceOf[NBTTagCompound]
|
||||||
xp = tag.getDouble(Settings.namespace + "xp")
|
|
||||||
updateXpInfo()
|
|
||||||
bot.node.changeBuffer(stack.getTagCompound.getInteger(Settings.namespace + "storedEnergy"))
|
bot.node.changeBuffer(stack.getTagCompound.getInteger(Settings.namespace + "storedEnergy"))
|
||||||
|
// TODO migration: xp to xp upgrade
|
||||||
|
// xp = tag.getDouble(Settings.namespace + "xp")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tag = new NBTTagCompound("tag")
|
tag = new NBTTagCompound("tag")
|
||||||
@ -323,10 +304,6 @@ class Robot(val isRemote: Boolean) extends traits.Computer with traits.TextBuffe
|
|||||||
globalBuffer = bot.node.globalBuffer
|
globalBuffer = bot.node.globalBuffer
|
||||||
globalBufferSize = bot.node.globalBufferSize
|
globalBufferSize = bot.node.globalBufferSize
|
||||||
updatePowerInformation()
|
updatePowerInformation()
|
||||||
if (xpChanged && world.getWorldInfo.getWorldTotalTime % 200 == 0) {
|
|
||||||
xpChanged = false
|
|
||||||
ServerPacketSender.sendRobotXp(this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (isRunning && isAnimatingMove) {
|
else if (isRunning && isAnimatingMove) {
|
||||||
client.Sound.updatePosition(this)
|
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 Some(item) => player_.getAttributeMap.applyAttributeModifiers(item.getAttributeModifiers)
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
updateXpInfo()
|
|
||||||
|
|
||||||
// Ensure we have a node address, because the proxy needs this to initialize
|
// Ensure we have a node address, because the proxy needs this to initialize
|
||||||
// its own node to the same address ours has.
|
// 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")) {
|
if (nbt.hasKey(Settings.namespace + "tag")) {
|
||||||
tag = nbt.getCompoundTag(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)
|
selectedSlot = nbt.getInteger(Settings.namespace + "selectedSlot") max actualSlot(0) min (getSizeInventory - 1)
|
||||||
animationTicksTotal = nbt.getInteger(Settings.namespace + "animationTicksTotal")
|
animationTicksTotal = nbt.getInteger(Settings.namespace + "animationTicksTotal")
|
||||||
animationTicksLeft = nbt.getInteger(Settings.namespace + "animationTicksLeft")
|
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")
|
swingingTool = nbt.getBoolean(Settings.namespace + "swingingTool")
|
||||||
turnAxis = nbt.getByte(Settings.namespace + "turnAxis")
|
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).
|
// 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) {
|
if (tag != null) {
|
||||||
nbt.setCompoundTag(Settings.namespace + "tag", tag)
|
nbt.setCompoundTag(Settings.namespace + "tag", tag)
|
||||||
}
|
}
|
||||||
nbt.setDouble(Settings.namespace + "xp", xp)
|
|
||||||
nbt.setInteger(Settings.namespace + "selectedSlot", selectedSlot)
|
nbt.setInteger(Settings.namespace + "selectedSlot", selectedSlot)
|
||||||
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
||||||
nbt.setInteger(Settings.namespace + "animationTicksTotal", animationTicksTotal)
|
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")) {
|
if (nbt.hasKey("upgrade")) {
|
||||||
equippedUpgrade = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("upgrade")))
|
equippedUpgrade = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("upgrade")))
|
||||||
}
|
}
|
||||||
xp = nbt.getDouble(Settings.namespace + "xp")
|
|
||||||
updateXpInfo()
|
|
||||||
animationTicksTotal = nbt.getInteger("animationTicksTotal")
|
animationTicksTotal = nbt.getInteger("animationTicksTotal")
|
||||||
animationTicksLeft = nbt.getInteger("animationTicksLeft")
|
animationTicksLeft = nbt.getInteger("animationTicksLeft")
|
||||||
moveFromX = nbt.getInteger("moveFromX")
|
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.setNewCompoundTag("upgrade", getStackInSlot(3).writeToNBT)
|
||||||
}
|
}
|
||||||
nbt.setDouble(Settings.namespace + "xp", xp)
|
|
||||||
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
||||||
nbt.setInteger("animationTicksTotal", animationTicksTotal)
|
nbt.setInteger("animationTicksTotal", animationTicksTotal)
|
||||||
nbt.setInteger("animationTicksLeft", animationTicksLeft)
|
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 isRunning = robot.isRunning
|
||||||
|
|
||||||
override def setRunning(value: Boolean) = robot.setRunning(value)
|
override def setRunning(value: Boolean) = robot.setRunning(value)
|
||||||
|
|
||||||
override def selectedSlot() = robot.selectedSlot
|
|
||||||
|
|
||||||
override def player() = robot.player()
|
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()
|
override def saveUpgrade() = robot.saveUpgrade()
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
@ -201,15 +201,6 @@ object PacketSender {
|
|||||||
pb.sendToNearbyPlayers(t, 16)
|
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) {
|
def sendRotatableState(t: Rotatable) {
|
||||||
val pb = new PacketBuilder(PacketType.RotatableState)
|
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 cpw.mods.fml.common.ObfuscationReflectionHelper
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
import li.cil.oc.api.event._
|
||||||
import li.cil.oc.common.tileentity
|
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 li.cil.oc.{OpenComputers, Settings}
|
||||||
import net.minecraft.block.{BlockPistonBase, BlockFluid, Block}
|
import net.minecraft.block.{BlockPistonBase, BlockFluid, Block}
|
||||||
import net.minecraft.entity.item.EntityItem
|
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 {
|
callUsingItemInSlot(0, stack => entity match {
|
||||||
case player: EntityPlayer if !canAttackPlayer(player) => // Avoid player damage.
|
case player: EntityPlayer if !canAttackPlayer(player) => // Avoid player damage.
|
||||||
case _ =>
|
case _ =>
|
||||||
super.attackTargetEntityWithCurrentItem(entity)
|
val event = new RobotAttackEntityEvent.Pre(robot, entity)
|
||||||
if (stack != null && entity.isDead) {
|
MinecraftForge.EVENT_BUS.post(event)
|
||||||
robot.addXp(Settings.get.robotActionXp)
|
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 =
|
val breakTime =
|
||||||
if (cobwebOverride) Settings.get.swingDelay
|
if (cobwebOverride) Settings.get.swingDelay
|
||||||
else hardness * 1.5 / strength
|
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
|
// Special handling for Tinkers Construct - tools like the hammers do
|
||||||
// their break logic in onBlockStartBreak but return true to cancel
|
// 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.
|
// check only serves to test whether the block can drop anything at all.
|
||||||
if (block.canHarvestBlock(this, metadata)) {
|
if (block.canHarvestBlock(this, metadata)) {
|
||||||
block.harvestBlock(world, this, x, y, z, 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) {
|
else if (stack != null) {
|
||||||
robot.addXp(Settings.get.robotActionXp)
|
MinecraftForge.EVENT_BUS.post(new RobotBreakBlockEvent.Post(robot, 0))
|
||||||
}
|
}
|
||||||
return adjustedBreakTime
|
return adjustedBreakTime
|
||||||
}
|
}
|
||||||
@ -351,37 +358,28 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Sett
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def tryRepair(stack: ItemStack, oldStack: ItemStack) {
|
private def tryRepair(stack: ItemStack, oldStack: ItemStack) {
|
||||||
def repair(high: Long, low: Long) = {
|
val damageRate = new RobotUsedTool.ComputeDamageRate(robot, stack, oldStack, Settings.get.itemDamageRate)
|
||||||
val needsRepairing = low < high
|
MinecraftForge.EVENT_BUS.post(damageRate)
|
||||||
val damageRate = Settings.get.itemDamageRate * math.max(1 - robot.level * Settings.get.toolEfficiencyPerLevel, 0)
|
if (damageRate.getDamageRate < 1) {
|
||||||
val shouldRepair = needsRepairing && getRNG.nextDouble() >= damageRate
|
MinecraftForge.EVENT_BUS.post(new RobotUsedTool.ApplyDamageRate(robot, stack, oldStack, damageRate.getDamageRate))
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def tryPlaceBlockWhileHandlingFunnySpecialCases(stack: ItemStack, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float) = {
|
private def tryPlaceBlockWhileHandlingFunnySpecialCases(stack: ItemStack, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float) = {
|
||||||
stack != null && stack.stackSize > 0 && {
|
stack != null && stack.stackSize > 0 && {
|
||||||
val fakeEyeHeight = if (rotationPitch < 0 && isSomeKindOfPiston(stack)) 1.82 else 0
|
val event = new RobotPlaceBlockEvent.Pre(robot, stack, world, x, y, z)
|
||||||
setPosition(posX, posY - fakeEyeHeight, posZ)
|
MinecraftForge.EVENT_BUS.post(event)
|
||||||
val didPlace = stack.tryPlaceItemIntoWorld(this, world, x, y, z, side, hitX, hitY, hitZ)
|
if (event.isCanceled) false
|
||||||
setPosition(posX, posY + fakeEyeHeight, posZ)
|
else {
|
||||||
if (didPlace) {
|
val fakeEyeHeight = if (rotationPitch < 0 && isSomeKindOfPiston(stack)) 1.82 else 0
|
||||||
robot.addXp(Settings.get.robotActionXp)
|
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) {
|
if (Settings.get.robotExhaustionCost > 0) {
|
||||||
robot.bot.node.changeBuffer(-Settings.get.robotExhaustionCost * amount)
|
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) {}
|
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
|
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.api.network._
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
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 {
|
class Robot(val robot: tileentity.Robot) extends ManagedComponent {
|
||||||
val node = api.Network.newNode(this, Visibility.Neighbors).
|
val node = api.Network.newNode(this, Visibility.Neighbors).
|
||||||
withComponent("robot").
|
withComponent("robot").
|
||||||
withConnector(Settings.get.bufferRobot + 30 * Settings.get.bufferPerLevel).
|
withConnector(Settings.get.bufferRobot).
|
||||||
create()
|
create()
|
||||||
|
|
||||||
def actualSlot(n: Int) = robot.actualSlot(n)
|
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")
|
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
|
@Callback
|
||||||
def name(context: Context, args: Arguments): Array[AnyRef] = result(robot.name)
|
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)) {
|
else if (robot.move(direction)) {
|
||||||
context.pause(Settings.get.moveDelay)
|
context.pause(Settings.get.moveDelay)
|
||||||
robot.addXp(Settings.get.robotExhaustionXpRate * 0.01)
|
|
||||||
result(true)
|
result(true)
|
||||||
}
|
}
|
||||||
else {
|
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