mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-25 14:05:39 -04:00
Merge branch 'master' of github.com:MightyPirates/OpenComputers into MC1.7
Conflicts: src/main/scala/li/cil/oc/client/renderer/tileentity/HologramRenderer.scala src/main/scala/li/cil/oc/client/renderer/tileentity/ScreenRenderer.scala src/main/scala/li/cil/oc/common/block/Screen.scala
This commit is contained in:
commit
a04732e5f0
@ -360,7 +360,7 @@ end
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function execute(command, env, ...)
|
local function execute(env, command, ...)
|
||||||
checkArg(1, command, "string")
|
checkArg(1, command, "string")
|
||||||
local commands, reason = parseCommands(command)
|
local commands, reason = parseCommands(command)
|
||||||
if not commands then
|
if not commands then
|
||||||
@ -479,39 +479,12 @@ local args, options = shell.parse(...)
|
|||||||
local history = {}
|
local history = {}
|
||||||
|
|
||||||
if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then
|
if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then
|
||||||
-- interactive shell.
|
-- interactive shell. use original shell for input but register self as
|
||||||
while true do
|
-- global SHELL for command execution.
|
||||||
if not term.isAvailable() then -- don't clear unless we lost the term
|
local oldShell = os.getenv("SHELL")
|
||||||
while not term.isAvailable() do
|
os.setenv("SHELL", process.running())
|
||||||
event.pull("term_available")
|
os.execute("/bin/sh")
|
||||||
end
|
os.setenv("SHELL", oldShell)
|
||||||
term.clear()
|
|
||||||
end
|
|
||||||
while term.isAvailable() do
|
|
||||||
local foreground = component.gpu.setForeground(0xFF0000)
|
|
||||||
term.write(expand(os.getenv("PS1") or "$ "))
|
|
||||||
component.gpu.setForeground(foreground)
|
|
||||||
local command = term.read(history)
|
|
||||||
if not command then
|
|
||||||
term.write("exit\n")
|
|
||||||
return -- eof
|
|
||||||
end
|
|
||||||
while #history > 10 do
|
|
||||||
table.remove(history, 1)
|
|
||||||
end
|
|
||||||
command = text.trim(command)
|
|
||||||
if command == "exit" then
|
|
||||||
return
|
|
||||||
elseif command ~= "" then
|
|
||||||
local result, reason = execute(command)
|
|
||||||
if not result then
|
|
||||||
io.stderr:write((tostring(reason) or "unknown error").. "\n")
|
|
||||||
elseif term.getCursor() > 1 then
|
|
||||||
term.write("\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
-- execute command.
|
-- execute command.
|
||||||
local result = table.pack(execute(...))
|
local result = table.pack(execute(...))
|
||||||
|
@ -41,7 +41,7 @@ local function evaluate(value)
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
local function execute(command, ...)
|
local function execute(env, command, ...)
|
||||||
local parts, reason = text.tokenize(command)
|
local parts, reason = text.tokenize(command)
|
||||||
if not parts then
|
if not parts then
|
||||||
return false, reason
|
return false, reason
|
||||||
@ -119,7 +119,7 @@ if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then
|
|||||||
if command == "exit" then
|
if command == "exit" then
|
||||||
return
|
return
|
||||||
elseif command ~= "" then
|
elseif command ~= "" then
|
||||||
local result, reason = execute(command)
|
local result, reason = os.execute(command)
|
||||||
if term.getCursor() > 1 then
|
if term.getCursor() > 1 then
|
||||||
term.write("\n")
|
term.write("\n")
|
||||||
end
|
end
|
||||||
|
@ -5,6 +5,23 @@ local unicode = require("unicode")
|
|||||||
local shell = {}
|
local shell = {}
|
||||||
local aliases = {}
|
local aliases = {}
|
||||||
|
|
||||||
|
-- Cache loaded shells for command execution. This puts the requirement on
|
||||||
|
-- shells that they do not keep a global state, since they may be called
|
||||||
|
-- multiple times, but reduces memory usage a lot.
|
||||||
|
local shells = setmetatable({}, {__mode="v"})
|
||||||
|
|
||||||
|
local function getShell()
|
||||||
|
local shellName = shell.resolve(os.getenv("SHELL"), "lua")
|
||||||
|
if shells[shellName] then
|
||||||
|
return shells[shellName]
|
||||||
|
end
|
||||||
|
local sh, reason = loadfile(shellName, "t", env)
|
||||||
|
if sh then
|
||||||
|
shells[shellName] = sh
|
||||||
|
end
|
||||||
|
return sh, reason
|
||||||
|
end
|
||||||
|
|
||||||
local function findFile(name, ext)
|
local function findFile(name, ext)
|
||||||
checkArg(1, name, "string")
|
checkArg(1, name, "string")
|
||||||
local function findIn(dir)
|
local function findIn(dir)
|
||||||
@ -129,11 +146,11 @@ function shell.resolve(path, ext)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function shell.execute(command, env, ...)
|
function shell.execute(command, env, ...)
|
||||||
local sh, reason = loadfile(shell.resolve(os.getenv("SHELL"), "lua"), "t", env)
|
local sh, reason = getShell()
|
||||||
if not sh then
|
if not sh then
|
||||||
return false, reason
|
return false, reason
|
||||||
end
|
end
|
||||||
local result = table.pack(pcall(sh, command, ...))
|
local result = table.pack(pcall(sh, env, command, ...))
|
||||||
if not result[1] and type(result[2]) == "table" and result[2].reason == "terminated" then
|
if not result[1] and type(result[2]) == "table" and result[2].reason == "terminated" then
|
||||||
if result[2].code then
|
if result[2].code then
|
||||||
return true
|
return true
|
||||||
|
@ -630,10 +630,20 @@ local function main()
|
|||||||
|
|
||||||
-- After memory footprint to avoid init.lua bumping the baseline.
|
-- After memory footprint to avoid init.lua bumping the baseline.
|
||||||
local co, args = bootstrap()
|
local co, args = bootstrap()
|
||||||
|
local forceGC = 10
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
deadline = computer.realTime() + system.timeout()
|
deadline = computer.realTime() + system.timeout()
|
||||||
hitDeadline = false
|
hitDeadline = false
|
||||||
|
|
||||||
|
-- NOTE: since this is run in an executor thread and we enforce timeouts
|
||||||
|
-- in user-defined garbage collector callbacks this should be safe.
|
||||||
|
forceGC = forceGC - 1
|
||||||
|
if forceGC < 1 then
|
||||||
|
collectgarbage("collect")
|
||||||
|
forceGC = 10
|
||||||
|
end
|
||||||
|
|
||||||
debug.sethook(co, checkDeadline, "", hookInterval)
|
debug.sethook(co, checkDeadline, "", hookInterval)
|
||||||
local result = table.pack(coroutine.resume(co, table.unpack(args, 1, args.n)))
|
local result = table.pack(coroutine.resume(co, table.unpack(args, 1, args.n)))
|
||||||
if not result[1] then
|
if not result[1] then
|
||||||
|
@ -15,15 +15,15 @@ import org.lwjgl.BufferUtils
|
|||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import java.nio.IntBuffer
|
import java.nio.IntBuffer
|
||||||
|
|
||||||
object HologramRenderer extends TileEntitySpecialRenderer with Callable[(Int, IntBuffer)] with RemovalListener[TileEntity, (Int, IntBuffer)] {
|
object HologramRenderer extends TileEntitySpecialRenderer with Callable[Int] with RemovalListener[TileEntity, Int] {
|
||||||
private val random = new Random()
|
private val random = new Random()
|
||||||
|
|
||||||
/** We cache the VBOs for the projectors we render for performance. */
|
/** We cache the VBOs for the projectors we render for performance. */
|
||||||
private val cache = com.google.common.cache.CacheBuilder.newBuilder().
|
private val cache = com.google.common.cache.CacheBuilder.newBuilder().
|
||||||
expireAfterAccess(10, TimeUnit.SECONDS).
|
expireAfterAccess(5, TimeUnit.SECONDS).
|
||||||
removalListener(this).
|
removalListener(this).
|
||||||
asInstanceOf[CacheBuilder[Hologram, (Int, IntBuffer)]].
|
asInstanceOf[CacheBuilder[Hologram, Int]].
|
||||||
build[Hologram, (Int, IntBuffer)]()
|
build[Hologram, Int]()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common for all holograms. Holds the vertex positions, texture
|
* Common for all holograms. Holds the vertex positions, texture
|
||||||
@ -33,9 +33,20 @@ object HologramRenderer extends TileEntitySpecialRenderer with Callable[(Int, In
|
|||||||
* same dimensions (in voxels). If we ever need holograms of different
|
* same dimensions (in voxels). If we ever need holograms of different
|
||||||
* sizes we could probably just fake that by making the outer layers
|
* sizes we could probably just fake that by making the outer layers
|
||||||
* immutable (i.e. always empty).
|
* immutable (i.e. always empty).
|
||||||
|
*
|
||||||
|
* NOTE: It already takes up 47.25 MiB of video memory and increasing
|
||||||
|
* hologram size to, for example, 64*64*64 will result in 168 MiB.
|
||||||
*/
|
*/
|
||||||
private var commonBuffer = 0
|
private var commonBuffer = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Also common for all holograms. Temporary buffer used to upload
|
||||||
|
* hologram data to GPU. First half stores colors for each vertex
|
||||||
|
* (0xAABBGGRR Int, alpha is used for alignment only) and second
|
||||||
|
* half stores (Int) indices of vertices that should be drawn.
|
||||||
|
*/
|
||||||
|
private var dataBuffer: IntBuffer = null
|
||||||
|
|
||||||
/** Used to pass the current screen along to call(). */
|
/** Used to pass the current screen along to call(). */
|
||||||
private var hologram: Hologram = null
|
private var hologram: Hologram = null
|
||||||
|
|
||||||
@ -92,13 +103,13 @@ object HologramRenderer extends TileEntitySpecialRenderer with Callable[(Int, In
|
|||||||
// When we don't do this the hologram will look different from different
|
// When we don't do this the hologram will look different from different
|
||||||
// angles (because some faces will shine through sometimes and sometimes
|
// angles (because some faces will shine through sometimes and sometimes
|
||||||
// they won't), so a more... consistent look is desirable.
|
// they won't), so a more... consistent look is desirable.
|
||||||
val (glBuffer, dataBuffer) = cache.get(hologram, this)
|
val glBuffer = cache.get(hologram, this)
|
||||||
GL11.glColorMask(false, false, false, false)
|
GL11.glColorMask(false, false, false, false)
|
||||||
GL11.glDepthMask(true)
|
GL11.glDepthMask(true)
|
||||||
draw(glBuffer, dataBuffer)
|
draw(glBuffer)
|
||||||
GL11.glColorMask(true, true, true, true)
|
GL11.glColorMask(true, true, true, true)
|
||||||
GL11.glDepthFunc(GL11.GL_EQUAL)
|
GL11.glDepthFunc(GL11.GL_EQUAL)
|
||||||
draw(glBuffer, dataBuffer)
|
draw(glBuffer)
|
||||||
|
|
||||||
GL11.glPopMatrix()
|
GL11.glPopMatrix()
|
||||||
GL11.glPopAttrib()
|
GL11.glPopAttrib()
|
||||||
@ -107,15 +118,17 @@ object HologramRenderer extends TileEntitySpecialRenderer with Callable[(Int, In
|
|||||||
RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving")
|
RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving")
|
||||||
}
|
}
|
||||||
|
|
||||||
def draw(glBuffer: Int, dataBuffer: IntBuffer) {
|
def draw(glBuffer: Int) {
|
||||||
initialize()
|
initialize()
|
||||||
validate(glBuffer, dataBuffer)
|
validate(glBuffer)
|
||||||
publish(glBuffer)
|
publish(glBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def initialize() {
|
private def initialize() {
|
||||||
// First run only, create structure information.
|
// First run only, create structure information.
|
||||||
if (commonBuffer == 0) {
|
if (commonBuffer == 0) {
|
||||||
|
dataBuffer = BufferUtils.createIntBuffer(hologram.width * hologram.width * hologram.height * 6 * 4 * 2)
|
||||||
|
|
||||||
commonBuffer = GL15.glGenBuffers()
|
commonBuffer = GL15.glGenBuffers()
|
||||||
|
|
||||||
val data = BufferUtils.createFloatBuffer(hologram.width * hologram.width * hologram.height * 24 * (2 + 3 + 3))
|
val data = BufferUtils.createFloatBuffer(hologram.width * hologram.width * hologram.height * 24 * (2 + 3 + 3))
|
||||||
@ -188,7 +201,7 @@ object HologramRenderer extends TileEntitySpecialRenderer with Callable[(Int, In
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def validate(glBuffer: Int, dataBuffer: IntBuffer) {
|
private def validate(glBuffer: Int) {
|
||||||
// Refresh indexes when the hologram's data changed.
|
// Refresh indexes when the hologram's data changed.
|
||||||
if (hologram.dirty) {
|
if (hologram.dirty) {
|
||||||
def value(hx: Int, hy: Int, hz: Int) = if (hx >= 0 && hy >= 0 && hz >= 0 && hx < hologram.width && hy < hologram.height && hz < hologram.width) hologram.getColor(hx, hy, hz) else 0
|
def value(hx: Int, hy: Int, hz: Int) = if (hx >= 0 && hy >= 0 && hz >= 0 && hx < hologram.width && hy < hologram.height && hz < hologram.width) hologram.getColor(hx, hy, hz) else 0
|
||||||
@ -262,12 +275,21 @@ object HologramRenderer extends TileEntitySpecialRenderer with Callable[(Int, In
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Important! OpenGL will start reading from the current buffer position.
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, glBuffer)
|
||||||
dataBuffer.rewind()
|
if (hologram.visibleQuads > 0) {
|
||||||
|
// Flip the buffer to only fill in as much data as necessary.
|
||||||
|
dataBuffer.flip()
|
||||||
|
|
||||||
// This buffer can be updated quite frequently, so dynamic seems sensible.
|
// This buffer can be updated quite frequently, so dynamic seems sensible.
|
||||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, glBuffer)
|
|
||||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, dataBuffer, GL15.GL_DYNAMIC_DRAW)
|
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, dataBuffer, GL15.GL_DYNAMIC_DRAW)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Empty hologram.
|
||||||
|
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, 0L, GL15.GL_DYNAMIC_DRAW)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset for the next operation.
|
||||||
|
dataBuffer.clear()
|
||||||
|
|
||||||
hologram.dirty = false
|
hologram.dirty = false
|
||||||
}
|
}
|
||||||
@ -294,16 +316,15 @@ object HologramRenderer extends TileEntitySpecialRenderer with Callable[(Int, In
|
|||||||
|
|
||||||
def call = {
|
def call = {
|
||||||
val glBuffer = GL15.glGenBuffers()
|
val glBuffer = GL15.glGenBuffers()
|
||||||
val dataBuffer = BufferUtils.createIntBuffer(hologram.width * hologram.width * hologram.height * 6 * 4 * 2)
|
|
||||||
|
|
||||||
// Force re-indexing.
|
// Force re-indexing.
|
||||||
hologram.dirty = true
|
hologram.dirty = true
|
||||||
|
|
||||||
(glBuffer, dataBuffer)
|
glBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
def onRemoval(e: RemovalNotification[TileEntity, (Int, IntBuffer)]) {
|
def onRemoval(e: RemovalNotification[TileEntity, Int]) {
|
||||||
val (glBuffer, dataBuffer) = e.getValue
|
val glBuffer = e.getValue
|
||||||
GL15.glDeleteBuffers(glBuffer)
|
GL15.glDeleteBuffers(glBuffer)
|
||||||
dataBuffer.clear()
|
dataBuffer.clear()
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,8 @@ object ScreenRenderer extends TileEntitySpecialRenderer {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderState.checkError(getClass.getName + ".renderTileEntityAt: checks")
|
||||||
|
|
||||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
|
||||||
|
|
||||||
RenderState.disableLighting()
|
RenderState.disableLighting()
|
||||||
@ -55,14 +57,20 @@ object ScreenRenderer extends TileEntitySpecialRenderer {
|
|||||||
|
|
||||||
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
|
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
|
||||||
|
|
||||||
|
RenderState.checkError(getClass.getName + ".renderTileEntityAt: setup")
|
||||||
|
|
||||||
drawOverlay()
|
drawOverlay()
|
||||||
|
|
||||||
|
RenderState.checkError(getClass.getName + ".renderTileEntityAt: overlay")
|
||||||
|
|
||||||
if (distance > fadeDistanceSq) {
|
if (distance > fadeDistanceSq) {
|
||||||
RenderState.setBlendAlpha(math.max(0, 1 - ((distance - fadeDistanceSq) * fadeRatio).toFloat))
|
RenderState.setBlendAlpha(math.max(0, 1 - ((distance - fadeDistanceSq) * fadeRatio).toFloat))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderState.checkError(getClass.getName + ".renderTileEntityAt: fade")
|
||||||
|
|
||||||
if (screen.buffer.isRenderingEnabled) {
|
if (screen.buffer.isRenderingEnabled) {
|
||||||
compileOrDraw()
|
draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
GL11.glPopMatrix()
|
GL11.glPopMatrix()
|
||||||
@ -119,7 +127,9 @@ object ScreenRenderer extends TileEntitySpecialRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def compileOrDraw() {
|
private def draw() {
|
||||||
|
RenderState.checkError(getClass.getName + ".draw: entering (aka: wasntme)")
|
||||||
|
|
||||||
val sx = screen.width
|
val sx = screen.width
|
||||||
val sy = screen.height
|
val sy = screen.height
|
||||||
val tw = sx * 16f
|
val tw = sx * 16f
|
||||||
@ -157,8 +167,12 @@ object ScreenRenderer extends TileEntitySpecialRenderer {
|
|||||||
// Slightly offset the text so it doesn't clip into the screen.
|
// Slightly offset the text so it doesn't clip into the screen.
|
||||||
GL11.glTranslatef(0, 0, 0.01f)
|
GL11.glTranslatef(0, 0, 0.01f)
|
||||||
|
|
||||||
|
RenderState.checkError(getClass.getName + ".draw: setup")
|
||||||
|
|
||||||
// Render the actual text.
|
// Render the actual text.
|
||||||
screen.buffer.renderText()
|
screen.buffer.renderText()
|
||||||
|
|
||||||
|
RenderState.checkError(getClass.getName + ".draw: text")
|
||||||
}
|
}
|
||||||
|
|
||||||
private def playerDistanceSq() = {
|
private def playerDistanceSq() = {
|
||||||
|
@ -330,7 +330,7 @@ abstract class Screen(val parent: SimpleDelegator) extends RedstoneAware with Si
|
|||||||
}
|
}
|
||||||
|
|
||||||
override def collide(world: World, x: Int, y: Int, z: Int, entity: Entity) =
|
override def collide(world: World, x: Int, y: Int, z: Int, entity: Entity) =
|
||||||
if (!world.isRemote) (entity, world.getTileEntity(x, y, z)) match {
|
if (world.isRemote) (entity, world.getTileEntity(x, y, z)) match {
|
||||||
case (arrow: EntityArrow, screen: tileentity.Screen) if screen.tier > 0 =>
|
case (arrow: EntityArrow, screen: tileentity.Screen) if screen.tier > 0 =>
|
||||||
val hitX = math.max(0, math.min(1, arrow.posX - x))
|
val hitX = math.max(0, math.min(1, arrow.posX - x))
|
||||||
val hitY = math.max(0, math.min(1, arrow.posY - y))
|
val hitY = math.max(0, math.min(1, arrow.posY - y))
|
||||||
@ -351,7 +351,7 @@ abstract class Screen(val parent: SimpleDelegator) extends RedstoneAware with Si
|
|||||||
else ForgeDirection.SOUTH
|
else ForgeDirection.SOUTH
|
||||||
}
|
}
|
||||||
if (side == screen.facing) {
|
if (side == screen.facing) {
|
||||||
screen.shot(arrow, hitX, hitY, hitZ)
|
screen.shot(arrow)
|
||||||
}
|
}
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import cpw.mods.fml.relauncher.{Side, SideOnly}
|
|||||||
import li.cil.oc.api.network._
|
import li.cil.oc.api.network._
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.util.Color
|
import li.cil.oc.util.Color
|
||||||
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
import net.minecraft.entity.projectile.EntityArrow
|
import net.minecraft.entity.projectile.EntityArrow
|
||||||
@ -134,19 +135,8 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def shot(arrow: EntityArrow, hitX: Double, hitY: Double, hitZ: Double) {
|
def shot(arrow: EntityArrow) {
|
||||||
// This is nasty, but I see no other way: arrows can trigger two collisions,
|
arrows.add(arrow)
|
||||||
// once on their own when hitting a block, a second time via their entity's
|
|
||||||
// common collision checker. The second one (collision checker) has the
|
|
||||||
// better coordinates (arrow moved back out of the block it collided with),
|
|
||||||
// so use that when possible, otherwise resolve in next update.
|
|
||||||
if (!arrows.add(arrow)) {
|
|
||||||
arrows.remove(arrow)
|
|
||||||
arrow.shootingEntity match {
|
|
||||||
case player: EntityPlayer => click(player, hitX, hitY, hitZ)
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
@ -219,12 +209,22 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
|
|||||||
}
|
}
|
||||||
if (arrows.size > 0) {
|
if (arrows.size > 0) {
|
||||||
for (arrow <- arrows) {
|
for (arrow <- arrows) {
|
||||||
val hitX = math.max(0, math.min(1, arrow.posX - x))
|
val hitX = arrow.posX - x
|
||||||
val hitY = math.max(0, math.min(1, arrow.posY - y))
|
val hitY = arrow.posY - y
|
||||||
val hitZ = math.max(0, math.min(1, arrow.posZ - z))
|
val hitZ = arrow.posZ - z
|
||||||
shot(arrow, hitX, hitY, hitZ)
|
val hitXInner = math.abs(hitX - 0.5) < 0.45
|
||||||
|
val hitYInner = math.abs(hitY - 0.5) < 0.45
|
||||||
|
val hitZInner = math.abs(hitZ - 0.5) < 0.45
|
||||||
|
if (hitXInner && hitYInner && !hitZInner ||
|
||||||
|
hitXInner && !hitYInner && hitZInner ||
|
||||||
|
!hitXInner && hitYInner && hitZInner) {
|
||||||
|
arrow.shootingEntity match {
|
||||||
|
case player: EntityPlayer if player == Minecraft.getMinecraft.thePlayer => click(player, hitX, hitY, hitZ)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assert(arrows.isEmpty)
|
arrows.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user