Skip to content

Commit bc87dd6

Browse files
committed
Initial work on the entity component system
1 parent ee1745f commit bc87dd6

89 files changed

Lines changed: 4563 additions & 255 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/main/java/org/lanternpowered/server/entity/LanternEntity.java

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,13 @@
3939
import org.lanternpowered.server.data.ValueCollection;
4040
import org.lanternpowered.server.data.key.LanternKeys;
4141
import org.lanternpowered.server.data.property.AbstractPropertyHolder;
42-
import org.lanternpowered.server.entity.event.DamagedEntityEvent;
43-
import org.lanternpowered.server.entity.event.EntityEvent;
42+
import org.lanternpowered.server.entity.event.EntityDamagedShardevent;
4443
import org.lanternpowered.server.entity.living.player.LanternPlayer;
4544
import org.lanternpowered.server.event.CauseStack;
4645
import org.lanternpowered.server.event.LanternEventContextKeys;
4746
import org.lanternpowered.server.game.LanternGame;
4847
import org.lanternpowered.server.game.registry.type.entity.EntityTypeRegistryModule;
49-
import org.lanternpowered.server.network.entity.EntityProtocolType;
48+
import org.lanternpowered.server.shards.AbstractComponentHolder;
5049
import org.lanternpowered.server.text.LanternTexts;
5150
import org.lanternpowered.server.util.Quaternions;
5251
import org.lanternpowered.server.world.LanternWorld;
@@ -103,7 +102,7 @@
103102

104103
import javax.annotation.Nullable;
105104

106-
public class LanternEntity implements Entity, IAdditionalDataHolder, AbstractPropertyHolder {
105+
public class LanternEntity extends AbstractComponentHolder implements Entity, IAdditionalDataHolder, AbstractPropertyHolder {
107106

108107
@SuppressWarnings("unused")
109108
private static boolean bypassEntityTypeLookup;
@@ -133,11 +132,6 @@ public class LanternEntity implements Entity, IAdditionalDataHolder, AbstractPro
133132
// The scale of the entity
134133
private Vector3d scale = Vector3d.ONE;
135134

136-
/**
137-
* The entity protocol type of this entity.
138-
*/
139-
@Nullable private EntityProtocolType<?> entityProtocolType;
140-
141135
/**
142136
* The state of the removal of this entity.
143137
*/
@@ -243,19 +237,6 @@ public Direction getHorizontalDirection(Direction.Division division) {
243237
return Direction.getClosest(getHorizontalDirectionVector(), division);
244238
}
245239

246-
@Nullable
247-
public EntityProtocolType<?> getEntityProtocolType() {
248-
return this.entityProtocolType;
249-
}
250-
251-
public void setEntityProtocolType(@Nullable EntityProtocolType<?> entityProtocolType) {
252-
if (entityProtocolType != null) {
253-
checkArgument(entityProtocolType.getEntityType().isInstance(this),
254-
"The protocol type %s is not applicable to this entity.");
255-
}
256-
this.entityProtocolType = entityProtocolType;
257-
}
258-
259240
/**
260241
* Gets whether this {@link Entity} is dead, should
261242
* only be implemented by a {@link Living}.
@@ -280,6 +261,16 @@ void postDestructEvent(DestructEntityEvent event) {
280261
}
281262
}
282263

264+
/**
265+
* Gets whether this {@link LanternEntity} currently
266+
* exists in a {@link LanternWorld}.
267+
*
268+
* @return Exists in world
269+
*/
270+
public boolean existsInWorld() {
271+
return this.world != null;
272+
}
273+
283274
@Override
284275
public boolean isRemoved() {
285276
return this.removeState != null;
@@ -696,6 +687,8 @@ public Random getRandom() {
696687
return this.random;
697688
}
698689

690+
private static final EntityDamagedShardevent ENTITY_DAMAGED_SHARDEVENT = new EntityDamagedShardevent();
691+
699692
@Override
700693
public boolean damage(double damage, DamageSource damageSource) {
701694
checkNotNull(damageSource, "damageSource");
@@ -743,7 +736,7 @@ public boolean damage(double damage, DamageSource damageSource) {
743736
final double exhaustion = damageSource.getExhaustion();
744737
getValue(Keys.EXHAUSTION).ifPresent(value -> offer(Keys.EXHAUSTION, Math.min(value.getMaxValue(), value.get() + exhaustion)));
745738
}
746-
triggerEvent(DamagedEntityEvent.of());
739+
getShardeventBus().post(ENTITY_DAMAGED_SHARDEVENT);
747740
return true;
748741
}
749742

@@ -836,13 +829,4 @@ public DataHolder copy() {
836829
public EntityArchetype createArchetype() {
837830
return null;
838831
}
839-
840-
/**
841-
* Triggers the {@link EntityEvent} for this entity.
842-
*
843-
* @param event The event
844-
*/
845-
public void triggerEvent(EntityEvent event) {
846-
getWorld().getEntityProtocolManager().triggerEvent(this, event);
847-
}
848832
}

src/main/java/org/lanternpowered/server/entity/LanternItem.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
import com.flowpowered.math.vector.Vector3d;
2929
import org.lanternpowered.server.data.ValueCollection;
3030
import org.lanternpowered.server.data.key.LanternKeys;
31-
import org.lanternpowered.server.entity.event.CollectEntityEvent;
31+
import org.lanternpowered.server.entity.component.NetworkComponent;
32+
import org.lanternpowered.server.entity.event.CollectEntityShardevent;
3233
import org.lanternpowered.server.event.CauseStack;
3334
import org.lanternpowered.server.event.LanternEventContextKeys;
3435
import org.lanternpowered.server.inventory.IInventory;
@@ -80,7 +81,7 @@ private static final class EffectHolder {
8081

8182
public LanternItem(UUID uniqueId) {
8283
super(uniqueId);
83-
setEntityProtocolType(EntityProtocolTypes.ITEM);
84+
addComponent(NetworkComponent.class).get().setEntityProtocolType(EntityProtocolTypes.ITEM);
8485
setBoundingBoxBase(BOUNDING_BOX_BASE);
8586
}
8687

@@ -229,7 +230,7 @@ private void tryToPickupItems() {
229230
added = itemStack.getQuantity();
230231
}
231232
if (added != 0 && entity instanceof Living) {
232-
triggerEvent(new CollectEntityEvent((Living) entity, added));
233+
getShardeventBus().post(new CollectEntityShardevent((Living) entity, added));
233234
}
234235
if (rejected == null || isRemoved()) {
235236
itemStack = null;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* This file is part of LanternServer, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) LanternPowered <https://www.lanternpowered.org>
5+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
6+
* Copyright (c) contributors
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the Software), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
package org.lanternpowered.server.entity.component;
27+
28+
import org.lanternpowered.server.shards.Component;
29+
import org.spongepowered.api.entity.Entity;
30+
import org.spongepowered.api.entity.ai.Goal;
31+
import org.spongepowered.api.entity.ai.GoalType;
32+
import org.spongepowered.api.entity.ai.task.AITask;
33+
import org.spongepowered.api.entity.living.Agent;
34+
35+
import java.util.Optional;
36+
37+
import javax.annotation.Nullable;
38+
39+
public interface AIComponent extends Component {
40+
41+
/**
42+
* Gets the current target, usually according to the various
43+
* {@link AITask}s that are acting on this agent.
44+
*
45+
* @return The target entity, if available
46+
*/
47+
Optional<Entity> getTarget();
48+
49+
/**
50+
* Sets the current target, usually to bypass what the {@link AITask}s are
51+
* deciding to be the target.
52+
*
53+
* @param target The target entity, or null
54+
*/
55+
void setTarget(@Nullable Entity target);
56+
57+
/**
58+
* Gets a {@link Goal} based on the {@link GoalType}.
59+
*
60+
* @param type GoalType to lookup
61+
* @param <T> Inferred agent type
62+
* @return The goal or {@link Optional#empty()} if not found.
63+
*/
64+
<T extends Agent> Optional<Goal<T>> getGoal(GoalType type);
65+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* This file is part of LanternServer, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) LanternPowered <https://www.lanternpowered.org>
5+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
6+
* Copyright (c) contributors
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the Software), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
package org.lanternpowered.server.entity.component;
27+
28+
import com.google.inject.Inject;
29+
import org.lanternpowered.server.entity.LanternEntity;
30+
import org.lanternpowered.server.entity.event.TrackerChangeShardevent;
31+
import org.lanternpowered.server.shards.Component;
32+
import org.lanternpowered.server.shards.Holder;
33+
import org.lanternpowered.server.shards.OnAttach;
34+
import org.lanternpowered.server.shards.OnUpdate;
35+
import org.lanternpowered.server.shards.event.ShardeventListener;
36+
import org.spongepowered.api.boss.BossBar;
37+
import org.spongepowered.api.boss.BossBarColors;
38+
import org.spongepowered.api.boss.BossBarOverlays;
39+
import org.spongepowered.api.boss.ServerBossBar;
40+
import org.spongepowered.api.data.key.Keys;
41+
import org.spongepowered.api.text.Text;
42+
43+
import java.util.List;
44+
45+
public final class BossComponent implements Component {
46+
47+
@Inject @Holder private LanternEntity holder;
48+
49+
private Text defaultName;
50+
private ServerBossBar bossBar;
51+
52+
@OnAttach
53+
private void onAttach() {
54+
// Get a name we can fallback to if there is no display name
55+
this.defaultName = Text.of(this.holder.getType().getTranslation());
56+
// Create the boss bar
57+
this.bossBar = ServerBossBar.builder()
58+
.overlay(BossBarOverlays.NOTCHED_12) // Is this OK?
59+
.color(BossBarColors.PURPLE)
60+
.visible(true)
61+
.build();
62+
// TODO: More boss bar settings?
63+
}
64+
65+
/**
66+
* Updates the {@link BossBar} for the
67+
* given health and max health.
68+
*/
69+
private void update() {
70+
final double health = this.holder.get(Keys.HEALTH).get();
71+
final double maxHealth = this.holder.get(Keys.MAX_HEALTH).get();
72+
// Update the percent of the boss bar
73+
this.bossBar.setPercent((float) Math.min(health / maxHealth, 1.0));
74+
// Update the name of the boss bar
75+
this.bossBar.setName(this.holder.get(Keys.DISPLAY_NAME).orElse(this.defaultName));
76+
}
77+
78+
@OnUpdate(pulseRate = 5)
79+
private void onUpdate() {
80+
if (this.bossBar.getPlayers().isEmpty()) { // Only update if necessary.
81+
return;
82+
}
83+
update();
84+
}
85+
86+
/**
87+
* Is called when trackers are added.
88+
*/
89+
@SuppressWarnings("unchecked")
90+
@ShardeventListener
91+
private void onTrackerChangeAdd(TrackerChangeShardevent.Add event) {
92+
if (this.bossBar.getPlayers().isEmpty()) {
93+
update(); // Update things when no players were present
94+
}
95+
this.bossBar.addPlayers((List) event.getPlayers());
96+
}
97+
98+
/**
99+
* Is called when trackers are removed.
100+
*/
101+
@SuppressWarnings("unchecked")
102+
@ShardeventListener
103+
private void onTrackerChangeRemove(TrackerChangeShardevent.Remove event) {
104+
this.bossBar.removePlayers((List) event.getPlayers());
105+
}
106+
107+
/**
108+
* Gets the {@link BossBar} that will be
109+
* displayed to surrounding players.
110+
*
111+
* @return The boss bar
112+
*/
113+
public BossBar getBossBar() {
114+
return this.bossBar;
115+
}
116+
117+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* This file is part of LanternServer, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) LanternPowered <https://www.lanternpowered.org>
5+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
6+
* Copyright (c) contributors
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the Software), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
package org.lanternpowered.server.entity.component;
27+
28+
import org.lanternpowered.server.shards.Component;
29+
import org.spongepowered.api.entity.Entity;
30+
31+
import java.util.Optional;
32+
33+
public interface ExplosiveComponent extends Component {
34+
35+
/**
36+
* The direct detonator of the {@link ExplosiveComponent},
37+
* if present.
38+
*
39+
* @return The detonator
40+
*/
41+
Optional<Entity> getDetonator();
42+
43+
/**
44+
* Detonates this explosive as soon as possible.
45+
*/
46+
void detonate();
47+
}

0 commit comments

Comments
 (0)