How do you get the x/y/z location of a block now from the block state? @simon816 since I know you’re active right now?
BlockState
doesn’t store that information. There can be multiple locations per state (e.g a dirt block can be in more than one place at a time).
You may want to look into keeping a reference to the Location
object rather than the state directly.
Sorry, I was using something along the lines of
event.getBlock().getBlockX()
however, the getBlockX() method was removed from BlockState, so I was trying to figure out how to get the x location from the BlockState in a new way, but didn’t realize I could just do
event.getLocation().getBlockX()
Silly mistake, sorry, and thanks for the help @simon816
There are two ways (though currently one at present time due to a missing Key for Velocity):
Optional<Vector3d> optional = entity.get(Keys.VELOCITY);
if (optional.isPresent()) {
entity.set(Keys.VELOCITY, optional.get().add(0,1,0);
}
Or
Optional<VelocityData> optional = entity.get(VelocityData.class);
if (optional.isPresent()) {
final Value<Vector3d> velocityVal = optional.get().velocity();
entity.offer(optional.get().set(velocityVal.set(velocityVal.get().add(0,1,0)));
}
OR! (this is a bit more interesting if you’re just wanting to transform the velocity)
entity.transform(Keys.VELOCITY, new Function<Vector3d, Vector3d>() {
@Override
public Vector3d apply(Vector3d input) {
return input.add(0,1,0);
}
}
It’s threadsafe to manipulate a DataManipulator
or Value
after you’ve retrieved it from a ValueContainer
/DataHolder
, but it is NOT thread safe to offer it back or retrieve it.
The primary reason for immutable stuff is so that events can especially rely on original values/manipulators not being meddled with, let alone being passed to external threads.
With the Causes PR I’m hoping to provide a feasible way to damage an entity with some provided stuff, including a DamageSource
and a bunch of other things.
You can use the AttributeData
which currently needs to have some work done due to the Attributes API being a near impossible to actually implement, let alone use.
A custom DataManipulator is quite literally a DataManipulator
that you want to be able to store custom data that isn’t already covered by the Data API. So, for example, if you have some Location
s of "home"s you want to attach to a Player
, you definitely could do so by providing your own custom DataManipulator
. Alternatively, you could go the more traditional route of storing that stuff to a config file. More examples of custom DataManipulators can range from storing custom information that you don’t want to be storing onto a map, linking to various entities and possibly having to manage references without leaking them, because you’ll know that the custom data is persisted.
This wont compile:
Optional<VelocityData> optional = entity.get(VelocityData.class);
because:
error: incompatible types: no instance(s) of type variable(s) T exist so that com.google.common.base.Optional<T> conforms to java.util.Optional<VelocityData>
Optional<VelocityData> optional = entity.get(VelocityData.class);
^
where T is a type-variable:
T extends DataManipulator<?,?> declared in method <T>get(Class<T>)
1 error
any ideas @gabizou?
SpongeAPI uses Guava’s Optional
(com.google.common.base.Optional
) but you’ve imported Java 8’s Optional
(java.util.Optional
).
Simply change the import.
How I can create custom data and assign it to the player? I messed around with it for a while, but I’m not quite sure that I understand everything about it.
A copy/pasteable working code example that converts a given location into a polishedgranite block would be an excellent example of how to sort out the new api features, given there are numerous examples on converting/adding blocks from the former methods but none of them work nor have obvious ways to be modified to have analogous results. Have tried too many ways that keep spitting out cant-do errors, would be nice to see how well modified the new system to streamline the process. Assuming it has to do with offering a key/value but can’t get it.
public void setBlockToPolishedGranite(Location block){ //doesnt matter what block was in this location, set it.
// please to -do here please
}
How to save arbitrary data to Players/blocks? Is this possible?
I believe so, unless I was mistaken. I just don’t know how to do this. Will this be documented at some point in the near future?
Is that for the old Data API or the new one?
It was for the old one, but will need to be partially rewritten to reflect the new Data API
How would one change the respawn location of a player in a given world?
With RespawnLocationData
.
/**
* Returns true if the data was set successfully.
*/
public boolean setRespawnLocation(Player player, Location<World> location) {
RespawnLocationData data = player.getOrCreate(RespawnLocationData.class).get(); // It's a player, assume it can be created
data.respawnLocation().put(location.getExtent().getUniqueId(), location.getPosition());
return player.offer(data).getType() == DataTransactionResult.Type.SUCCESS;
}
@simon816 Thanks for the reply, I noticed setRespawnLocation in the docs, however, when I get an instance of RespawnLocationData from the player it doesn’t have that method. I’m assuming it hasn’t been merged yet or some changes are being made, however I can accomplish the same thing using the implementation you have provided, thanks!
That’s on the PlayerRespawnEvent
, the event has some convenience methods, including getRespawnLocation()
and setNewRespawnLocation(Location)
Ah, my mistake for not clarifying, I was trying to accomplish this outside of the PlayerRespawnEvent. Thanks.
Thanks for the comments guys.
Be patient with us, we are getting data implemented as fast as we can. Loving the interest so far.
I just tried velocity data on the latest sponge, after updating my dependencies, and I get this error:
java.lang.NoSuchFieldError: VELOCITY
This is my code:
Optional<Vector3d> optional = entity.get(Keys.VELOCITY);
if (optional.isPresent()) {
final Vector3d velocity = optional.get();
double x = velocity.getX();
double y = velocity.getY();
double z = velocity.getZ();
getLogger().info("Vector3d<" + x + ", " + y + ", " + z + ">");
}
any thoughts?