[Script] PathAlgorithm 0.3(寻路算法动画)
-
作者:mumy
B站:https://space.bilibili.com/363239963这是个教学性脚本,可用于学习如何编写寻路
import Color = JVM.java$.awt$.Color; import JavaBoolean = JVM.java$.lang$.Boolean; import JavaFloat = JVM.java$.lang$.Float; import JavaInteger = JVM.java$.lang$.Integer; import JavaString = JVM.java$.lang$.String; import AttackEvent = JVM.net$.ccbluex$.liquidbounce$.event$.AttackEvent; import ClickBlockEvent = JVM.net$.ccbluex$.liquidbounce$.event$.ClickBlockEvent; import JumpEvent = JVM.net$.ccbluex$.liquidbounce$.event$.JumpEvent; import KeyEvent = JVM.net$.ccbluex$.liquidbounce$.event$.KeyEvent; import MotionEvent = JVM.net$.ccbluex$.liquidbounce$.event$.MotionEvent; import MoveEvent = JVM.net$.ccbluex$.liquidbounce$.event$.MoveEvent; import PacketEvent = JVM.net$.ccbluex$.liquidbounce$.event$.PacketEvent; import Render2DEvent = JVM.net$.ccbluex$.liquidbounce$.event$.Render2DEvent; import Render3DEvent = JVM.net$.ccbluex$.liquidbounce$.event$.Render3DEvent; import SlowDownEvent = JVM.net$.ccbluex$.liquidbounce$.event$.SlowDownEvent; import StepEvent = JVM.net$.ccbluex$.liquidbounce$.event$.StepEvent; import StrafeEvent = JVM.net$.ccbluex$.liquidbounce$.event$.StrafeEvent; import UpdateEvent = JVM.net$.ccbluex$.liquidbounce$.event$.UpdateEvent; import WorldEvent = JVM.net$.ccbluex$.liquidbounce$.event$.WorldEvent; import RenderUtils = JVM.net$.ccbluex$.liquidbounce$.utils$.render$.RenderUtils; import BlockValue = JVM.net$.ccbluex$.liquidbounce$.value$.BlockValue; import BoolValue = JVM.net$.ccbluex$.liquidbounce$.value$.BoolValue; import FloatValue = JVM.net$.ccbluex$.liquidbounce$.value$.FloatValue; import IntegerValue = JVM.net$.ccbluex$.liquidbounce$.value$.IntegerValue; import ListValue = JVM.net$.ccbluex$.liquidbounce$.value$.ListValue; import TextValue = JVM.net$.ccbluex$.liquidbounce$.value$.TextValue; import BlockSnow = JVM.net$.minecraft$.block$.BlockSnow; import BlockWeb = JVM.net$.minecraft$.block$.BlockWeb; import GlStateManager = JVM.net$.minecraft$.client$.renderer$.GlStateManager; import AxisAlignedBB = JVM.net$.minecraft$.util$.AxisAlignedBB; import BlockPos = JVM.net$.minecraft$.util$.BlockPos; import GL11 = JVM.org$.lwjgl$.opengl$.GL11; const scriptName = "PathAlgorithm"; const scriptVersion = 0.3; const scriptAuthor = "mumy++"; class PathAlgorithm { private readonly setting = { float: (name: string, def: number, min: number, max: number, object: object = {}) => { return new _AdaptedValue<number, JavaFloat>(new (Java.extend(FloatValue, object))(name, def, min, max)); }, integer: (name: string, def: number, min: number, max: number, object: object = {}) => { return new _AdaptedValue<number, JavaInteger>(new (Java.extend(IntegerValue, object))(name, def, min, max)); }, boolean: (name: string, def: boolean, object: object = {}) => { return new _AdaptedValue<boolean, JavaBoolean>(new (Java.extend(BoolValue, object))(name, def)); }, list: (name: string, values: string[], def: string, object: object = {}) => { return new _AdaptedValue<string, JavaString>(new (Java.extend(ListValue, object))(name, values, def)); }, text: (name: string, def: string, object: object = {}) => { return new _AdaptedValue<string, JavaString>(new (Java.extend(TextValue, object))(name, def)); }, block: (name: string, def: number, object: object = {}) => { return new _AdaptedValue<number, JavaInteger>(new (Java.extend(BlockValue, object))(name, def)); } }; private readonly settings = { setStart: this.setting.boolean("SetStart", false, { onChanged: (oldValue: boolean, newValue: boolean) => { if (!newValue) { return; } const player = mc.thePlayer!; this.start = new PathAlgorithm.Pos(Math.floor(player.posX), Math.floor(player.posY), Math.floor(player.posZ)); this.aStarAlgorithm = null; this.settings.setStart.set(false); } }), setEnd: this.setting.boolean("SetEnd", false, { onChanged: (oldValue: boolean, newValue: boolean) => { if (!newValue) { return; } const player = mc.thePlayer!; this.end = new PathAlgorithm.Pos(Math.floor(player.posX), Math.floor(player.posY), Math.floor(player.posZ)); this.aStarAlgorithm = null; this.settings.setEnd.set(false); } }), gWeight: this.setting.float("GWeight", 1.00005, 0, 2), hWeight: this.setting.float("HWeight", 1, 0, 2), speed: this.setting.integer("Speed", 1, 1, 50), reset: this.setting.boolean("Reset", false, { onChanged: (oldValue: boolean, newValue: boolean) => { if (!newValue) { return; } this.start = null; this.end = null; this.aStarAlgorithm = null; this.settings.reset.set(false); } }) }; private start = <typeof PathAlgorithm.Pos.prototype | null>null; private end = <typeof PathAlgorithm.Pos.prototype | null>null; private aStarAlgorithm = <typeof PathAlgorithm.AStarAlgorithm.prototype | null>null; private readonly openColor = new Color(200, 200, 200); private readonly closeColor = new Color(127, 127, 127); private readonly pathColor = new Color(0, 220, 220); public getName() { return "PathAlgorithm"; } public getDescription() { return "PathAlgorithm-Module, By-mumy"; } public getCategory() { return "Misc"; } public onEnable() { this.start = null; this.end = null; this.aStarAlgorithm = null; } public onDisable() { this.onEnable(); } public onUpdate() { if (this.start != null && this.end != null) { if (this.aStarAlgorithm == null) { this.aStarAlgorithm = new PathAlgorithm.AStarAlgorithm(this.start, this.end, this.settings.hWeight.get(), this.settings.gWeight.get()); } this.aStarAlgorithm.update(this.settings.speed.get()); } } public onRender3D(event: Render3DEvent) { if (this.start != null && this.aStarAlgorithm == null) { const { x, y, z } = this.start; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.openColor); } if (this.end != null && this.aStarAlgorithm?.path == null) { const { x, y, z } = this.end; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.openColor); } if (this.aStarAlgorithm != null) { if (this.aStarAlgorithm.path != null) { for (let pos of this.aStarAlgorithm.path) { const { x, y, z } = pos; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.pathColor); } } else { for (let pos of this.aStarAlgorithm.openList) { const { x, y, z } = pos; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.openColor); } for (let pos of this.aStarAlgorithm.closeList) { const { x, y, z } = pos; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.closeColor); } } } } public onWorld(event: WorldEvent) { moduleManager.getModule(this.getName())!.setState(false); } public addValues(values: _ValueAdapter) { const settings = <{ [ket: string]: _AdaptedValue<unknown, unknown> }>this.settings; for (let key in settings) { values.add(settings[key]); } } private drawEntityBox(entityBox: AxisAlignedBB, color: Color) { const renderManager = mc.getRenderManager()!; GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); RenderUtils.enableGlCap(GL11.GL_BLEND); RenderUtils.disableGlCap(GL11.GL_TEXTURE_2D, GL11.GL_DEPTH_TEST); GL11.glDepthMask(false); RenderUtils.glColor(color.getRed(), color.getGreen(), color.getBlue(), 26); const axisAlignedBB = new AxisAlignedBB(entityBox.minX - renderManager.renderPosX, entityBox.minY - renderManager.renderPosY, entityBox.minZ - renderManager.renderPosZ, entityBox.maxX - renderManager.renderPosX, entityBox.maxY - renderManager.renderPosY, entityBox.maxZ - renderManager.renderPosZ); RenderUtils.drawFilledBox(axisAlignedBB); GL11.glLineWidth(1); RenderUtils.enableGlCap(GL11.GL_LINE_SMOOTH); RenderUtils.glColor(color.getRed(), color.getGreen(), color.getBlue(), 95); RenderUtils.drawSelectionBoundingBox(axisAlignedBB); GlStateManager.resetColor(); GL11.glDepthMask(true); RenderUtils.resetCaps(); } public static Pos = class Pos { public constructor(public x: number, public y: number, public z: number) {} public equals(pos: Pos) { return pos.x === this.x && pos.y === this.y && pos.z === this.z; } } public static Node = class Node extends PathAlgorithm.Pos { public cost = 0; public hCost = 0; public constructor(public x: number, public y: number, public z: number, public parent: Node | null) { super(x, y, z); this.hCost = (parent?.hCost ?? -1) + 1; } } private static AStarAlgorithm = class AStarAlgorithm { private readonly start: typeof PathAlgorithm.Pos.prototype; private readonly end: typeof PathAlgorithm.Pos.prototype; public readonly openList = <typeof PathAlgorithm.Node.prototype[]>[]; public readonly closeList = <typeof PathAlgorithm.Pos.prototype[]>[]; private readonly hWeight: number; private readonly gWeight: number; public path = <typeof PathAlgorithm.Pos.prototype[] | null>null; public constructor(start: typeof PathAlgorithm.Pos.prototype, end: typeof PathAlgorithm.Pos.prototype, hWeight: number, gWeight: number) { this.start = start; this.end = end; this.hWeight = hWeight; this.gWeight = gWeight; this.openList.push(new PathAlgorithm.Node(start.x, start.y, start.z, null)); } public update(loops: number) { if (this.path != null) { return false; } top: while (loops-- > 0) { if (this.openList.length === 0) { return false; } const node = this.getNode()!; for (let pos of this.closeList) { if (node.equals(pos)) { continue top; } } if (!this.canPassable(new BlockPos(node.x, node.y, node.z))) { continue; } if (node.equals(this.end)) { this.path = []; let temp = <typeof PathAlgorithm.Node.prototype | null>node; do { this.path.push(temp!); temp = temp!.parent; } while (temp != null); this.path.reverse(); return false; } this.closeList.push(node); const { x, y, z } = node; this.createNodeToOpenList(x + 1, y, z, node); this.createNodeToOpenList(x, y + 1, z, node); this.createNodeToOpenList(x, y, z + 1, node); this.createNodeToOpenList(x - 1, y, z, node); this.createNodeToOpenList(x, y - 1, z, node); this.createNodeToOpenList(x, y, z - 1, node); } return true; } private createNodeToOpenList(x: number, y: number, z: number, parent: typeof PathAlgorithm.Node.prototype | null) { const node = new PathAlgorithm.Node(x, y, z, parent); const [ xDist, yDist, zDist ] = [Math.abs(node.x - this.end.x), Math.abs(node.y - this.end.y), Math.abs(node.z - this.end.z)]; node.cost = node.hCost * this.gWeight + (xDist + yDist + zDist) * this.hWeight; this.openList.push(node); } private getNode() { let finalIndex = -1; let finalCost = -1; let finalNode = <typeof PathAlgorithm.Node.prototype | null>null; for (let i = this.openList.length - 1; !(i < 0); --i) { const node = this.openList[i]; const cost = node.cost; if (finalNode == null || cost < finalCost) { finalNode = node; finalCost = cost; finalIndex = i; } if (i === 0) { this.openList.splice(finalIndex, 1); } } return finalNode; } private canPassable(blockPos: BlockPos) { const world = mc.theWorld!; const iBlockState = world.getBlockState(blockPos)!; const block = iBlockState.getBlock()!; return block.getCollisionBoundingBox(world, blockPos, iBlockState) == null ? !(block instanceof BlockWeb) : block instanceof BlockSnow && block.isReplaceable(world, blockPos); } } } let scriptModule: any; function onLoad() {} function onEnable() { scriptModule = moduleManager.registerModule(new PathAlgorithm()); } function onDisable() { moduleManager.unregisterModule(scriptModule); } -
作者:mumy
B站:https://space.bilibili.com/363239963这是个教学性脚本,可用于学习如何编写寻路
import Color = JVM.java$.awt$.Color; import JavaBoolean = JVM.java$.lang$.Boolean; import JavaFloat = JVM.java$.lang$.Float; import JavaInteger = JVM.java$.lang$.Integer; import JavaString = JVM.java$.lang$.String; import AttackEvent = JVM.net$.ccbluex$.liquidbounce$.event$.AttackEvent; import ClickBlockEvent = JVM.net$.ccbluex$.liquidbounce$.event$.ClickBlockEvent; import JumpEvent = JVM.net$.ccbluex$.liquidbounce$.event$.JumpEvent; import KeyEvent = JVM.net$.ccbluex$.liquidbounce$.event$.KeyEvent; import MotionEvent = JVM.net$.ccbluex$.liquidbounce$.event$.MotionEvent; import MoveEvent = JVM.net$.ccbluex$.liquidbounce$.event$.MoveEvent; import PacketEvent = JVM.net$.ccbluex$.liquidbounce$.event$.PacketEvent; import Render2DEvent = JVM.net$.ccbluex$.liquidbounce$.event$.Render2DEvent; import Render3DEvent = JVM.net$.ccbluex$.liquidbounce$.event$.Render3DEvent; import SlowDownEvent = JVM.net$.ccbluex$.liquidbounce$.event$.SlowDownEvent; import StepEvent = JVM.net$.ccbluex$.liquidbounce$.event$.StepEvent; import StrafeEvent = JVM.net$.ccbluex$.liquidbounce$.event$.StrafeEvent; import UpdateEvent = JVM.net$.ccbluex$.liquidbounce$.event$.UpdateEvent; import WorldEvent = JVM.net$.ccbluex$.liquidbounce$.event$.WorldEvent; import RenderUtils = JVM.net$.ccbluex$.liquidbounce$.utils$.render$.RenderUtils; import BlockValue = JVM.net$.ccbluex$.liquidbounce$.value$.BlockValue; import BoolValue = JVM.net$.ccbluex$.liquidbounce$.value$.BoolValue; import FloatValue = JVM.net$.ccbluex$.liquidbounce$.value$.FloatValue; import IntegerValue = JVM.net$.ccbluex$.liquidbounce$.value$.IntegerValue; import ListValue = JVM.net$.ccbluex$.liquidbounce$.value$.ListValue; import TextValue = JVM.net$.ccbluex$.liquidbounce$.value$.TextValue; import BlockSnow = JVM.net$.minecraft$.block$.BlockSnow; import BlockWeb = JVM.net$.minecraft$.block$.BlockWeb; import GlStateManager = JVM.net$.minecraft$.client$.renderer$.GlStateManager; import AxisAlignedBB = JVM.net$.minecraft$.util$.AxisAlignedBB; import BlockPos = JVM.net$.minecraft$.util$.BlockPos; import GL11 = JVM.org$.lwjgl$.opengl$.GL11; const scriptName = "PathAlgorithm"; const scriptVersion = 0.3; const scriptAuthor = "mumy++"; class PathAlgorithm { private readonly setting = { float: (name: string, def: number, min: number, max: number, object: object = {}) => { return new _AdaptedValue<number, JavaFloat>(new (Java.extend(FloatValue, object))(name, def, min, max)); }, integer: (name: string, def: number, min: number, max: number, object: object = {}) => { return new _AdaptedValue<number, JavaInteger>(new (Java.extend(IntegerValue, object))(name, def, min, max)); }, boolean: (name: string, def: boolean, object: object = {}) => { return new _AdaptedValue<boolean, JavaBoolean>(new (Java.extend(BoolValue, object))(name, def)); }, list: (name: string, values: string[], def: string, object: object = {}) => { return new _AdaptedValue<string, JavaString>(new (Java.extend(ListValue, object))(name, values, def)); }, text: (name: string, def: string, object: object = {}) => { return new _AdaptedValue<string, JavaString>(new (Java.extend(TextValue, object))(name, def)); }, block: (name: string, def: number, object: object = {}) => { return new _AdaptedValue<number, JavaInteger>(new (Java.extend(BlockValue, object))(name, def)); } }; private readonly settings = { setStart: this.setting.boolean("SetStart", false, { onChanged: (oldValue: boolean, newValue: boolean) => { if (!newValue) { return; } const player = mc.thePlayer!; this.start = new PathAlgorithm.Pos(Math.floor(player.posX), Math.floor(player.posY), Math.floor(player.posZ)); this.aStarAlgorithm = null; this.settings.setStart.set(false); } }), setEnd: this.setting.boolean("SetEnd", false, { onChanged: (oldValue: boolean, newValue: boolean) => { if (!newValue) { return; } const player = mc.thePlayer!; this.end = new PathAlgorithm.Pos(Math.floor(player.posX), Math.floor(player.posY), Math.floor(player.posZ)); this.aStarAlgorithm = null; this.settings.setEnd.set(false); } }), gWeight: this.setting.float("GWeight", 1.00005, 0, 2), hWeight: this.setting.float("HWeight", 1, 0, 2), speed: this.setting.integer("Speed", 1, 1, 50), reset: this.setting.boolean("Reset", false, { onChanged: (oldValue: boolean, newValue: boolean) => { if (!newValue) { return; } this.start = null; this.end = null; this.aStarAlgorithm = null; this.settings.reset.set(false); } }) }; private start = <typeof PathAlgorithm.Pos.prototype | null>null; private end = <typeof PathAlgorithm.Pos.prototype | null>null; private aStarAlgorithm = <typeof PathAlgorithm.AStarAlgorithm.prototype | null>null; private readonly openColor = new Color(200, 200, 200); private readonly closeColor = new Color(127, 127, 127); private readonly pathColor = new Color(0, 220, 220); public getName() { return "PathAlgorithm"; } public getDescription() { return "PathAlgorithm-Module, By-mumy"; } public getCategory() { return "Misc"; } public onEnable() { this.start = null; this.end = null; this.aStarAlgorithm = null; } public onDisable() { this.onEnable(); } public onUpdate() { if (this.start != null && this.end != null) { if (this.aStarAlgorithm == null) { this.aStarAlgorithm = new PathAlgorithm.AStarAlgorithm(this.start, this.end, this.settings.hWeight.get(), this.settings.gWeight.get()); } this.aStarAlgorithm.update(this.settings.speed.get()); } } public onRender3D(event: Render3DEvent) { if (this.start != null && this.aStarAlgorithm == null) { const { x, y, z } = this.start; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.openColor); } if (this.end != null && this.aStarAlgorithm?.path == null) { const { x, y, z } = this.end; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.openColor); } if (this.aStarAlgorithm != null) { if (this.aStarAlgorithm.path != null) { for (let pos of this.aStarAlgorithm.path) { const { x, y, z } = pos; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.pathColor); } } else { for (let pos of this.aStarAlgorithm.openList) { const { x, y, z } = pos; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.openColor); } for (let pos of this.aStarAlgorithm.closeList) { const { x, y, z } = pos; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.closeColor); } } } } public onWorld(event: WorldEvent) { moduleManager.getModule(this.getName())!.setState(false); } public addValues(values: _ValueAdapter) { const settings = <{ [ket: string]: _AdaptedValue<unknown, unknown> }>this.settings; for (let key in settings) { values.add(settings[key]); } } private drawEntityBox(entityBox: AxisAlignedBB, color: Color) { const renderManager = mc.getRenderManager()!; GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); RenderUtils.enableGlCap(GL11.GL_BLEND); RenderUtils.disableGlCap(GL11.GL_TEXTURE_2D, GL11.GL_DEPTH_TEST); GL11.glDepthMask(false); RenderUtils.glColor(color.getRed(), color.getGreen(), color.getBlue(), 26); const axisAlignedBB = new AxisAlignedBB(entityBox.minX - renderManager.renderPosX, entityBox.minY - renderManager.renderPosY, entityBox.minZ - renderManager.renderPosZ, entityBox.maxX - renderManager.renderPosX, entityBox.maxY - renderManager.renderPosY, entityBox.maxZ - renderManager.renderPosZ); RenderUtils.drawFilledBox(axisAlignedBB); GL11.glLineWidth(1); RenderUtils.enableGlCap(GL11.GL_LINE_SMOOTH); RenderUtils.glColor(color.getRed(), color.getGreen(), color.getBlue(), 95); RenderUtils.drawSelectionBoundingBox(axisAlignedBB); GlStateManager.resetColor(); GL11.glDepthMask(true); RenderUtils.resetCaps(); } public static Pos = class Pos { public constructor(public x: number, public y: number, public z: number) {} public equals(pos: Pos) { return pos.x === this.x && pos.y === this.y && pos.z === this.z; } } public static Node = class Node extends PathAlgorithm.Pos { public cost = 0; public hCost = 0; public constructor(public x: number, public y: number, public z: number, public parent: Node | null) { super(x, y, z); this.hCost = (parent?.hCost ?? -1) + 1; } } private static AStarAlgorithm = class AStarAlgorithm { private readonly start: typeof PathAlgorithm.Pos.prototype; private readonly end: typeof PathAlgorithm.Pos.prototype; public readonly openList = <typeof PathAlgorithm.Node.prototype[]>[]; public readonly closeList = <typeof PathAlgorithm.Pos.prototype[]>[]; private readonly hWeight: number; private readonly gWeight: number; public path = <typeof PathAlgorithm.Pos.prototype[] | null>null; public constructor(start: typeof PathAlgorithm.Pos.prototype, end: typeof PathAlgorithm.Pos.prototype, hWeight: number, gWeight: number) { this.start = start; this.end = end; this.hWeight = hWeight; this.gWeight = gWeight; this.openList.push(new PathAlgorithm.Node(start.x, start.y, start.z, null)); } public update(loops: number) { if (this.path != null) { return false; } top: while (loops-- > 0) { if (this.openList.length === 0) { return false; } const node = this.getNode()!; for (let pos of this.closeList) { if (node.equals(pos)) { continue top; } } if (!this.canPassable(new BlockPos(node.x, node.y, node.z))) { continue; } if (node.equals(this.end)) { this.path = []; let temp = <typeof PathAlgorithm.Node.prototype | null>node; do { this.path.push(temp!); temp = temp!.parent; } while (temp != null); this.path.reverse(); return false; } this.closeList.push(node); const { x, y, z } = node; this.createNodeToOpenList(x + 1, y, z, node); this.createNodeToOpenList(x, y + 1, z, node); this.createNodeToOpenList(x, y, z + 1, node); this.createNodeToOpenList(x - 1, y, z, node); this.createNodeToOpenList(x, y - 1, z, node); this.createNodeToOpenList(x, y, z - 1, node); } return true; } private createNodeToOpenList(x: number, y: number, z: number, parent: typeof PathAlgorithm.Node.prototype | null) { const node = new PathAlgorithm.Node(x, y, z, parent); const [ xDist, yDist, zDist ] = [Math.abs(node.x - this.end.x), Math.abs(node.y - this.end.y), Math.abs(node.z - this.end.z)]; node.cost = node.hCost * this.gWeight + (xDist + yDist + zDist) * this.hWeight; this.openList.push(node); } private getNode() { let finalIndex = -1; let finalCost = -1; let finalNode = <typeof PathAlgorithm.Node.prototype | null>null; for (let i = this.openList.length - 1; !(i < 0); --i) { const node = this.openList[i]; const cost = node.cost; if (finalNode == null || cost < finalCost) { finalNode = node; finalCost = cost; finalIndex = i; } if (i === 0) { this.openList.splice(finalIndex, 1); } } return finalNode; } private canPassable(blockPos: BlockPos) { const world = mc.theWorld!; const iBlockState = world.getBlockState(blockPos)!; const block = iBlockState.getBlock()!; return block.getCollisionBoundingBox(world, blockPos, iBlockState) == null ? !(block instanceof BlockWeb) : block instanceof BlockSnow && block.isReplaceable(world, blockPos); } } } let scriptModule: any; function onLoad() {} function onEnable() { scriptModule = moduleManager.registerModule(new PathAlgorithm()); } function onDisable() { moduleManager.unregisterModule(scriptModule); }@CookieChinese Very cool.
-
作者:mumy
B站:https://space.bilibili.com/363239963这是个教学性脚本,可用于学习如何编写寻路
import Color = JVM.java$.awt$.Color; import JavaBoolean = JVM.java$.lang$.Boolean; import JavaFloat = JVM.java$.lang$.Float; import JavaInteger = JVM.java$.lang$.Integer; import JavaString = JVM.java$.lang$.String; import AttackEvent = JVM.net$.ccbluex$.liquidbounce$.event$.AttackEvent; import ClickBlockEvent = JVM.net$.ccbluex$.liquidbounce$.event$.ClickBlockEvent; import JumpEvent = JVM.net$.ccbluex$.liquidbounce$.event$.JumpEvent; import KeyEvent = JVM.net$.ccbluex$.liquidbounce$.event$.KeyEvent; import MotionEvent = JVM.net$.ccbluex$.liquidbounce$.event$.MotionEvent; import MoveEvent = JVM.net$.ccbluex$.liquidbounce$.event$.MoveEvent; import PacketEvent = JVM.net$.ccbluex$.liquidbounce$.event$.PacketEvent; import Render2DEvent = JVM.net$.ccbluex$.liquidbounce$.event$.Render2DEvent; import Render3DEvent = JVM.net$.ccbluex$.liquidbounce$.event$.Render3DEvent; import SlowDownEvent = JVM.net$.ccbluex$.liquidbounce$.event$.SlowDownEvent; import StepEvent = JVM.net$.ccbluex$.liquidbounce$.event$.StepEvent; import StrafeEvent = JVM.net$.ccbluex$.liquidbounce$.event$.StrafeEvent; import UpdateEvent = JVM.net$.ccbluex$.liquidbounce$.event$.UpdateEvent; import WorldEvent = JVM.net$.ccbluex$.liquidbounce$.event$.WorldEvent; import RenderUtils = JVM.net$.ccbluex$.liquidbounce$.utils$.render$.RenderUtils; import BlockValue = JVM.net$.ccbluex$.liquidbounce$.value$.BlockValue; import BoolValue = JVM.net$.ccbluex$.liquidbounce$.value$.BoolValue; import FloatValue = JVM.net$.ccbluex$.liquidbounce$.value$.FloatValue; import IntegerValue = JVM.net$.ccbluex$.liquidbounce$.value$.IntegerValue; import ListValue = JVM.net$.ccbluex$.liquidbounce$.value$.ListValue; import TextValue = JVM.net$.ccbluex$.liquidbounce$.value$.TextValue; import BlockSnow = JVM.net$.minecraft$.block$.BlockSnow; import BlockWeb = JVM.net$.minecraft$.block$.BlockWeb; import GlStateManager = JVM.net$.minecraft$.client$.renderer$.GlStateManager; import AxisAlignedBB = JVM.net$.minecraft$.util$.AxisAlignedBB; import BlockPos = JVM.net$.minecraft$.util$.BlockPos; import GL11 = JVM.org$.lwjgl$.opengl$.GL11; const scriptName = "PathAlgorithm"; const scriptVersion = 0.3; const scriptAuthor = "mumy++"; class PathAlgorithm { private readonly setting = { float: (name: string, def: number, min: number, max: number, object: object = {}) => { return new _AdaptedValue<number, JavaFloat>(new (Java.extend(FloatValue, object))(name, def, min, max)); }, integer: (name: string, def: number, min: number, max: number, object: object = {}) => { return new _AdaptedValue<number, JavaInteger>(new (Java.extend(IntegerValue, object))(name, def, min, max)); }, boolean: (name: string, def: boolean, object: object = {}) => { return new _AdaptedValue<boolean, JavaBoolean>(new (Java.extend(BoolValue, object))(name, def)); }, list: (name: string, values: string[], def: string, object: object = {}) => { return new _AdaptedValue<string, JavaString>(new (Java.extend(ListValue, object))(name, values, def)); }, text: (name: string, def: string, object: object = {}) => { return new _AdaptedValue<string, JavaString>(new (Java.extend(TextValue, object))(name, def)); }, block: (name: string, def: number, object: object = {}) => { return new _AdaptedValue<number, JavaInteger>(new (Java.extend(BlockValue, object))(name, def)); } }; private readonly settings = { setStart: this.setting.boolean("SetStart", false, { onChanged: (oldValue: boolean, newValue: boolean) => { if (!newValue) { return; } const player = mc.thePlayer!; this.start = new PathAlgorithm.Pos(Math.floor(player.posX), Math.floor(player.posY), Math.floor(player.posZ)); this.aStarAlgorithm = null; this.settings.setStart.set(false); } }), setEnd: this.setting.boolean("SetEnd", false, { onChanged: (oldValue: boolean, newValue: boolean) => { if (!newValue) { return; } const player = mc.thePlayer!; this.end = new PathAlgorithm.Pos(Math.floor(player.posX), Math.floor(player.posY), Math.floor(player.posZ)); this.aStarAlgorithm = null; this.settings.setEnd.set(false); } }), gWeight: this.setting.float("GWeight", 1.00005, 0, 2), hWeight: this.setting.float("HWeight", 1, 0, 2), speed: this.setting.integer("Speed", 1, 1, 50), reset: this.setting.boolean("Reset", false, { onChanged: (oldValue: boolean, newValue: boolean) => { if (!newValue) { return; } this.start = null; this.end = null; this.aStarAlgorithm = null; this.settings.reset.set(false); } }) }; private start = <typeof PathAlgorithm.Pos.prototype | null>null; private end = <typeof PathAlgorithm.Pos.prototype | null>null; private aStarAlgorithm = <typeof PathAlgorithm.AStarAlgorithm.prototype | null>null; private readonly openColor = new Color(200, 200, 200); private readonly closeColor = new Color(127, 127, 127); private readonly pathColor = new Color(0, 220, 220); public getName() { return "PathAlgorithm"; } public getDescription() { return "PathAlgorithm-Module, By-mumy"; } public getCategory() { return "Misc"; } public onEnable() { this.start = null; this.end = null; this.aStarAlgorithm = null; } public onDisable() { this.onEnable(); } public onUpdate() { if (this.start != null && this.end != null) { if (this.aStarAlgorithm == null) { this.aStarAlgorithm = new PathAlgorithm.AStarAlgorithm(this.start, this.end, this.settings.hWeight.get(), this.settings.gWeight.get()); } this.aStarAlgorithm.update(this.settings.speed.get()); } } public onRender3D(event: Render3DEvent) { if (this.start != null && this.aStarAlgorithm == null) { const { x, y, z } = this.start; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.openColor); } if (this.end != null && this.aStarAlgorithm?.path == null) { const { x, y, z } = this.end; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.openColor); } if (this.aStarAlgorithm != null) { if (this.aStarAlgorithm.path != null) { for (let pos of this.aStarAlgorithm.path) { const { x, y, z } = pos; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.pathColor); } } else { for (let pos of this.aStarAlgorithm.openList) { const { x, y, z } = pos; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.openColor); } for (let pos of this.aStarAlgorithm.closeList) { const { x, y, z } = pos; this.drawEntityBox(new AxisAlignedBB(x, y, z, x + 1, y + 1, z + 1), this.closeColor); } } } } public onWorld(event: WorldEvent) { moduleManager.getModule(this.getName())!.setState(false); } public addValues(values: _ValueAdapter) { const settings = <{ [ket: string]: _AdaptedValue<unknown, unknown> }>this.settings; for (let key in settings) { values.add(settings[key]); } } private drawEntityBox(entityBox: AxisAlignedBB, color: Color) { const renderManager = mc.getRenderManager()!; GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); RenderUtils.enableGlCap(GL11.GL_BLEND); RenderUtils.disableGlCap(GL11.GL_TEXTURE_2D, GL11.GL_DEPTH_TEST); GL11.glDepthMask(false); RenderUtils.glColor(color.getRed(), color.getGreen(), color.getBlue(), 26); const axisAlignedBB = new AxisAlignedBB(entityBox.minX - renderManager.renderPosX, entityBox.minY - renderManager.renderPosY, entityBox.minZ - renderManager.renderPosZ, entityBox.maxX - renderManager.renderPosX, entityBox.maxY - renderManager.renderPosY, entityBox.maxZ - renderManager.renderPosZ); RenderUtils.drawFilledBox(axisAlignedBB); GL11.glLineWidth(1); RenderUtils.enableGlCap(GL11.GL_LINE_SMOOTH); RenderUtils.glColor(color.getRed(), color.getGreen(), color.getBlue(), 95); RenderUtils.drawSelectionBoundingBox(axisAlignedBB); GlStateManager.resetColor(); GL11.glDepthMask(true); RenderUtils.resetCaps(); } public static Pos = class Pos { public constructor(public x: number, public y: number, public z: number) {} public equals(pos: Pos) { return pos.x === this.x && pos.y === this.y && pos.z === this.z; } } public static Node = class Node extends PathAlgorithm.Pos { public cost = 0; public hCost = 0; public constructor(public x: number, public y: number, public z: number, public parent: Node | null) { super(x, y, z); this.hCost = (parent?.hCost ?? -1) + 1; } } private static AStarAlgorithm = class AStarAlgorithm { private readonly start: typeof PathAlgorithm.Pos.prototype; private readonly end: typeof PathAlgorithm.Pos.prototype; public readonly openList = <typeof PathAlgorithm.Node.prototype[]>[]; public readonly closeList = <typeof PathAlgorithm.Pos.prototype[]>[]; private readonly hWeight: number; private readonly gWeight: number; public path = <typeof PathAlgorithm.Pos.prototype[] | null>null; public constructor(start: typeof PathAlgorithm.Pos.prototype, end: typeof PathAlgorithm.Pos.prototype, hWeight: number, gWeight: number) { this.start = start; this.end = end; this.hWeight = hWeight; this.gWeight = gWeight; this.openList.push(new PathAlgorithm.Node(start.x, start.y, start.z, null)); } public update(loops: number) { if (this.path != null) { return false; } top: while (loops-- > 0) { if (this.openList.length === 0) { return false; } const node = this.getNode()!; for (let pos of this.closeList) { if (node.equals(pos)) { continue top; } } if (!this.canPassable(new BlockPos(node.x, node.y, node.z))) { continue; } if (node.equals(this.end)) { this.path = []; let temp = <typeof PathAlgorithm.Node.prototype | null>node; do { this.path.push(temp!); temp = temp!.parent; } while (temp != null); this.path.reverse(); return false; } this.closeList.push(node); const { x, y, z } = node; this.createNodeToOpenList(x + 1, y, z, node); this.createNodeToOpenList(x, y + 1, z, node); this.createNodeToOpenList(x, y, z + 1, node); this.createNodeToOpenList(x - 1, y, z, node); this.createNodeToOpenList(x, y - 1, z, node); this.createNodeToOpenList(x, y, z - 1, node); } return true; } private createNodeToOpenList(x: number, y: number, z: number, parent: typeof PathAlgorithm.Node.prototype | null) { const node = new PathAlgorithm.Node(x, y, z, parent); const [ xDist, yDist, zDist ] = [Math.abs(node.x - this.end.x), Math.abs(node.y - this.end.y), Math.abs(node.z - this.end.z)]; node.cost = node.hCost * this.gWeight + (xDist + yDist + zDist) * this.hWeight; this.openList.push(node); } private getNode() { let finalIndex = -1; let finalCost = -1; let finalNode = <typeof PathAlgorithm.Node.prototype | null>null; for (let i = this.openList.length - 1; !(i < 0); --i) { const node = this.openList[i]; const cost = node.cost; if (finalNode == null || cost < finalCost) { finalNode = node; finalCost = cost; finalIndex = i; } if (i === 0) { this.openList.splice(finalIndex, 1); } } return finalNode; } private canPassable(blockPos: BlockPos) { const world = mc.theWorld!; const iBlockState = world.getBlockState(blockPos)!; const block = iBlockState.getBlock()!; return block.getCollisionBoundingBox(world, blockPos, iBlockState) == null ? !(block instanceof BlockWeb) : block instanceof BlockSnow && block.isReplaceable(world, blockPos); } } } let scriptModule: any; function onLoad() {} function onEnable() { scriptModule = moduleManager.registerModule(new PathAlgorithm()); } function onDisable() { moduleManager.unregisterModule(scriptModule); }@CookieChinese 十分有趣
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login