I am using citizensAPI to spawn and manipulate NPC. The code is as follows.
I am trying to find the nearest block of type JUNGLE_WOOD in the radius of 20.
package org.mineacademy.orion.npctest;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.ai.PathStrategy;
import net.citizensnpcs.api.hpastar.Tile;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.npc.ai.AStarNavigationStrategy;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.mineacademy.fo.command.SimpleCommand;
public class BlockFinder extends SimpleCommand {
public BlockFinder(){
super("finder");
}
public void onCommand() {
checkConsole();
NPC npc= CitizensAPI.getNPCRegistry().createNPC(EntityType.VILLAGER,"cutter");
Player player=getPlayer();
npc.spawn(player.getTargetBlock(null, 5).getLocation().add(3, 3, 0));
//add location and setTarget to that location.
Location finalLoc=newLocation(npc,player);
npc.setProtected(false);
npc.faceLocation(finalLoc);
npc.getNavigator().setTarget(finalLoc);
}
public Location newLocation(NPC npc, Player player) {
double r =25;
double x=npc.getEntity().getLocation().getX();
double y=npc.getEntity().getLocation().getY();
double z=npc.getEntity().getLocation().getZ();
int minx=(int)(x-r);
int miny=(int)(y-r);
int minz=(int)(z-r);
int maxx=(int)(x+r);
int maxy=(int)(y+r);
int maxz=(int)(z+r);
Location nloc=new Location(npc.getEntity().getWorld(),x,y,z);
for(int rx=minx;rx<=maxx;rx++) {
for (int ry = miny; ry <= maxy; ry++) {
for (int rz = minz; rz <= maxz; rz++) {
Block block = player.getWorld().getBlockAt(rx, ry, rz);
if (block.getType() == Material.JUNGLE_WOOD) {
nloc.setX(rx);
nloc.setY(ry);
nloc.setZ(rz);
return nloc;
}
}
}
}
return nloc;
}
}
The NPC spawns properly but sometimes it does not move at all, and otherwise it spins or just moves a couple of meters and stops.
Does anyone know any fix so that I am able to move the NPC along a path to that block?
First of all, you should check if the NPC exists : NPC.isSpawned() - boolean
Then, you should trigger this part after the NPCSpawnEvent (https://jd.citizensnpcs.co/net/citizensnpcs/api/event/NPCSpawnEvent.html) :
Location finalLoc=newLocation(npc,player);
npc.setProtected(false);
npc.faceLocation(finalLoc);
npc.getNavigator().setTarget(finalLoc);
By the way, you can google it : https://www.spigotmc.org/threads/citizens-api-problem-walking-npc.365712/
I found this, really useful.
Related
I apologize in advance if anything isn't clear enough.
While attempting to check if an index value exists of an array in D, I encountered an unexpected RangeError.
I'm attempting to make an array check function, and I wouldn't know how to check for a value in an array in D.
In C, I would use arr[index].
Execution Error:
core.exception.RangeError#test.d(6): Range violation
----------------
??:? _d_arrayboundsp [0x100f855d9]
??:? int checkArray(immutable(char)[][]) [0x100f6715e]
??:? _Dmain [0x100f7832e]
Code:
import std.stdio;
import std.stdc.stdlib;
import core.sys.posix.unistd;
int checkArray(string[] arr) {
if (!arr[1]) {
return 0;
} else {
return 1;
}
}
void main() {
string base = "test";
string[] cut = base.split(" ");
checkArray(cut);
}
I currently use a Mac, and used DMD to compile the source.
Should I try some other checker, other than arr[index]?
Firstly, never ever check if an index is within an array by dereferencing it.
bool check(int[] arr, size_t index)
{
return index < arr.length;
}
unittest {
assert(!check([], 0));
assert(!check([1], 1));
assert(check([1, 2], 1));
auto testArray = new int[1024];
//testArray[testArray.length] = 1; // this throws, so check should return false
assert(!check(testArray, testArray.length));
}
enjoy
hi so im making a hierarchy sort of structure for a robotic walker to make the number of servos manageable and im trying to create a Limb class that contains a number of servo classes (yes im using the built in servo Library but i want to also tweak the offset,scale ect. of the value for calibration purposes) anyway hear is my code.
the problem is the Limb Class initiator (bottom 4 lines) i usually dont like just straight up asking for the correct line of code and prefer to figure it out but iv tried everything i can think of
PS i apolagise for any crap spelling and thanks
class ServoConfig{
public :
float Offset;
float Scale;
bool Inversed;
Servo ServoV;
ServoConfig (float InOffset, float InScale, bool InInversed,int Pin){
float Offset = InOffset;
float Scale = InScale;
bool Inversed = InInversed;
ServoV.attach(Pin);
}
void WriteToServo(float Angle){
if (Inversed){
ServoV.write((180-Angle)/Scale + Offset);
}
else{
ServoV.write(Angle/Scale + Offset);
}
}
};
class Limb{
ServoConfig Servos[];
Limb (ServoConfig InServos[]){
ServoConfig Servos[] = InServos;
}
};
It's not so easy in C++ and on Arduino it's even harder.
But first you have loads of mistakes in code. For example shadowing class attibutes by local variables:
ServoConfig (float InOffset, float InScale, bool InInversed,int Pin) {
float Offset = InOffset; // this will create new local variable and hides that one in class with the same name
float Scale = InScale; // this too
bool Inversed = InInversed; // and this too
The same is in Limb constructor, but it doesn't work anyways.
And how it can be working? You can use something like this:
#include <Servo.h>
class ServoConfig {
public :
float Offset;
float Scale;
bool Inversed;
Servo ServoV;
ServoConfig (float InOffset, float InScale, bool InInversed,int Pin)
: Offset { InOffset }
, Scale { InScale }
, Inversed { InInversed }
{
ServoV.attach(Pin); // it might have to be attached in setup() as constructors are called before main()
}
void WriteToServo(float Angle){
if (Inversed) {
ServoV.write((180-Angle)/Scale + Offset);
} else {
ServoV.write(Angle/Scale + Offset);
}
}
};
ServoConfig servos[] = {{10,10,0,9},{0,1,0,10}}; // this makes servos of size two and calls constructors
class Limb {
public:
ServoConfig * servos_begin;
ServoConfig * servos_end;
Limb(ServoConfig * beg, ServoConfig * end)
: servos_begin { beg }
, servos_end { end }
{;}
ServoConfig * begin() { return servos_begin; }
ServoConfig * end() { return servos_end; }
size_t size() { return servos_end - servos_begin; }
};
// much better than using sizeof(array)/sizeof(array[0]):
template <class T, size_t size> size_t arraySize(T(&)[size]) { return size; }
// create and construct Limb instance:
Limb limb { servos, servos + arraySize(servos)};
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.println("starting...");
for (ServoConfig & servo : limb) { // this uses begin() and end() methods
servo.WriteToServo(90);
}
// or directly with array[]
for (ServoConfig & servo : servos) {
servo.WriteToServo(40);
}
}
I am working on creating a program that reads strings in from a data file calles "palindromes.txt" and which stores the strings in a one-dimensional array. The program is supposed to inspect each of the strings and detrmine whether or not each one is a pallindrome. It's supposed to show output on the screen and into a file called "output.txt".
The problem i'm having is that I can't figure out how to get the input/output correct and i'm not sure the best way to utilize the arrays.
Very new to this, please advise if you can. :)
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class Palindromes2
{
public static boolean isPalindrome(String dirtystr)
{
dirtystr = dirtystr.toLowerCase().replaceAll("[^a-zA-Z]+","");
int length = dirtystr.length(), middle = length / 2;
for (int x = 0; x < middle; x++)
if (dirtystr.charAt(x) != dirtystr.charAt(length - x - 1))
return false;
return true;
}
public static void main(String[] args) throws IOException
{
File inputFile = new File("output.txt");
try (Scanner scanner = new Scanner(inputFile))
{
while (scanner.hasNextLine())
{
String dirtystr = scanner.nextLine();
if (isPalindrome(dirtystr))
{
System.out.println(dirtystr + " IS a palindrome.");
}
else
{
System.out.println(dirtystr + " is NOT a palindrome.");
}
}
}
}
}
I'm making a simple program in D that loops around the files present inside a given folder and calculate the MD5 of the file. I have got this program working easily with no problem.
I recently learned more about parallelism and thought that my little program would benefit greatly from it.
I changed the loop around the files to a parallel one, but now it is working weird.
The program starts reading files and calculating their MD5, but sometimes, executing close(file) throw an exception with error code 0. Sometimes, there is just an
Object.Error: Access violation
Sometimes the program just freezes, sometimes it simply crashes.
When I remove the file opening (the loop then basically just print the filename to the console) it works well.
The time it takes for the program to crash is maybe linked to the size of workUnitSize. If not set (default 100), it crashes or stop working after processing around 30-40 files. If I set it to 1, it stops after 2 to 10 files.
Here is the smallest reproducible code I've extracted :
import std.md5;
import std.stdio;
import std.file;
import std.conv;
import std.getopt;
import std.string;
import std.process;
import std.parallelism;
import std.exception;
struct Entry
{
string name;
ubyte[16] md5;
}
int ChunkStep = 4096;
void main(string[] args)
{
string folder1 = args[1];
string folder2 = args[2];
Entry[] entries1;
foreach (name; parallel(dirEntries(folder1, SpanMode.breadth), 1)) // not working
{
if(name.isFile())
{
entries1 ~= Entry(name ,mdFile(name));
}
}
writeln(folder1," has ",entries1.length, " entries");
Entry[] entries2;
foreach (string name; dirEntries(folder2, SpanMode.breadth)) //working fine
{
if(name.isFile())
{
entries2 ~= Entry(name ,mdFile(name));
}
}
writeln(folder2," has ", entries2.length, " entries");
}
/// Digests a file and prints the result.
ubyte[16] mdFile(string filename)
{
MD5_CTX context;
ubyte[16] digest;
context.start();
File f = File(filename,"r");
foreach (buffer; f.byChunk(ChunkStep))
context.update(buffer);
context.finish(digest);
try{
f.close();
}
catch(ErrnoException e)
{
writeln(e.errno);
}
writefln("MD5 (%s) = %s", filename, digestToString(digest));
return digest;
}
I'm using Dmd2.064.2 on Windows 7 64b with a Intel Q6600 (quad core).
Do you use 32bit version of dmd?
update:
seems on windows there is some bug with byChunk (rawRead). So you can use std.stream instead.
import std.md5;
import std.stdio;
import std.file;
import std.conv;
import std.getopt;
import std.string;
static import std.stream;
import std.process;
import std.parallelism;
import std.exception;
struct Entry
{
string name;
ubyte[16] md5;
}
enum ChunkStep = 4096;
void main(string[] args)
{
string folder1 = args[1];
string folder2 = args[2];
Entry[] entries1;
foreach (name; parallel(dirEntries(folder1, SpanMode.breadth), 1)) // not working
{
if(name.isFile())
{
entries1 ~= Entry(name ,mdFile(name));
}
}
writeln(folder1," has ",entries1.length, " entries");
}
/// Digests a file and prints the result.
ubyte[16] mdFile(string filename)
{
MD5_CTX context;
ubyte[16] digest;
context.start();
std.stream.File f = new std.stream.File(filename);
byte[ChunkStep] buffer;
size_t len;
while((len = f.readBlock(buffer.ptr, ChunkStep)) > 0) {
context.update(buffer.ptr[0 .. len]);
}
context.finish(digest);
f.close();
writefln("MD5 (%s) = %s", filename, digestToString(digest));
return digest;
}
Sorry this is probably a dumb question. I'm kinda new to coding and I'm using Processing, which is based off Java.
I have an array of 5 rectangle objects in my main program
for (int i = 0; i < portals.length; i++)
{
portals[i] = new Portals();
}
when displayed, I call this method from my Portals class
void display()
{
rectMode(CENTER);
rect(xLoc, yLoc, rad, 30);
}
the xLoc and yLoc are determined randomly. How would you go about assigning a number (like an identity) to each object in the array so that I can refer to that specific rectangles's location and where would I put it in my code?
You can have a filed in the class that makes it identifiable. Like:
public class Portals {
int xLoc;
int yLoc;
String name;
...
public Portals(String name){
this.name = name;
}
public String getName(){
return name;
}
}
Then you can try to access by name in array
for (int i = 0; i < portals.length; i++)
{
portals[i] = new Portals("Name");
}
for (Portals p : portals){
if ("Name".equals(p.getname()) {
// do somthing
}
}
Or you can use a Map. But that may be more advanced than your knowledge, so I won't give code. But that's another suggestion.
Edit: with Map
Map<String, Portals> map = new HashMap<String, Portals>();
Key Value
map.put("nameForPortal", new Portals());
map.put("anotherNameForPortal", new Portals());
// To access the portal, you can get by the key
Portals p = map.get("nameForPortal");