示例#1
0
 public void setCommandBlock(Block block) {
   castCommandBlock = block;
   if (castCommandBlock.getType() == Material.COMMAND) {
     BlockState commandData = castCommandBlock.getState();
     if (commandData != null && commandData instanceof CommandBlock) {
       CommandBlock commandBlock = ((CommandBlock) commandData);
       castCommand = commandBlock.getCommand();
       commandName = commandBlock.getName();
     }
     includeCommands = castCommand != null && castCommand.length() > 0;
   }
 }
示例#2
0
  public void target(TargetMode mode) {
    targetMode = mode == null ? TargetMode.STABILIZE : mode;
    switch (targetMode) {
      case FLEE:
      case HUNT:
      case DIRECTED:
        Target bestTarget = null;
        reverseTargetDistanceScore = true;
        if (targetType == TargetType.ANY || targetType == TargetType.MOB) {
          List<Entity> entities =
              CompatibilityUtils.getNearbyEntities(
                  center, huntMaxRange, huntMaxRange, huntMaxRange);
          for (Entity entity : entities) {
            // We'll get the players from the Mages list
            if (entity instanceof Player || !(entity instanceof LivingEntity) || entity.isDead())
              continue;
            if (!entity.getLocation().getWorld().equals(center.getWorld())) continue;
            LivingEntity li = (LivingEntity) entity;
            if (li.hasPotionEffect(PotionEffectType.INVISIBILITY)) continue;
            Target newScore =
                new Target(center, entity, huntMinRange, huntMaxRange, huntFov, false);
            int score = newScore.getScore();
            if (bestTarget == null || score > bestTarget.getScore()) {
              bestTarget = newScore;
            }
          }
        }
        if (targetType == TargetType.MAGE
            || targetType == TargetType.AUTOMATON
            || targetType == TargetType.ANY
            || targetType == TargetType.PLAYER) {
          Collection<Mage> mages = controller.getMages();
          for (Mage mage : mages) {
            if (mage == this.mage) continue;
            if (targetType == TargetType.AUTOMATON && mage.getPlayer() != null) continue;
            if (targetType == TargetType.PLAYER && mage.getPlayer() == null) continue;
            if (mage.isDead() || !mage.isOnline() || !mage.hasLocation()) continue;
            if (!mage.getLocation().getWorld().equals(center.getWorld())) continue;
            if (!mage.getLocation().getWorld().equals(center.getWorld())) continue;

            if (!mage.isPlayer()) {
              // Check for automata of the same type, kinda hacky.. ?
              Block block = mage.getLocation().getBlock();
              if (block.getType() == Material.COMMAND) {
                BlockState blockState = block.getState();
                if (blockState != null && blockState instanceof CommandBlock) {
                  CommandBlock command = (CommandBlock) blockState;
                  String commandString = command.getCommand();
                  if (commandString != null
                      && commandString.length() > 0
                      && commandString.startsWith("cast " + spell.getKey())) {
                    continue;
                  }
                }
              }
            } else {
              Player player = mage.getPlayer();
              if (player.hasPotionEffect(PotionEffectType.INVISIBILITY)) continue;
            }

            Target newScore = new Target(center, mage, huntMinRange, huntMaxRange, huntFov, false);
            int score = newScore.getScore();
            if (bestTarget == null || score > bestTarget.getScore()) {
              bestTarget = newScore;
            }
          }
        }

        if (bestTarget != null) {
          String targetDescription =
              bestTarget.getEntity() == null
                  ? "NONE"
                  : ((bestTarget instanceof Player)
                      ? ((Player) bestTarget.getEntity()).getName()
                      : bestTarget.getEntity().getType().name());

          if (DEBUG) {
            controller
                .getLogger()
                .info(
                    " *Tracking "
                        + targetDescription
                        + " score: "
                        + bestTarget.getScore()
                        + " location: "
                        + center
                        + " -> "
                        + bestTarget.getLocation()
                        + " move "
                        + commandMoveRangeSquared);
          }
          Vector direction = null;

          if (targetMode == TargetMode.DIRECTED) {
            direction = bestTarget.getLocation().getDirection();
            if (DEBUG) {
              controller.getLogger().info(" *Directed: " + direction);
            }
          } else {
            Location targetLocation = bestTarget.getLocation();
            direction = targetLocation.toVector().subtract(center.toVector());
          }

          if (direction != null) {
            center.setDirection(direction);
          }

          // Check for obstruction
          // TODO Think about this more..
          /*
          Block block = spell.getInteractBlock();
          if (block.getType() != Material.AIR && block.getType() != POWER_MATERIAL && !!birthMaterial.is(block)) {
          	// TODO: Use location.setDirection in 1.7+
          	center = CompatibilityUtils.setDirection(center, new Vector(0, 1, 0));
          }
          */

          if (level != null
              && center.distanceSquared(bestTarget.getLocation()) < castRange * castRange) {
            level.onTick(mage, birthMaterial);
          }

          // After ticking, re-position for movement. This way spells still fire towards the target.
          if (targetMode == TargetMode.FLEE) {
            direction = direction.multiply(-1);
            // Don't Flee upward
            if (direction.getY() > 0) {
              direction.setY(-direction.getY());
            }
          }
        }
        break;
      case GLIDE:
        reverseTargetDistanceScore = true;
        break;
      default:
        reverseTargetDistanceScore = false;
    }
  }
示例#3
0
  @Override
  public int process(int maxBlocks) {
    int processedBlocks = 0;
    if (state == SimulationState.SCANNING_COMMAND) {
      // Process the casting command block first, and only if specially configured to do so.
      if (includeCommands && castCommandBlock != null) {
        // We are going to rely on the block toggling to kick this back to life when the chunk
        // reloads, so for now just bail and hope the timing works out.
        if (!castCommandBlock.getChunk().isLoaded()) {
          finish();
          // TODO: Maybe Scatter-shot and register all 6 surrounding power blocks for reload toggle.
          // Can't really do it without the chunk being loaded though, so hrm.
          return processedBlocks;
        }

        // Check for death since activation (e.g. during delay period)
        if (castCommandBlock.getType() != Material.COMMAND) {
          die();
          finish();
          return processedBlocks;
        }

        // Check for power blocks
        for (BlockFace powerFace : POWER_FACES) {
          Block checkForPower = castCommandBlock.getRelative(powerFace);
          if (checkForPower.getType() == POWER_MATERIAL) {
            if (commandReload) {
              controller.unregisterAutomata(checkForPower);
            }
            powerSimMaterial.modify(checkForPower);
            commandPowered = true;
          }
        }

        if (!commandPowered) {
          die();
          finish();
          return processedBlocks;
        }

        // Make this a normal block so the sim will process it
        // this also serves to reset the command block for the next tick, if it lives.
        birthMaterial.modify(castCommandBlock);
      }

      processedBlocks++;
      state = SimulationState.SCANNING;
    }

    while (state == SimulationState.SCANNING && processedBlocks <= maxBlocks) {
      if (!simulateBlocks(x, y, z)) {
        return processedBlocks;
      }

      y++;
      if (y > yRadius) {
        y = 0;
        if (x < radius) {
          x++;
        } else {
          z--;
          if (z < 0) {
            r++;
            z = r;
            x = 0;
          }
        }
      }

      if (r > radius) {
        state = SimulationState.UPDATING;
      }
    }

    while (state == SimulationState.UPDATING && processedBlocks <= maxBlocks) {
      int deadIndex = updatingIndex;
      if (deadIndex >= 0 && deadIndex < deadBlocks.size()) {
        Block killBlock = deadBlocks.get(deadIndex);
        if (!killBlock.getChunk().isLoaded()) {
          killBlock.getChunk().load();
          return processedBlocks;
        }

        if (birthMaterial.is(killBlock)) {
          registerForUndo(killBlock);
          killBlock.setType(deathMaterial);
        } else {
          // If this block was destroyed while we were processing,
          // avoid spawning a random birth block.
          // This tries to make it so automata don't "cheat" when
          // getting destroyed. A bit hacky though, I'm not about
          // to re-simulate...
          if (bornBlocks.size() > 0) {
            bornBlocks.remove(bornBlocks.size() - 1);
          }
        }
        processedBlocks++;
      }

      int bornIndex = updatingIndex - deadBlocks.size();
      if (bornIndex >= 0 && bornIndex < bornBlocks.size()) {
        Block birthBlock = bornBlocks.get(bornIndex);
        if (!birthBlock.getChunk().isLoaded()) {
          birthBlock.getChunk().load();
          return processedBlocks;
        }
        registerForUndo(birthBlock);
        birthMaterial.modify(birthBlock);
      }

      updatingIndex++;
      if (updatingIndex >= deadBlocks.size() + bornBlocks.size()) {
        state = SimulationState.COMMAND_SEARCH;

        // Wait at least a tick before re-populating the command block.
        return maxBlocks;
      }
    }

    // Each of the following states will end in this tick, to give the
    // MC sim time to register power updates.
    if (state == SimulationState.COMMAND_SEARCH) {
      if (includeCommands && potentialCommandBlocks.size() > 0) {
        switch (targetMode) {
          case HUNT:
            Collections.sort(potentialCommandBlocks);
            break;
          case FLEE:
            Collections.sort(potentialCommandBlocks);
            break;
          default:
            Collections.shuffle(potentialCommandBlocks);
            break;
        }

        // Find a valid block for the command
        powerTargetBlock = null;
        commandTargetBlock = null;
        Block backupBlock = null;
        while (commandTargetBlock == null && potentialCommandBlocks.size() > 0) {
          Block block = potentialCommandBlocks.remove(0).getBlock();
          if (block != null && birthMaterial.is(block)) {
            // If we're powering the block, look for one with a powerable neighbor.
            if (!commandPowered) {
              commandTargetBlock = block;
            } else {
              backupBlock = block;
              BlockFace powerFace = findPowerLocation(block, powerSimMaterial);
              if (powerFace != null) {
                commandTargetBlock = block;
              }
            }
          }
        }

        // If we didn't find any powerable blocks, but we did find at least one valid sim block
        // just use that one.
        if (commandTargetBlock == null) commandTargetBlock = backupBlock;

        // Search for a power block
        if (commandTargetBlock != null) {
          // First try and replace a live cell
          BlockFace powerDirection = findPowerLocation(commandTargetBlock, powerSimMaterial);
          // Next try to replace a dead cell, which will affect the simulation outcome
          // but this is perhaps better than it dying?
          if (powerDirection == null) {
            if (DEBUG) {
              controller
                  .getLogger()
                  .info("Had to fall back to backup location, pattern may diverge");
            }
            powerDirection = findPowerLocation(commandTargetBlock, powerSimMaterialBackup);
          }
          // If it's *still* not valid, search for something breakable.
          if (powerDirection == null) {
            for (BlockFace face : POWER_FACES) {
              if (blockSpell.isDestructible(commandTargetBlock.getRelative(face))) {
                if (DEBUG) {
                  controller
                      .getLogger()
                      .info(
                          "Had to fall back to destructible location, pattern may diverge and may destroy blocks");
                }
                powerDirection = face;
                break;
              }
            }
          }

          if (powerDirection != null) {
            powerTargetBlock = commandTargetBlock.getRelative(powerDirection);
          }
        }
      }
      if (DEBUG) {
        if (commandTargetBlock != null) {
          controller
              .getLogger()
              .info(
                  "MOVED: "
                      + commandTargetBlock.getLocation().toVector().subtract(center.toVector()));
        }
      }
      state = SimulationState.COMMON_RESET_REDSTONE;
      return processedBlocks;
    }

    if (state == SimulationState.COMMON_RESET_REDSTONE) {
      if (includeCommands && commandTargetBlock != null) {
        DeprecatedUtils.setData(commandTargetBlock, (byte) 0);
      }
      if (includeCommands && powerTargetBlock != null) {
        DeprecatedUtils.setData(powerTargetBlock, (byte) 0);
      }
      state = SimulationState.COMMAND_UPDATE;
      return processedBlocks;
    }

    if (state == SimulationState.COMMAND_UPDATE) {
      if (includeCommands) {
        if (commandTargetBlock != null) {
          if (!commandTargetBlock.getChunk().isLoaded()) {
            commandTargetBlock.getChunk().load();
            return processedBlocks;
          }

          commandTargetBlock.setType(Material.COMMAND);
          BlockState commandData = commandTargetBlock.getState();
          if (castCommand != null && commandData != null && commandData instanceof CommandBlock) {
            CommandBlock copyCommand = (CommandBlock) commandData;
            copyCommand.setCommand(castCommand);
            copyCommand.setName(commandName);
            copyCommand.update();

            // Also move the mage
            Location newLocation = commandTargetBlock.getLocation();
            newLocation.setPitch(center.getPitch());
            newLocation.setYaw(center.getYaw());
            mage.setLocation(newLocation);
          } else {
            commandTargetBlock = null;
          }
        } else {
          die();
        }
      }
      powerDelayTicks = POWER_DELAY_TICKS;
      state = SimulationState.COMMAND_POWER;
      return processedBlocks;
    }

    if (state == SimulationState.COMMAND_POWER) {
      // Continue to power the command block
      if (commandPowered && powerTargetBlock != null && includeCommands) {
        // Wait a bit before powering for redstone signals to reset
        if (powerDelayTicks > 0) {
          powerDelayTicks--;
          return processedBlocks;
        }

        if (powerTargetBlock != null) {
          powerTargetBlock.setType(POWER_MATERIAL);
          if (commandReload) {
            String automataName = commandName;
            if (automataName == null || automataName.length() <= 1) {
              automataName = controller.getMessages().get("automata.default_name");
            }
            controller.registerAutomata(powerTargetBlock, automataName, "automata.awaken");
          }
        }
      }
      state = SimulationState.FINISHED;
      return processedBlocks;
    }

    if (state == SimulationState.FINISHED) {
      finish();
    }

    return processedBlocks;
  }
示例#4
0
  protected boolean simulateBlock(int dx, int dy, int dz) {
    int x = center.getBlockX() + dx;
    int y = center.getBlockY() + dy;
    int z = center.getBlockZ() + dz;
    Block block = world.getBlockAt(x, y, z);
    if (!block.getChunk().isLoaded()) {
      block.getChunk().load();
      return false;
    }

    Material blockMaterial = block.getType();
    if (birthMaterial.is(block)) {
      int distanceSquared =
          liveRangeSquared > 0 || includeCommands
              ? (int) Math.ceil(block.getLocation().distanceSquared(castCommandBlock.getLocation()))
              : 0;

      if (liveRangeSquared <= 0 || distanceSquared <= liveRangeSquared) {
        if (diagonalLiveCounts.size() > 0) {
          int faceNeighborCount = getFaceNeighborCount(block, birthMaterial, includeCommands);
          int diagonalNeighborCount =
              getDiagonalNeighborCount(block, birthMaterial, includeCommands);
          if (faceNeighborCount >= liveCounts.size()
              || !liveCounts.get(faceNeighborCount)
              || diagonalNeighborCount >= diagonalLiveCounts.size()
              || !diagonalLiveCounts.get(diagonalNeighborCount)) {
            killBlock(block);
          } else {
            checkForPotentialCommand(block, distanceSquared);
          }
        } else {
          int neighborCount = getNeighborCount(block, birthMaterial, includeCommands);
          if (neighborCount >= liveCounts.size() || !liveCounts.get(neighborCount)) {
            killBlock(block);
          } else {
            checkForPotentialCommand(block, distanceSquared);
          }
        }
      } else {
        killBlock(block);
      }
    } else if (blockMaterial == deathMaterial) {
      int distanceSquared =
          birthRangeSquared > 0 || includeCommands
              ? (int) Math.ceil(block.getLocation().distanceSquared(castCommandBlock.getLocation()))
              : 0;

      if (birthRangeSquared <= 0 || distanceSquared <= birthRangeSquared) {
        if (diagonalBirthCounts.size() > 0) {
          int faceNeighborCount = getFaceNeighborCount(block, birthMaterial, includeCommands);
          int diagonalNeighborCount =
              getDiagonalNeighborCount(block, birthMaterial, includeCommands);
          if (faceNeighborCount < birthCounts.size()
              && birthCounts.get(faceNeighborCount)
              && diagonalNeighborCount < diagonalBirthCounts.size()
              && diagonalBirthCounts.get(diagonalNeighborCount)) {
            birthBlock(block);
            checkForPotentialCommand(block, distanceSquared);
          }
        } else {
          int neighborCount = getNeighborCount(block, birthMaterial, includeCommands);
          if (neighborCount < birthCounts.size() && birthCounts.get(neighborCount)) {
            birthBlock(block);
            checkForPotentialCommand(block, distanceSquared);
          }
        }
      }
    } else if (includeCommands
        && blockMaterial == Material.COMMAND
        && commandName != null
        && commandName.length() > 1) {
      // Absorb nearby commands of the same name.
      BlockState commandData = block.getState();
      if (commandData != null && commandData instanceof CommandBlock) {
        CommandBlock commandBlock = ((CommandBlock) commandData);
        if (commandBlock.getName().equals(commandName)) {
          block.setType(deathMaterial);
          if (DEBUG) {
            controller.getLogger().info("CONSUMED clone at " + block.getLocation().toVector());
          }
        }
      }
    }

    return true;
  }