Merge pull request #117 from scooterboo/patch-9

Now with 50% more seelies
This commit is contained in:
Alexander Hartmann 2024-04-30 22:18:11 +02:00 committed by GitHub
commit bffaf4f956
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 149 additions and 20 deletions

View File

@ -16,6 +16,7 @@ public class RoutePoint {
private float waitTime; //optional
private float targetVelocity; //optional
private boolean hasReachEvent; //optional
private boolean reachStop; //optional
// rotRoundReachDir //optional Pos with optional values
// rotRoundLeaveDir //optional Pos with optional values

View File

@ -8,6 +8,7 @@ import emu.grasscutter.data.excels.GadgetData;
import emu.grasscutter.game.ability.AbilityManager;
import emu.grasscutter.game.entity.gadget.*;
import emu.grasscutter.game.entity.gadget.platform.BaseRoute;
import emu.grasscutter.game.entity.gadget.platform.ConfigRoute;
import emu.grasscutter.game.entity.interfaces.ConfigAbilityDataAbilityEntity;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EntityIdType;
@ -187,6 +188,14 @@ public class EntityGadget extends EntityBaseGadget implements ConfigAbilityDataA
.setSourceEntityId(this.getId()));
}
@Override
public void afterCreate(List<Player> players) {
if (this.getMetaGadget() != null && !this.getMetaGadget().isStartRoute()) return;
if (this.routeConfig == null) return;
this.routeConfig.startRoute(this.getScene());
players.forEach(p -> p.sendPacket(new PacketPlatformStartRouteNotify(this)));
}
@Override
public void onRemoved() {
super.onRemoved();
@ -225,9 +234,12 @@ public class EntityGadget extends EntityBaseGadget implements ConfigAbilityDataA
return false;
}
if(routeConfig.isStarted()){
if (routeConfig.isStarted()) {
return true;
}
schedulePlatform();
getScene().broadcastPacket(new PacketSceneTimeNotify(getScene()));
routeConfig.startRoute(getScene());
getScene().broadcastPacket(new PacketPlatformStartRouteNotify(this));
@ -235,14 +247,42 @@ public class EntityGadget extends EntityBaseGadget implements ConfigAbilityDataA
return true;
}
public boolean schedulePlatform() {
if (!(routeConfig instanceof ConfigRoute configRoute)) {
return false;
}
var route = this.getScene().getSceneRouteById(configRoute.getRouteId());
if (route == null) {
return false;
}
var points = route.getPoints();
//restart platform if at end and told to start
if (configRoute.getStartIndex() == points.length - 1) {
configRoute.setStartIndex(0);
}
val currIndex = configRoute.getStartIndex();
if (currIndex == 0) {
this.getScene().callPlatformEvent(this.getId());
}
double distance = points[currIndex].getPos().computeDistance(points[currIndex + 1].getPos());
double time = 1000 * distance / points[currIndex].getTargetVelocity();
time += this.getScene().getSceneTime();
this.getScene().getScheduledPlatforms().put(this.getId(), time);
return true;
}
public boolean stopPlatform(){
if(routeConfig == null){
return false;
}
if(!routeConfig.isStarted()){
return true;
}
this.getScene().getScheduledPlatforms().remove(this.getId());
routeConfig.stopRoute(getScene());
getScene().broadcastPacket(new PacketPlatformStopRouteNotify(this));

View File

@ -235,6 +235,13 @@ public abstract class GameEntity {
}
/**
* Called right after this entity is added to the world
*/
public void afterCreate(List<Player> players) {
}
public void onRemoved() {
}

View File

@ -15,6 +15,7 @@ public abstract class BaseRoute {
@Getter @Setter private Position startRot;
@Getter @Setter private int startSceneTime;
@Getter @Setter private int stopSceneTime;
@Getter @Setter private int startIndex;
BaseRoute(Position startRot, boolean isStarted, boolean isActive) {
this.startRot = startRot;
@ -24,8 +25,8 @@ public abstract class BaseRoute {
BaseRoute(SceneGadget gadget) {
this.startRot = new Position(gadget.getRot());
this.isStarted = gadget.isStartRoute();
this.isActive = gadget.isStartRoute();
this.isStarted = false;
this.isActive = true;
}
public static BaseRoute fromSceneGadget(SceneGadget sceneGadget) {
@ -38,22 +39,15 @@ public abstract class BaseRoute {
}
public boolean startRoute(Scene scene) {
if (this.isStarted) {
return false;
}
this.isStarted = true;
this.isActive = true;
this.startSceneTime = scene.getSceneTime()+300;
this.startSceneTime = scene.getSceneTime();
return true;
}
public boolean stopRoute(Scene scene) {
if (!this.isStarted) {
return false;
}
this.isStarted = false;
this.isActive = false;
this.startSceneTime = scene.getSceneTime();
this.stopSceneTime = scene.getSceneTime();
@ -95,6 +89,7 @@ public abstract class BaseRoute {
if (!isStarted) {
result.setStopSceneTime(stopSceneTime);
}
result.setStartIndex(startIndex);
return result;
}
}

View File

@ -5,6 +5,7 @@ import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GameDepot;
import emu.grasscutter.data.binout.SceneNpcBornEntry;
import emu.grasscutter.data.binout.routes.Route;
import emu.grasscutter.data.binout.routes.RouteType;
import emu.grasscutter.data.excels.*;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.avatar.Avatar;
@ -14,6 +15,7 @@ import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.entity.gadget.GadgetWorktop;
import emu.grasscutter.game.entity.gadget.platform.ConfigRoute;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.TeamInfo;
import emu.grasscutter.game.props.*;
@ -89,6 +91,7 @@ public class Scene {
private boolean weatherLoaded = false;
@Getter private final GameEntity sceneEntity;
@Getter @Setter private Map<Integer, Double> scheduledPlatforms = new ConcurrentHashMap<>();
public Scene(World world, SceneData sceneData) {
this.world = world;
@ -264,12 +267,13 @@ public class Scene {
public synchronized void addEntity(GameEntity entity) {
addEntityDirectly(entity);
broadcastPacket(new PacketSceneEntityAppearNotify(entity));
entity.afterCreate(this.players);
}
public synchronized void addEntityToSingleClient(Player player, GameEntity entity) {
addEntityDirectly(entity);
player.sendPacket(new PacketSceneEntityAppearNotify(entity));
entity.afterCreate(List.of(player));
}
public void addEntities(Collection<? extends GameEntity> entities) {
@ -295,7 +299,10 @@ public class Scene {
entities.forEach(this::addEntityDirectly);
chopped(entities.stream().toList(), 100).forEach(l -> broadcastPacket(new PacketSceneEntityAppearNotify(l, visionType)));
chopped(entities.stream().toList(), 100).forEach(l -> {
broadcastPacket(new PacketSceneEntityAppearNotify(l, visionType));
l.forEach(x -> x.afterCreate(this.players));
});
}
private GameEntity removeEntityDirectly(GameEntity entity) {
@ -342,6 +349,7 @@ public class Scene {
entity != player.getTeamManager().getCurrentAvatarEntity()).toList();
player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_MEET));
entities.forEach(x -> x.afterCreate(List.of(player)));
}
public void handleAttack(AttackResult result) {
@ -432,9 +440,11 @@ public class Scene {
this.entities.values().forEach(e -> e.onTick(getSceneTimeSeconds()));
checkPlatforms();
checkNpcGroup();
finishLoading();
checkPlayerRespawn();
if (this.tickCount % 10 == 0) {
broadcastPacket(new PacketSceneTimeNotify(this));
}
@ -600,6 +610,7 @@ public class Scene {
if (!toAdd.isEmpty()) {
toAdd.forEach(this::addEntityDirectly);
broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_BORN));
toAdd.forEach(x -> x.afterCreate(this.players));
}
if (!toRemove.isEmpty()) {
toRemove.forEach(this::removeEntityDirectly);
@ -945,6 +956,77 @@ public class Scene {
return dungeonManager != null ? dungeonManager.getDungeonData().getId() : 0;
}
private void checkPlatforms() {
val curTime = this.getSceneTime();
var iter = scheduledPlatforms.entrySet().iterator();
while (iter.hasNext()) {
val entry = iter.next();
val key = entry.getKey();
val value = entry.getValue();
if (value < curTime) {
scheduledPlatforms.remove(key);
val entity = getEntityById(key);
// Deleted entity
if (entity == null) return;
// Not a platform
if (!(entity instanceof EntityGadget entityGadget)) return;
// No configRoute
if (!(entityGadget.getRouteConfig() instanceof ConfigRoute configRoute)) return;
// No route in file
val route = this.getSceneRouteById(configRoute.getRouteId());
if (route == null) return;
val points = route.getPoints();
// Increment the index
var index = 1 + entityGadget.getRouteConfig().getStartIndex();
if (index == points.length) index = 0;
entityGadget.getRouteConfig().setStartIndex(index);
// Update position
entity.getPosition().set(points[index].getPos());
// If the point has a Reach Event:
if (points[index].isHasReachEvent()) {
callPlatformEvent(key);
}
//if there is a Reach Stop, or we have reached the end, call stop
if (points[index].isReachStop() || (index == points.length - 1 /*&& route.getType().equals(RouteType.OneWay)*/)) {
entityGadget.stopPlatform();
//otherwise, schedule the next one.
} else {
double distance;
if (index == points.length - 1 && route.getType().equals(RouteType.Loop)) {
distance = points[index].getPos().computeDistance(points[0].getPos());
} else {
distance = points[index].getPos().computeDistance(points[index + 1].getPos());
}
double time = 1000 * distance / points[index].getTargetVelocity();
scheduledPlatforms.put(key, value + time);
}
}
}
}
public boolean callPlatformEvent(int entityId) {
val entity = getEntityById(entityId);
if (entity == null) return false;
if (!(entity instanceof EntityGadget entityGadget)) return false;
if (!(entityGadget.getRouteConfig() instanceof ConfigRoute configRoute)) return false;
val groupId = entityGadget.getGroupId();
val configId = entityGadget.getConfigId();
val routeId = configRoute.getRouteId();
val index = configRoute.getStartIndex();
this.scriptManager.callEvent(new ScriptArgs(groupId, EventType.EVENT_PLATFORM_REACH_POINT, configId, routeId)
.setParam3(index)
.setEventSource(configId));
return true;
}
public WeatherArea getWeatherArea(Position position) {
val data = GameData.getWeatherAreaPointData().get(getId());
if(data == null) return null;

View File

@ -1016,7 +1016,7 @@ public class SceneScriptManager {
}
logger.warn("trying to cancel a timer that's not active {} {}", groupID, source);
return 1;
return 0;
}
// todo use killed monsters instead of spawned entites for check?

View File

@ -1466,7 +1466,8 @@ public class ScriptLibHandler extends BaseHandler implements org.anime_game_serv
public int SetPlatformRouteId(GroupEventLuaContext context, int entityConfigId, int routeId) {
logger.info("[LUA] Call SetPlatformRouteId {} {}", entityConfigId, routeId);
val entity = context.getSceneScriptManager().getScene().getEntityByConfigId(entityConfigId, context.getCurrentGroup().getGroupInfo().getId());
val scene = context.getSceneScriptManager().getScene();
val entity = scene.getEntityByConfigId(entityConfigId, context.getCurrentGroup().getGroupInfo().getId());
if(entity == null){
return 1;
}
@ -1486,7 +1487,10 @@ public class ScriptLibHandler extends BaseHandler implements org.anime_game_serv
}
configRoute.setRouteId(routeId);
context.getSceneScriptManager().getScene().broadcastPacket(new PacketPlatformChangeRouteNotify(entityGadget));
configRoute.setStartSceneTime(scene.getSceneTime());
configRoute.setStartIndex(0);
entityGadget.schedulePlatform();
scene.broadcastPacket(new PacketPlatformChangeRouteNotify(entityGadget));
return 0;
}