API - Minecraft-Maxmc/KingdomsX-ChineseTranslation GitHub Wiki
王国的API是经过再三考虑后才编写的. 该API非常稳定且易懂 任何拥有Java基础的人都可以使用该API. 如果有需要, API 会毫不犹豫地被更改, 因此某些插件可能会在API更新后中断.
不要忘记将 Kingdoms
加入到你的 plugin.yml
-> softdepend
你需要将 version
替换为 Spigot 中的版本, 像这样:
Note: 由于某些构建中的某些本地更改, 您可能会收到有关 XSeries 的一些错误. 因此, 如果出现该错误, 只需排除 XSeries.
Maven
<dependency>
<groupId>com.github.cryptomorin</groupId>
<artifactId>kingdoms</artifactId>
<version>version</version>
<scope>provided</scope>
</dependency>
Gradle
repositories {
mavenCentral()
}
dependencies {
compileOnly 'com.github.cryptomorin:kingdoms:version'
}
Gradle Kotlin DSL
repositories {
mavenCentral()
}
dependencies {
compileOnly("com.github.cryptomorin:kingdoms:version")
}
手动 你可以从 Discord 服务器上免费下载到该插件.
所有的对象都针对 equals
和 hashCode
方法优化过, 所以这些方法可以使用, 但是 强烈建议只选择特定字段来用来比较. 例如, 永远不要在比较Lands 的时候使用equls
, they have optimized methods, but not when you're trying to compare them normally. Refer to Optimization section for more info.
You can figure out most of the things you're looking for just by following your IDE's auto completion. Take a look at some examples at the end of the page.
90% of the API is thread-safe unless the method is dealing with Bukkit related operations. Most of the API is also marked with Nullability Annotations.
You can get a kingdom player by either using an OfflinePlayer
or UUID
object.
They're both the same, none is accurate or performs better than the other.
Player player = ...;
KingdomPlayer kp = KingdomPlayer.getKingdomPlayer(player);
You can get a kingdom/nation either by its UUID or name. It's always recommended to use the UUID.
Kingdom kingdom = Kingdom.getKingdom(name/id);
Nation nation = Nation.getNation(name/id);
It's also useful to know that Kingdom
and Nation
objects both inherit from a class called Group
which shares the most common methods for these two objects. These two objects also have some methods that are exactly the same as Group
, but with a different name. E.g. Nation#getCapitalId()
and Kingdom#getKingId()
are equivelant to Group#getOwner()
90% of the time you don't even need to get a kingdom this way, most of the kingdom objects have a way to get to the kingdom object. They're all named getKingdom()
Notice that some objects have getKingdomId()
method, this method is highly recommended instead of getKingdom()
for performance reasons.
For example instead of doing KingdomPlayer#getKingdom().equals(Kingdom)
do Kingdom#isMember(Player)
or KingdomPlayer#getKingdomId().equals(kingdomId)
Kingdom
objects are cached for KingdomPlayer
and Land
.
KingdomPlayer kp = ...;
if (kp.hasKingdom()) { // A better way is to use kp.getKingdom() and check if it's null. Same for nations.
Kingdom kingdom = kp.getKingdom();
if (kingdom.hasNation()) {
Nation nation = kingdom.getNation();
// ...
}
}
Kingdoms save locations (other than kingdom and nation home locations) in SimpleLocation
and SimpleChunkLocation
objects for memory performance. You can use the Object#of()
method of these objects to get the location for your right object. Using the correct one can improve performance.
-
SimpleLocation is the simplified version of
Location
-
SimpleChunkLocation is the simplified version of
Chunk
These two objects have most of the useful methods (even more) of Location
and Chunk
A land that's null
is a land that has absolutely no (kingdom related) data attached to it.
A land that's not null
, but is also not claimed (!isClaimed()
) doesn't have a kingdom, but it might have protected chests, turrets, structures or other data in it.
Player player = ...;
SimpleChunkLocation chunk = SimpleChunkLocation.of(player.getLocation());
Land land = chunk.getLand();
// or simply
Land land = Land.getLand(player.getLocation());
if (land == null) return;
Structure structure = land.getStructure();
SimpleLocation = simpLocation = SimpleLocation.of(player.getLocation());
Turret turret = land.getTurrets().get(simpLocation);
if (land.isClaimed()) {
Kingdom kingdom = land.getKingdom();
// ...
}
Top kingdoms and nations depend on their might.
Make sure to use these methods properly and use them asynchronous when possible.
// Kingdoms
Collection<Kingdom> kingdoms = DataHandler.get().getKingdomManager().getKingdoms();
// Nations
Collection<Nation> nations = DataHandler.get().getNationManager().getNations();
// Lands
Collection<Land> lands = DataHandler.get().getLandManager().getLands();
In this example we get the top 10 kingdoms/nations.
// Kingdoms
List<Kingdom> kingdoms = DataHandler.get().getKingdomManager().getTopKingdoms(0, 10);
// Nations
List<Nation> kingdoms = DataHandler.get().getNationManager().getTopNations(0, 10);
Block block = ...;
Optional<ProtectionSign> protectionSign = ProtectionSign.getProtection(block);
if (!protectionSign.isPresent()) return;
ProtectionSign protection = protectionSign.get();
List<UUID> group = protection.getGroup();
You can register your own custom permissions for ranks to use! It's really easy.
public enum SomePermission implements KingdomPermission {
FIRST, SECOND, THIRD;
}
Note: If you change the enum names, the plugin will not recognize the permission and the data will be discarded
Then you'll have to register it with:
try {
KingdomPermissionFactory.registerPermissions(plugin, SomePermission.values());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Note: You cannot register permissions after the server is fully loaded because the plugin loads data after that and if it can't find your permission, it'll discard the data. If you attempt to register permissions after that, you'll get a IllegalAccessError
, so a good place to register your permissions is onEnable()
If you attempt to register a permission that already exists or use the kingdoms plugin instance, you'll get a IllegalArgumentException
After you registered your permissions. You can do:
KingdomPlayer kp = ...;
kp.hasPermission(SomePermission.FIRST)
kp.getRank().getPermissions().add(SomePermission.SECOND);
// If other plugins want to use your permission,
// but don't want to import your JAR for some reasons, they can use:
KingdomPermission permission = KingdomPermissionFactory.getPermission("THIRD");
Here I'll give you some examples for when and which methods to use for your specific case.
This first example applies to getLand(), getKingdom(), getNation() and etc...
KingdomPlayer kp = ...;
// DONT
if (kp.hasKingdom()) {
if (kp.getKingdom().hasAttribute(...) && kp.getKingdom().equals(...))
}
// DO
Kingdom kingdom = kp.getKingdom();
if (kingdom != null) {
if (kingdom.hasAttribute(...) && kingdom.equals(...))
}
Checking if a land belongs to a kingdom.
Scenario 1: You have a location (Location, SimpleChunkLocation, SimpleLocation, Block and etc...) and a Kingdom instance.
// Or convert it to SimpleChunkLocation of other types.
SimpleChunkLocation chunk = ...;
Kingdom kingdom = ...;
// DONT
Land land = chunk.getLand();
if (land != null && land.isClaimed && land.getKingdom().equals(kingdom))
// DO
if (kingdom.isClaimed(chunk))
Scenario 2: You have a Land instance and the Kingdom ID.
Land land = ...;
UUID kingdomId = ...;
// DONT
Kingdom kingdom = Kingdom.getKingdom(kingdomId);
if (kingdom.isClaimed(land.getLocation()))
// OR
if (kingdom.getId().equals(land.getKingdomId()))
// DO
if (land.getKingdomId().equals(kingdomID))
Comparing Lands
Land one = ...;
Land two = ...;
// DONT
if (one.equals(two))
// DO
if (one.simpleEquals(two))
Saving data
// DONT
Map<Land, ...> map = new HashMap<>();
Set<Land> set = new HashSet<>();
// DO
Map<SimpleChunkLocation, ...> map = new HashMap<>();
Set<SimpleChunkLocation> set = new HashSet<>();
// DONT
Map<Turret, ...> map = new HashMap<>();
Set<Turret> set = new HashSet<>();
// DO
Map<SimpleLocation, ...> map = new HashMap<>();
Set<SimpleLocation> set = new HashSet<>();
// This applies for structures which need to be saved with their SimpleLocation as well and
// Kingdom and KingdomPlayer which need to saved with their UUID.
Making custom turrets and structures are more complicated because of the abstraction level.
Turrets and Structures have 2 different main objects, 3 for turrets.
When it's mentioned that a class is a another x class
it means that class extends x class
.
- KingdomItem: Unlike the name, each turret and structure that's placed is called a kingdom item. They handle data for each turret and structure such as their location, ammo, holograms and etc...
- KingdomItemType: The main mechanics for the turrets and structures that are the same type. They handle turrets and structures GUIs, how their data is saved and how turrets activate.
- KingdomItemStyle: The modified version of (extends) KingdomItemType for turrets. They modify how turrets GUI works and how they activate.
KingdomItem class for turrets is called Turret and for structures it's called Structure.
KingdomItemType class for turret types is called TurretType and for structures it's called StructureType
So, each Structure & Turret is a KingdomItem and each KingdomItem has a KingdomItemType.
For turrets, each Turret has a KingdomItemStyle which is technically a KingdomItemType but with modified options which you can find the in turret config.
Structures cannot have a KingdomItemStyle because their mechanics are so unique that there is nothing special about them to be modified.
Let's understand KingdomItemStyle and KingdomItemType a little more.
Go to Plugins/Kingdoms/Turrets
folder in your server. You'll see all the turret files. Each of these files are a KingdomItemStyle and their KingdomItemType that they're modifying is the type
property inside the file.
Now this means that servers can make their own KingdomItemStyle without needing to code anything.
That makes it more easier to understand.
For example, by default there is a turret style named arrow
.yml that uses the type arrow
in the Turrets folder.
In this case, our KingdomItem is a RangedTurret which is a Turret.
And our KingdomItemStyle is a RangedTurretType which is a TurretType which is a KingdomItemType.
Yes, in this case both of our KingdomItemType and KingdomItemStyle are called arrow
which is allowed, but they're not the same.
As an example for structures, take a look at powercell
structure in structures.yml
:
- KingdomItem is a Structure.
- KingdomItemType is a StructurePowercell which is a StructureType
But now for an Extractor
:
- KingdomItem is an Extractor which is a Structure
- KingdomItemType is a StructureExtractor which is a StructureType
Now you might ask why extractors have their own kingdom item object but not powercells? Because extractors save data such as the last collected time milliseconds, but powercells don't need to store any extra information.
IMPORTANT:
If the turret or structure you're making has additional data (that is not temporary or transient) other than the ones provided in the superclass, you MUST override its KingdomItem hashCode() method in addition to calling its super.hashCode()
while building the hash. If you don't, the server might not save your data to the data files.
Example of overriding hashcode methods correctly for a kingdom item like extractors that has extra data:
@Override
public int hashCode() {
int prime = 31;
int result = 15;
result = prime * result + super.hashCode();
result = prime * result + lastCollector.hashCode();
result = prime * result + Long.hashCode(lastCollected);
return result;
}
Now let's make a complicated turret.
public class TurretGhasterBlaster extends RangedTurret { // RangedTurret extend Turret and Turret extends KingdomItem<Turret>
private int blasts = 0;
private int durability = 1000;
public GhasterBlasterTurret(KingdomItemStyle type, SimpleLocation location) {
super(type, location);
}
@Override
public void activate(LivingEntity target, Kingdom kingdom) {
super.activate(target, kingdom);
target.setVelocity(new Vector(0, blasts, 0));
blasts++;
durability--;
if (durability == 0) remove(getLand());
}
@Override
public int hashCode() {
int prime = 31;
int result = 15;
result = prime * result + super.hashCode();
result = prime * result + blasts;
result = prime * result + durability;
return result;
}
public int getBlasts() { return blasts; }
public void setBlasts(int blasts) { this.blasts = blasts; }
}
public class TurretGhasterBlaster extends TurretTypeRanged { // TurretTypeRanged extend TurretType and TurretType extends KingdomItemType<Turret>
public TurretGhasterBlaster () {
super("ghasterblaster", false, true);
}
@Override
public boolean activate(TurretActivateEvent event) { ... }
@Override
public void serialize(JsonObject json, Turret turret, Type type, JsonSerializationContext context) {
GhasterBlaster rangedTurret = (GhasterBlaster) turret;
super.serialize(json, turret, type, context);
json.addProperty("ammo", rangedTurret.getAmmo());
json.addProperty("blasts", rangedTurret.getBlasts());
}
@Override
public Turret deserialize(KingdomItemStyle style, JsonObject json, Type type, JsonDeserializationContext context) throws JsonParseException {
GhasterBlaster turret = new GhasterBlaster(style, null);
turret.setLevel(json.get("level").getAsInt());
turret.setAmmo(json.get("ammo").getAsInt());
turret.setBlasts(json.get("blasts").getAsInt());
turret.setHolograms(context.deserialize(json.get("holograms"), new TypeToken<List<UUID>>() {
}.getType()));
return turret;
}
@Override
public Turret build(KingdomItemStyle style, SimpleLocation location, KingdomPlayer kp, NBTWrappers.NBTTagCompound tag) {
Turret turret = new GhasterBlaster(style, location);
if (tag != null) turret.setData(tag);
return turret;
}
Now let's register our turret type.
register(new TurretGhasterBlaster());
Our style is automatically registered.
Now in our Turrets folder let's add blaster.yml
file
name: "&0Ghaster&cBlaster"
type: ghasterblaster
cost: 300
max-level: 3
hologram:
1:
lines:
- "&8-=[ &0Ghaster&cBlaster &8]=-"
height: 1
placing:
whitelist: true
blocks:
- CONTAINS:FENCE
- CONTAINS:WALL
range: 7 + lvl
cooldown: 8 - lvl
max-targets: min(2, 1 + (lvl + 1))
max-ammo: lvl * 2000
upgrade-cost: lvl * 80
fire: 1
particle: ~
effects:
1: []
projectile:
1: FIREBALL
speed: 1 + (lvl * 0.8)
damage: lvl * 4
block:
1: PLAYER_HEAD
skull:
1: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNmNlZGVjMDRkMjM4MGNkNzcwMjdmOWQ0NDQ1NWM5OGI3ZWRjNWY2NjRjYTBkZDMwYTYxMDY5MDM5MTUzOTFkYiJ9fX0="
2: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQzNzI4NTc5MzEzMWVkNzU1ZjFiMDA5OGYyOWRkNDEzZDY3NjU2YjYyMDg3Mjg5MzU0OTJiNDliMWQwZDRiYSJ9fX0="
item:
1:
name: "&0Ghaster&cBlaster Turret"
material: FIRE_CHARGE
lore:
- "&6A similar turret as flame"
- "turret but really fast with multiple targets."
- ""
- "&9Attributes&8:"
- "&7⚫ &2Level&8: &6%level_roman%"
- "&7⚫ &2Ammo&8: &6%ammo%"
- "&7⚫ &2Range&8: &6%range%"
- "&7⚫ &2Max Targets&8: &6%max_targets%"
- "&7⚫ &2Max Ammo&8: &6%max_ammo%"
- "&7⚫ &2Cooldown&8: &6%cooldown%"
- "&7⚫ &2Speed&8: &6%speed%"
- "&7⚫ &2Damage&8: &6%damage%"
It's similar to Bukkit's metadata except it's specifically made for kingdoms and stays after restarts.
All the main kingdom objects support metadata:
- KingdomPlayer
- Land
- Kingdom
- Nation
Metadata is simply a map with the key as a string and the value as an object.
To modify this map, use getMetadata()
method. Some custom data objects might not be stored correctly. Please check your data once to see if the data is stored the way you expected or it might lead to some data corruptions.
Event | Description |
---|---|
KingdomCreateEvent |
Called when a kingdom is created via test /k create (Kingdom(UUID id, UUID king) constructor) |
KingdomDisbandEvent |
Called when a kingdom is disbanded either from /k disband, taxes or inactivities. (Kingdom#disband() ) |
KingdomRelationshipChangeEvent |
Called when a kingdom relationship changes from commands. (Kingdom#acceptRelationShipRequest(...)
|
KingdomSetHomeEvent |
Called when a player sets/changes their kingdom home (Kingdom#setHome() ) |
OpenProtectedBlockEvent |
Called when a player opens a protected block using protection signs. |
ChampionAbilityEvent |
Called when a champion uses an ability. |
KingdomInvadeAttackEvent |
Called when either the champion or the player attack each other. |
KingdomInvadeEndEvent |
Called when an invasion ends with the invasion results and reason. |
KingdomPreInvadeEvent |
Called before the cooldown of /k invade starts. |
KingdomInvadeEvent |
Called after the cooldown of /k invade command. |
KingdomJoinEvent |
Called when someone join a kingdom. This is also called right before KingdomCreateEvent when someone creates a kingdom. |
KingdomLeaveEvent |
Called when someone leaves a kingdom. |
KingdomResourcePointDonateEvent |
Called when a player donates resource points to a kingdom. Specifically called when KingdomPlayer#donate is used. |
LandChangeEvent |
Called when someone goes from a land to another land. This is basically a chunk change event but with kingdoms data. (for performance reason. |
LandLoadEvent |
When a kingdom land data loads. (When chunks load) Note that this will not do anything if the land is null (with no data attached to it) |
LandUnloadEvent |
When a kingdom land data unloads. (When chunks unload) Note that this will not do anything if the land is null (with no data attached |
ClaimLandEvent |
When someone claims a land for a kingdom. |
UnclaimLandEvent |
When someone unclaims a land for a kingdom. Called even for /k unclaimall |
NexusMoveEvent |
After someone used /k nexus to move their nexus. |
KingdomItemBreakEvent<? extends KingdomItem<?>> |
When someone breaks a structure or a turret block either from the GUI or manually. |
KingdomItemPlaceEvent<? extends KingdomItem<?>> |
When someone places a structure or a turret. |
KingdomItemInteractEvent<? extends KingdomItem<?>> |
When someone interacts with a structure or a turret. |
TurretActivateEvent |
When a turret wants to target an entity. |
We're going to take a look at some examples that are only a little harder to find for developers.
Getting all the kingdom allies.
List<Kingdom> allies = damagerKingdom.getKingdomsWithRelation(KingdomRelation.ALLY);
Checking if player has permission in kingdom or nation.
Player player = ...;
KingdomPlayer kp = new KingdomPlayer(player);
if (kp.hasKingdom()) {
kp.hasPermission(DefaultKingdomPermission.HOME);
if (kp.getKingdom().hasNation()) kp.hasNationPermission(DefaultKingdomPermission.HOME); // Spawn
}
Joining a kingdom.
Player player = ...;
KingdomPlayer kp = KingdomPlayer.getKingdomPlayer(player);
Kingdom kingdom = Kingdom.getKingdom(...);
kp.joinKingdom(kingdom);
Opening /k map for players. This method is completely async.
Player player = ...;
KingdomPlayer kp = KingdomPlayer.getKingdomPlayer(player);
kp.showMap(player);
// or
KingdomsMap.display(player, height, width, kp);
If you're using EntityDamageByEntityEvent
event, simply check if the event is cancelled. Kingdoms uses LOW
event priority to make it easier for other plugins.
To check if two players can PvP each other in any circumstances you can use the following code. This will consider all the kingdom features and configured options.
Note: It's important that which player is the damager and which is the victim.
Player damager = ...;
Player victim = ...;
boolean canFight = PvPManager.canFight(damager, victim);
A manual way to do this, and get to know how canFight method works.
Player damager = ...;
Player victim = ...;
KingdomPlayer damagerKp = KingdomPlayer.getKingdomPlayer(damager);
if (damagerKp.isAdmin() || !damagerKp.hasKingdom()) return true;
KingdomPlayer victimKp = KingdomPlayer.getKingdomPlayer(victim);
if (!victimKp.hasKingdom()) return true;
if (damagerKp.isPvp() && victimKp.isPvp()) return true;
Kingdom damagerKingdom = damagerKp.getKingdom();
Kingdom victimKingdom = victimKp.getKingdom();
return !victimKingdom.hasAttribute(damagerKingdom, KingdomRelation.Attribute.CEASEFIRE);
Checking if an entity is a kingdom spawned mob:
LivingEntity entity = ...;
boolean isKingdomMob = PvPManager.isKingdomMob(entity);
Player player = ...;
Location location = player.getLocation();
KingdomPlayer kp = KingdomPlayer.getKingdomPlayer(player);
if (!kp.hasKingdom()) return;
// WorldGuard Support
if (ServiceHandler.isLocationInRegion(loc)) return;
SimpleChunkLocation simpLocation = new SimpleChunkLocation(loc);
Land land = Land.getLand(location);
if (land != null && !land.isClaimed()) kp.getKingdom().claim(kp, simpLocation);
You don't need to use everything from here. Take what you need.
Collection<ItemStack> items = ...;
List<ItemStack> stacked = XItemStack.stack(items);
Player player = ...;
KingdomPlayer kp = KingdomPlayer.getKingdomPlayer(player);
// You can leave the second argument as null if you don't want to modify anything.
Pair<Long, List<ItemStack>> result = Kingdom.convertToResourcePoints(stacked, (item, leftOvers) -> {
// Return null if you want the item to be handled normally according to the config.
// You can also add a part of the item to the leftOvers list. You don't need to clone the item.
// If you return a nonnull value, the item will not be added to the leftOvers list and the amount will be added to the result.
});
long added = result.getKey();
List<ItemStack> leftOvers = result.getValue();
KingdomResourcePointDonateEvent event = kp.donate(added, stacked, leftOvers);
if (!event.isCancelled()) {
added = event.getAmount();
leftOvers = event.getLeftOvers();
kingdom.addResourcePoints(added);
if (leftOvers != null) XItemStack.giveOrDrop(player, true, leftOvers.toArray(new ItemStack[0]));
}
OfflinePlayer player = ...;
KingdomPlayer kp = KingdomPlayer.getKingdomPlayer(player);
Kingdom kingdom = kp.getKingdom();
Pair<Boolean, Double> result = kingdom.payTaxes(player);
result.getKey(); // Could pay?
result.getValue(); // Tax amount the player paid.
if (!kingdom.hasNation()) return;
Nation nation = kingdom.getNation();
nation.payTaxes(kingdom);
Same process for structures.
Block block = ...;
SimpleLocation location = new SimpleLocation(block);
// You can leave the kp and nbt data as null if you don't have it.
Land land = location.toSimpleChunkLocation().getLand();
Turret turret = type.getType().build(type, location, kp, nbt);
land.getTurrets().put(location, turret);
turret.spawnHologram(land.getKingdom());
ItemStack item = ...;
NBTWrappers.NBTTagCompound nbt = ItemNBT.getTag(item);
nbt = nbt.getCompound(Kingdoms.NBT);
// It's not a kingdom item!
if (nbt == null) return;
String tag = nbt.get(StructureType.METADATA, NBTType.STRING);
// It's a structure.
if (tag != null) return;
tag = nbt.get(TurretType.METADATA, NBTType.STRING);
if (tag != null) return;// It's a turret.
// If it ever passed the above check then I don't know what the hell you did to the item.
Checking if a player is invading or an entity is a champion.
Entity entity = ...;
if (entity.hasMetadata(Invasion.METADATA)) {
if (entity instanceof Player) // invader
else // champion
}
Getting the land under attack.
// From players:
Player player = ...;
KingdomPlayer kp = KingdomPlayer.getKingdomPlayer(player);
Land land = kp.getInvading();
// From entity (champions):
Entity entity = ...;
Land land = Invasion.getLandFromSession(entity);
Getting invasion stuff from land.
Land land = ...;
Invasion invasion = land.getInvasion();
if (invasion.getChampion().isValid()) invasion.end(KingdomInvadeEndEvent.InvasionResult.TIMES_UP);
Replacing an ability for champions (you cannot create a new one)
public class ChampionAbilityBoom extends ChampionAbility implements Listener {
public ChampionAbilityResistance() {
super(ChampionUpgrade.THOR);
}
@EventHandler
public void onDamage(KingdomInvadeAttackEvent event) {
if (cantUse(event.getInvasion().getDefender().getKingdom())) return;
if (event.isAttackerChampion()) return;
if (!MathUtils.hasChance(10) return;
if (callEvent(event.getInvasion())) return;
Entity champion = event.getEntity();
Player player = event.getInvasion().getInvader().getPlayer();
// A much better way of getting the player is:
player = (Player) event.getDamager();
player.getWorld().createExplosion(player.getLocation(), 3f);
}
}
new ChampionAbilityBoom();
Checking relation attributes between two kingdoms needs to follow an order.
Kingdom defender = ...;
Kingdom attacker = ...;
boolean hasAttribute = defender.hasAttribute(attacker, ...);
This code will check the relation attributes for attacker
, so for example if defender
disabled CEASEFIRE
attribute for allies and attacker
is allies with defender
, hasAttribute
will return false. Since the attributes are checked from attacker
and only defender
changed that attribute. Now it'll return true the other way around. If defender is the attacker, and the attacker is the defender. (it doesn't mean that defender and attacker instances switch, we just switch the order that we check their attribute):
boolean hasAttribute = attacker.hasAttribute(defender, ...);
Since the order matters, sometimes you'll have to do a few extra checks before using the kingdom objects. To make it easier and safer, you can use the following method:
KingdomRelation.Attribute attribute = ...;
boolean hasAttribute = attribute.hasAttribute(kingdom, otherKingdom);
Listening to KingdomItemEvent
s is a little special since they use generic types.
In this example, we're going to use KingdomItemPlaceEvent
// If you want to listen to either structures or turrets.
@EventHandler
public void onPlace(KingdomItemPlaceEvent<?> event) {
if (event.getKingdomItem() instanceof Structure) {
Structure structure = (Structure) event.getKingdomItem();
}
if (event.getKingdomItem() instanceof Turret) {
Turret structure = (Turret) event.getKingdomItem();
}
}
// Listening to only one type of kingdom item. In this example, structures.
@EventHandler
public void onPlace(KingdomItemPlaceEvent<Structure> event) {
if (!(event.getKingdomItem() instanceof Structure)) return; // Yes, this line is still necessary.
Structure structure = event.getKingdomItem();
}