CCBlueX Forum

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups

    [Script] PathAlgorithm 0.3(寻路算法动画)

    Chinese
    3
    3
    107
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • CookieChinese
      CookieChinese last edited by

      作者: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);
      }
      
      kawaiinekololis Y 2 Replies Last reply Reply Quote 1
      • kawaiinekololis
        kawaiinekololis Admin @CookieChinese last edited by

        @CookieChinese Very cool.

        1 Reply Last reply Reply Quote 0
        • Y
          ybyyby_ awa @CookieChinese last edited by

          @CookieChinese 十分有趣

          1 Reply Last reply Reply Quote 0
          • First post
            Last post
          About
          • Terms of Service
          • Privacy Policy
          • Status
          • Contact Us
          Downloads
          • Releases
          • Source code
          • License
          Docs
          • Tutorials
          • CustomHUD
          • AutoSettings
          • ScriptAPI
          Community
          • Forum
          • Guilded
          • YouTube
          • Twitter
          • D.Tube