mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-25 11:57:35 +00:00
Merge remote-tracking branch 'origin/development' into development
This commit is contained in:
commit
6e309b6fee
@ -68,7 +68,7 @@ class MlgmXyysd_Animation_Company_Proxy:
|
|||||||
]
|
]
|
||||||
|
|
||||||
def request(self, flow: http.HTTPFlow) -> None:
|
def request(self, flow: http.HTTPFlow) -> None:
|
||||||
if flow.request.host in self.LIST_DOMAINS:
|
if flow.request.pretty_host in self.LIST_DOMAINS:
|
||||||
if USE_SSL:
|
if USE_SSL:
|
||||||
flow.request.scheme = "https"
|
flow.request.scheme = "https"
|
||||||
else:
|
else:
|
||||||
|
@ -158,6 +158,8 @@ public final class Grasscutter {
|
|||||||
|
|
||||||
// Generate handbooks.
|
// Generate handbooks.
|
||||||
Tools.createGmHandbooks(false);
|
Tools.createGmHandbooks(false);
|
||||||
|
// Generate gacha mappings.
|
||||||
|
Tools.generateGachaMappings();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start servers.
|
// Start servers.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package emu.grasscutter.command;
|
package emu.grasscutter.command;
|
||||||
|
|
||||||
|
import emu.grasscutter.game.world.Position;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.regex.*;
|
import java.util.regex.*;
|
||||||
@ -54,4 +55,78 @@ public class CommandHelpers {
|
|||||||
});
|
});
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float parseRelative(String input, Float current) {
|
||||||
|
if (input.contains("~")) { // Relative
|
||||||
|
if (!input.equals("~")) { // Relative with offset
|
||||||
|
current += Float.parseFloat(input.replace("~", ""));
|
||||||
|
} // Else no offset, no modification
|
||||||
|
} else { // Absolute
|
||||||
|
current = Float.parseFloat(input);
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Position parsePosition(
|
||||||
|
String inputX, String inputY, String inputZ, Position curPos, Position curRot) {
|
||||||
|
Position offset = new Position();
|
||||||
|
Position target = new Position(curPos);
|
||||||
|
if (inputX.contains("~")) { // Relative
|
||||||
|
if (!inputX.equals("~")) { // Relative with offset
|
||||||
|
target.addX(Float.parseFloat(inputX.replace("~", "")));
|
||||||
|
}
|
||||||
|
} else if (inputX.contains("^")) {
|
||||||
|
if (!inputX.equals("^")) {
|
||||||
|
offset.setX(Float.parseFloat(inputX.replace("^", "")));
|
||||||
|
}
|
||||||
|
} else { // Absolute
|
||||||
|
target.setX(Float.parseFloat(inputX));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputY.contains("~")) { // Relative
|
||||||
|
if (!inputY.equals("~")) { // Relative with offset
|
||||||
|
target.addY(Float.parseFloat(inputY.replace("~", "")));
|
||||||
|
}
|
||||||
|
} else if (inputY.contains("^")) {
|
||||||
|
if (!inputY.equals("^")) {
|
||||||
|
offset.setY(Float.parseFloat(inputY.replace("^", "")));
|
||||||
|
}
|
||||||
|
} else { // Absolute
|
||||||
|
target.setY(Float.parseFloat(inputY));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputZ.contains("~")) { // Relative
|
||||||
|
if (!inputZ.equals("~")) { // Relative with offset
|
||||||
|
target.addZ(Float.parseFloat(inputZ.replace("~", "")));
|
||||||
|
}
|
||||||
|
} else if (inputZ.contains("^")) {
|
||||||
|
if (!inputZ.equals("^")) {
|
||||||
|
offset.setZ(Float.parseFloat(inputZ.replace("^", "")));
|
||||||
|
}
|
||||||
|
} else { // Absolute
|
||||||
|
target.setZ(Float.parseFloat(inputZ));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!offset.equal3d(Position.ZERO)) {
|
||||||
|
return calculateOffset(target, curRot, offset);
|
||||||
|
} else {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Position calculateOffset(Position pos, Position rot, Position offset) {
|
||||||
|
// Degrees to radians
|
||||||
|
float angleZ = (float) Math.toRadians(rot.getY());
|
||||||
|
float angleX = (float) Math.toRadians(rot.getY() + 90);
|
||||||
|
|
||||||
|
// Calculate offset based on current position and rotation
|
||||||
|
return new Position(
|
||||||
|
pos.getX()
|
||||||
|
+ offset.getZ() * (float) Math.sin(angleZ)
|
||||||
|
+ offset.getX() * (float) Math.sin(angleX),
|
||||||
|
pos.getY() + offset.getY(),
|
||||||
|
pos.getZ()
|
||||||
|
+ offset.getZ() * (float) Math.cos(angleZ)
|
||||||
|
+ offset.getX() * (float) Math.cos(angleX));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,9 @@ import lombok.Setter;
|
|||||||
label = "spawn",
|
label = "spawn",
|
||||||
aliases = {"drop", "s"},
|
aliases = {"drop", "s"},
|
||||||
usage = {
|
usage = {
|
||||||
"<itemId> [x<amount>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
|
"<itemId> [x<amount>] [blk<blockId>] [grp<groupId>] [cfg<configId>] [<x> <y> <z>] [<rotX> <rotY> <rotZ>]",
|
||||||
"<gadgetId> [x<amount>] [state<state>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
|
"<gadgetId> [x<amount>] [state<state>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] [<x> <y> <z>] [<rotX> <rotY> <rotZ>]",
|
||||||
"<monsterId> [x<amount>] [lv<level>] [ai<aiId>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>"
|
"<monsterId> [x<amount>] [lv<level>] [ai<aiId>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] [<x> <y> <z>] [<rotX> <rotY> <rotZ>]"
|
||||||
},
|
},
|
||||||
permission = "server.spawn",
|
permission = "server.spawn",
|
||||||
permissionTargeted = "server.spawn.others")
|
permissionTargeted = "server.spawn.others")
|
||||||
@ -53,14 +53,23 @@ public final class SpawnCommand implements CommandHandler {
|
|||||||
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
|
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Position pos = new Position(targetPlayer.getPosition());
|
||||||
|
Position rot = new Position(targetPlayer.getRotation());
|
||||||
|
|
||||||
switch (args.size()) {
|
switch (args.size()) {
|
||||||
|
case 7:
|
||||||
|
try {
|
||||||
|
rot.setX(CommandHelpers.parseRelative(args.get(4), rot.getX()));
|
||||||
|
rot.setY(CommandHelpers.parseRelative(args.get(5), rot.getY()));
|
||||||
|
rot.setZ(CommandHelpers.parseRelative(args.get(6), rot.getZ()));
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
CommandHandler.sendMessage(
|
||||||
|
sender, translate(sender, "commands.execution.argument_error"));
|
||||||
|
} // Fallthrough
|
||||||
case 4:
|
case 4:
|
||||||
try {
|
try {
|
||||||
float x, y, z;
|
pos = CommandHelpers.parsePosition(args.get(1), args.get(2), args.get(3), pos, rot);
|
||||||
x = Float.parseFloat(args.get(1));
|
|
||||||
y = Float.parseFloat(args.get(2));
|
|
||||||
z = Float.parseFloat(args.get(3));
|
|
||||||
param.pos = new Position(x, y, z);
|
|
||||||
} catch (NumberFormatException ignored) {
|
} catch (NumberFormatException ignored) {
|
||||||
CommandHandler.sendMessage(
|
CommandHandler.sendMessage(
|
||||||
sender, translate(sender, "commands.execution.argument_error"));
|
sender, translate(sender, "commands.execution.argument_error"));
|
||||||
@ -77,6 +86,8 @@ public final class SpawnCommand implements CommandHandler {
|
|||||||
sendUsageMessage(sender);
|
sendUsageMessage(sender);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
param.pos = pos;
|
||||||
|
param.rot = rot;
|
||||||
|
|
||||||
MonsterData monsterData = GameData.getMonsterDataMap().get(param.id);
|
MonsterData monsterData = GameData.getMonsterDataMap().get(param.id);
|
||||||
GadgetData gadgetData = GameData.getGadgetDataMap().get(param.id);
|
GadgetData gadgetData = GameData.getGadgetDataMap().get(param.id);
|
||||||
@ -102,12 +113,8 @@ public final class SpawnCommand implements CommandHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double maxRadius = Math.sqrt(param.amount * 0.2 / Math.PI);
|
double maxRadius = Math.sqrt(param.amount * 0.2 / Math.PI);
|
||||||
if (param.pos == null) {
|
|
||||||
param.pos = targetPlayer.getPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < param.amount; i++) {
|
for (int i = 0; i < param.amount; i++) {
|
||||||
Position pos = GetRandomPositionInCircle(param.pos, maxRadius).addY(3);
|
pos = GetRandomPositionInCircle(param.pos, maxRadius).addY(3);
|
||||||
GameEntity entity = null;
|
GameEntity entity = null;
|
||||||
if (itemData != null) {
|
if (itemData != null) {
|
||||||
entity = createItem(itemData, param, pos);
|
entity = createItem(itemData, param, pos);
|
||||||
@ -128,12 +135,12 @@ public final class SpawnCommand implements CommandHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private EntityItem createItem(ItemData itemData, SpawnParameters param, Position pos) {
|
private EntityItem createItem(ItemData itemData, SpawnParameters param, Position pos) {
|
||||||
return new EntityItem(param.scene, null, itemData, pos, 1, true);
|
return new EntityItem(param.scene, null, itemData, pos, param.rot, 1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityMonster createMonster(
|
private EntityMonster createMonster(
|
||||||
MonsterData monsterData, SpawnParameters param, Position pos) {
|
MonsterData monsterData, SpawnParameters param, Position pos) {
|
||||||
var entity = new EntityMonster(param.scene, monsterData, pos, param.lvl);
|
var entity = new EntityMonster(param.scene, monsterData, pos, param.rot, param.lvl);
|
||||||
if (param.ai != -1) {
|
if (param.ai != -1) {
|
||||||
entity.setAiId(param.ai);
|
entity.setAiId(param.ai);
|
||||||
}
|
}
|
||||||
@ -144,16 +151,13 @@ public final class SpawnCommand implements CommandHandler {
|
|||||||
GadgetData gadgetData, SpawnParameters param, Position pos, Player targetPlayer) {
|
GadgetData gadgetData, SpawnParameters param, Position pos, Player targetPlayer) {
|
||||||
EntityBaseGadget entity;
|
EntityBaseGadget entity;
|
||||||
if (gadgetData.getType() == EntityType.Vehicle) {
|
if (gadgetData.getType() == EntityType.Vehicle) {
|
||||||
entity =
|
entity = new EntityVehicle(param.scene, targetPlayer, param.id, 0, pos, param.rot);
|
||||||
new EntityVehicle(
|
|
||||||
param.scene, targetPlayer, param.id, 0, pos, targetPlayer.getRotation());
|
|
||||||
} else {
|
} else {
|
||||||
entity = new EntityGadget(param.scene, param.id, pos, targetPlayer.getRotation());
|
entity = new EntityGadget(param.scene, param.id, pos, param.rot);
|
||||||
if (param.state != -1) {
|
if (param.state != -1) {
|
||||||
((EntityGadget) entity).setState(param.state);
|
((EntityGadget) entity).setState(param.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +211,7 @@ public final class SpawnCommand implements CommandHandler {
|
|||||||
@Setter public int def = -1;
|
@Setter public int def = -1;
|
||||||
@Setter public int ai = -1;
|
@Setter public int ai = -1;
|
||||||
@Setter public Position pos = null;
|
@Setter public Position pos = null;
|
||||||
|
@Setter public Position rot = null;
|
||||||
public Scene scene = null;
|
public Scene scene = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,24 +16,10 @@ import java.util.List;
|
|||||||
permissionTargeted = "player.teleport.others")
|
permissionTargeted = "player.teleport.others")
|
||||||
public final class TeleportCommand implements CommandHandler {
|
public final class TeleportCommand implements CommandHandler {
|
||||||
|
|
||||||
private float parseRelative(
|
|
||||||
String input, Float current) { // TODO: Maybe this will be useful elsewhere later
|
|
||||||
if (input.contains("~")) { // Relative
|
|
||||||
if (!input.equals("~")) { // Relative with offset
|
|
||||||
current += Float.parseFloat(input.replace("~", ""));
|
|
||||||
} // Else no offset, no modification
|
|
||||||
} else { // Absolute
|
|
||||||
current = Float.parseFloat(input);
|
|
||||||
}
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||||
Position pos = targetPlayer.getPosition();
|
Position pos = new Position(targetPlayer.getPosition());
|
||||||
float x = pos.getX();
|
Position rot = new Position(targetPlayer.getRotation());
|
||||||
float y = pos.getY();
|
|
||||||
float z = pos.getZ();
|
|
||||||
int sceneId = targetPlayer.getSceneId();
|
int sceneId = targetPlayer.getSceneId();
|
||||||
|
|
||||||
switch (args.size()) {
|
switch (args.size()) {
|
||||||
@ -46,9 +32,7 @@ public final class TeleportCommand implements CommandHandler {
|
|||||||
} // Fallthrough
|
} // Fallthrough
|
||||||
case 3:
|
case 3:
|
||||||
try {
|
try {
|
||||||
x = this.parseRelative(args.get(0), x);
|
pos = CommandHelpers.parsePosition(args.get(0), args.get(1), args.get(2), pos, rot);
|
||||||
y = this.parseRelative(args.get(1), y);
|
|
||||||
z = this.parseRelative(args.get(2), z);
|
|
||||||
} catch (NumberFormatException ignored) {
|
} catch (NumberFormatException ignored) {
|
||||||
CommandHandler.sendMessage(
|
CommandHandler.sendMessage(
|
||||||
sender, translate(sender, "commands.teleport.invalid_position"));
|
sender, translate(sender, "commands.teleport.invalid_position"));
|
||||||
@ -59,11 +43,10 @@ public final class TeleportCommand implements CommandHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Position target_pos = new Position(x, y, z);
|
|
||||||
boolean result =
|
boolean result =
|
||||||
targetPlayer
|
targetPlayer
|
||||||
.getWorld()
|
.getWorld()
|
||||||
.transferPlayerToScene(targetPlayer, sceneId, TeleportType.COMMAND, target_pos);
|
.transferPlayerToScene(targetPlayer, sceneId, TeleportType.COMMAND, pos);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.exists_error"));
|
CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.exists_error"));
|
||||||
@ -71,7 +54,13 @@ public final class TeleportCommand implements CommandHandler {
|
|||||||
CommandHandler.sendMessage(
|
CommandHandler.sendMessage(
|
||||||
sender,
|
sender,
|
||||||
translate(
|
translate(
|
||||||
sender, "commands.teleport.success", targetPlayer.getNickname(), x, y, z, sceneId));
|
sender,
|
||||||
|
"commands.teleport.success",
|
||||||
|
targetPlayer.getNickname(),
|
||||||
|
pos.getX(),
|
||||||
|
pos.getY(),
|
||||||
|
pos.getZ(),
|
||||||
|
sceneId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package emu.grasscutter.data;
|
package emu.grasscutter.data;
|
||||||
|
|
||||||
import emu.grasscutter.Grasscutter;
|
import emu.grasscutter.Grasscutter;
|
||||||
import emu.grasscutter.server.http.handlers.GachaHandler;
|
|
||||||
import emu.grasscutter.tools.Tools;
|
|
||||||
import emu.grasscutter.utils.*;
|
import emu.grasscutter.utils.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
@ -114,8 +112,6 @@ public class DataLoader {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Grasscutter.getLogger().error("An error occurred while trying to check the data folder.", e);
|
Grasscutter.getLogger().error("An error occurred while trying to check the data folder.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateGachaMappings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkAndCopyData(String name) {
|
private static void checkAndCopyData(String name) {
|
||||||
@ -131,16 +127,4 @@ public class DataLoader {
|
|||||||
FileUtils.copyResource("/defaults/data/" + name, filePath.toString());
|
FileUtils.copyResource("/defaults/data/" + name, filePath.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void generateGachaMappings() {
|
|
||||||
var path = GachaHandler.getGachaMappingsPath();
|
|
||||||
if (!Files.exists(path)) {
|
|
||||||
try {
|
|
||||||
Grasscutter.getLogger().debug("Creating default '" + path + "' data");
|
|
||||||
Tools.createGachaMappings(path);
|
|
||||||
} catch (Exception exception) {
|
|
||||||
Grasscutter.getLogger().warn("Failed to create gacha mappings. \n" + exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -214,6 +214,14 @@ public final class GameData {
|
|||||||
private static final Int2ObjectMap<CookRecipeData> cookRecipeDataMap =
|
private static final Int2ObjectMap<CookRecipeData> cookRecipeDataMap =
|
||||||
new Int2ObjectOpenHashMap<>();
|
new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static final Int2ObjectMap<CoopChapterData> coopChapterDataMap =
|
||||||
|
new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static final Int2ObjectMap<CoopPointData> coopPointDataMap =
|
||||||
|
new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private static final Int2ObjectMap<CompoundData> compoundDataMap = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<CompoundData> compoundDataMap = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package emu.grasscutter.data.excels;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import emu.grasscutter.data.*;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
|
@ResourceType(name = "CoopChapterExcelConfigData.json")
|
||||||
|
@Getter
|
||||||
|
@Setter // TODO: remove setters next API break
|
||||||
|
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||||
|
public class CoopChapterData extends GameResource {
|
||||||
|
@Getter(onMethod_ = @Override)
|
||||||
|
int id;
|
||||||
|
|
||||||
|
int avatarId;
|
||||||
|
// int chapterNameTextMapHash;
|
||||||
|
// int coopPageTitleTextMapHash;
|
||||||
|
// int chapterSortId;
|
||||||
|
// int avatarSortId;
|
||||||
|
// String chapterIcon;
|
||||||
|
List<CoopCondition> unlockCond;
|
||||||
|
// int [] unlockCondTips;
|
||||||
|
// int openMaterialId;
|
||||||
|
// int openMaterialNum;
|
||||||
|
// String beginTimeStr;
|
||||||
|
// int confidenceValue;
|
||||||
|
// String pointGraphPath;
|
||||||
|
// Double graphXRatio;
|
||||||
|
// Double graphYRatio;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||||
|
private static class CoopCondition {
|
||||||
|
@SerializedName(
|
||||||
|
value = "_condType",
|
||||||
|
alternate = {"condType"})
|
||||||
|
String type = "COOP_COND_NONE";
|
||||||
|
|
||||||
|
@SerializedName(
|
||||||
|
value = "_args",
|
||||||
|
alternate = {"args"})
|
||||||
|
int[] args;
|
||||||
|
}
|
||||||
|
}
|
24
src/main/java/emu/grasscutter/data/excels/CoopPointData.java
Normal file
24
src/main/java/emu/grasscutter/data/excels/CoopPointData.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package emu.grasscutter.data.excels;
|
||||||
|
|
||||||
|
import emu.grasscutter.data.*;
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
|
@ResourceType(name = "CoopPointExcelConfigData.json")
|
||||||
|
@Getter
|
||||||
|
@Setter // TODO: remove setters next API break
|
||||||
|
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||||
|
public class CoopPointData extends GameResource {
|
||||||
|
@Getter(onMethod_ = @Override)
|
||||||
|
int id;
|
||||||
|
|
||||||
|
int chapterId;
|
||||||
|
String type;
|
||||||
|
int acceptQuest;
|
||||||
|
int[] postPointList;
|
||||||
|
// int pointNameTextMapHash;
|
||||||
|
// int pointDecTextMapHash;
|
||||||
|
int pointPosId;
|
||||||
|
// long photoMaleHash;
|
||||||
|
// long photoFemaleHash;
|
||||||
|
}
|
@ -241,7 +241,8 @@ public interface HandbookActions {
|
|||||||
|
|
||||||
// Create the entity.
|
// Create the entity.
|
||||||
for (var i = 1; i <= request.getAmount(); i++) {
|
for (var i = 1; i <= request.getAmount(); i++) {
|
||||||
var entity = new EntityMonster(scene, entityData, player.getPosition(), level);
|
var entity =
|
||||||
|
new EntityMonster(scene, entityData, player.getPosition(), player.getRotation(), level);
|
||||||
scene.addEntity(entity);
|
scene.addEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ public class EntityHomeAnimal extends EntityMonster implements Rebornable {
|
|||||||
@Getter private final int rebirthCD;
|
@Getter private final int rebirthCD;
|
||||||
private final AtomicBoolean disappeared = new AtomicBoolean();
|
private final AtomicBoolean disappeared = new AtomicBoolean();
|
||||||
|
|
||||||
public EntityHomeAnimal(Scene scene, HomeWorldAnimalData data, Position pos) {
|
public EntityHomeAnimal(Scene scene, HomeWorldAnimalData data, Position pos, Position rot) {
|
||||||
super(scene, GameData.getMonsterDataMap().get(data.getMonsterID()), pos, 1);
|
super(scene, GameData.getMonsterDataMap().get(data.getMonsterID()), pos, rot, 1);
|
||||||
|
|
||||||
this.rebornPos = pos.clone();
|
this.rebornPos = pos.clone();
|
||||||
this.rebirth = data.getIsRebirth();
|
this.rebirth = data.getIsRebirth();
|
||||||
|
@ -54,14 +54,14 @@ public class EntityMonster extends GameEntity {
|
|||||||
@Getter private List<Player> playerOnBattle;
|
@Getter private List<Player> playerOnBattle;
|
||||||
@Nullable @Getter @Setter private SceneMonster metaMonster;
|
@Nullable @Getter @Setter private SceneMonster metaMonster;
|
||||||
|
|
||||||
public EntityMonster(Scene scene, MonsterData monsterData, Position pos, int level) {
|
public EntityMonster(Scene scene, MonsterData monsterData, Position pos, Position rot, int level) {
|
||||||
super(scene);
|
super(scene);
|
||||||
|
|
||||||
this.id = this.getWorld().getNextEntityId(EntityIdType.MONSTER);
|
this.id = this.getWorld().getNextEntityId(EntityIdType.MONSTER);
|
||||||
this.monsterData = monsterData;
|
this.monsterData = monsterData;
|
||||||
this.fightProperties = new Int2FloatOpenHashMap();
|
this.fightProperties = new Int2FloatOpenHashMap();
|
||||||
this.position = new Position(pos);
|
this.position = new Position(pos);
|
||||||
this.rotation = new Position();
|
this.rotation = new Position(rot);
|
||||||
this.bornPos = this.getPosition().clone();
|
this.bornPos = this.getPosition().clone();
|
||||||
this.level = level;
|
this.level = level;
|
||||||
this.playerOnBattle = new ArrayList<>();
|
this.playerOnBattle = new ArrayList<>();
|
||||||
|
@ -15,9 +15,8 @@ import emu.grasscutter.scripts.data.controller.EntityController;
|
|||||||
import emu.grasscutter.server.event.entity.*;
|
import emu.grasscutter.server.event.entity.*;
|
||||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||||
import it.unimi.dsi.fastutil.ints.*;
|
import it.unimi.dsi.fastutil.ints.*;
|
||||||
import lombok.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
public abstract class GameEntity {
|
public abstract class GameEntity {
|
||||||
@Getter private final Scene scene;
|
@Getter private final Scene scene;
|
||||||
@ -35,7 +34,8 @@ public abstract class GameEntity {
|
|||||||
@Getter @Setter private boolean lockHP;
|
@Getter @Setter private boolean lockHP;
|
||||||
|
|
||||||
@Setter(AccessLevel.PROTECTED)
|
@Setter(AccessLevel.PROTECTED)
|
||||||
@Getter private boolean isDead = false;
|
@Getter
|
||||||
|
private boolean isDead = false;
|
||||||
|
|
||||||
// Lua controller for specific actions
|
// Lua controller for specific actions
|
||||||
@Getter @Setter private EntityController entityController;
|
@Getter @Setter private EntityController entityController;
|
||||||
|
@ -107,7 +107,8 @@ public class HomeSceneItem {
|
|||||||
return new EntityHomeAnimal(
|
return new EntityHomeAnimal(
|
||||||
scene,
|
scene,
|
||||||
GameData.getHomeWorldAnimalDataMap().get(homeAnimalItem.getFurnitureId()),
|
GameData.getHomeWorldAnimalDataMap().get(homeAnimalItem.getFurnitureId()),
|
||||||
homeAnimalItem.getSpawnPos());
|
homeAnimalItem.getSpawnPos(),
|
||||||
|
homeAnimalItem.getSpawnRot());
|
||||||
})
|
})
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ public class HomeWorld extends World {
|
|||||||
|
|
||||||
this.home = owner.isOnline() ? owner.getHome() : GameHome.getByUid(owner.getUid());
|
this.home = owner.isOnline() ? owner.getHome() : GameHome.getByUid(owner.getUid());
|
||||||
this.refreshModuleManager();
|
this.refreshModuleManager();
|
||||||
server.registerHomeWorld(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -104,7 +104,8 @@ public final class BlossomActivity {
|
|||||||
|
|
||||||
var monsterData = GameData.getMonsterDataMap().get((int) entry);
|
var monsterData = GameData.getMonsterDataMap().get((int) entry);
|
||||||
var level = scene.getEntityLevel(1, worldLevelOverride);
|
var level = scene.getEntityLevel(1, worldLevelOverride);
|
||||||
var entity = new EntityMonster(scene, monsterData, pos.nearby2d(4f), level);
|
var entity =
|
||||||
|
new EntityMonster(scene, monsterData, pos.nearby2d(4f), Position.ZERO, level);
|
||||||
scene.addEntity(entity);
|
scene.addEntity(entity);
|
||||||
newMonsters.add(entity);
|
newMonsters.add(entity);
|
||||||
}
|
}
|
||||||
|
@ -1378,14 +1378,6 @@ public class Player implements PlayerHook, FieldFetch {
|
|||||||
this.getPlayerProgress().setPlayer(this); // Add reference to the player.
|
this.getPlayerProgress().setPlayer(this); // Add reference to the player.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked when the player selects their avatar.
|
|
||||||
*/
|
|
||||||
public void onPlayerBorn() {
|
|
||||||
Grasscutter.getThreadPool().submit(
|
|
||||||
this.getQuestManager()::onPlayerBorn);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onLogin() {
|
public void onLogin() {
|
||||||
// Quest - Commented out because a problem is caused if you log out while this quest is active
|
// Quest - Commented out because a problem is caused if you log out while this quest is active
|
||||||
/*
|
/*
|
||||||
|
@ -33,12 +33,9 @@ public final class PlayerProgressManager extends BasePlayerDataManager {
|
|||||||
|
|
||||||
public static final Set<Integer> IGNORED_OPEN_STATES =
|
public static final Set<Integer> IGNORED_OPEN_STATES =
|
||||||
Set.of(
|
Set.of(
|
||||||
1404, // OPEN_STATE_MENGDE_INFUSEDCRYSTAL, causes quest 'Mine Craft' to be given to the
|
1404 // OPEN_STATE_MENGDE_INFUSEDCRYSTAL, causes quest 'Mine Craft' to be given to the
|
||||||
// player at the start of the game.
|
// player at the start of the game.
|
||||||
// This should be removed when city reputation is implemented.
|
// This should be removed when city reputation is implemented.
|
||||||
57 // OPEN_STATE_PERSONAL_LINE, causes the prompt for showing character hangout quests to
|
|
||||||
// be permanently shown.
|
|
||||||
// This should be removed when character story quests are implemented.
|
|
||||||
);
|
);
|
||||||
// Set of open states that are set per default for all accounts. Can be overwritten by an entry in
|
// Set of open states that are set per default for all accounts. Can be overwritten by an entry in
|
||||||
// `map`.
|
// `map`.
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package emu.grasscutter.game.player;
|
package emu.grasscutter.game.player;
|
||||||
|
|
||||||
|
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||||
|
|
||||||
import dev.morphia.annotations.*;
|
import dev.morphia.annotations.*;
|
||||||
import emu.grasscutter.*;
|
import emu.grasscutter.*;
|
||||||
import emu.grasscutter.data.GameData;
|
import emu.grasscutter.data.GameData;
|
||||||
@ -21,12 +23,9 @@ import emu.grasscutter.server.packet.send.*;
|
|||||||
import emu.grasscutter.utils.Utils;
|
import emu.grasscutter.utils.Utils;
|
||||||
import it.unimi.dsi.fastutil.ints.*;
|
import it.unimi.dsi.fastutil.ints.*;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
import lombok.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import lombok.*;
|
||||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
public final class TeamManager extends BasePlayerDataManager {
|
public final class TeamManager extends BasePlayerDataManager {
|
||||||
|
@ -221,14 +221,11 @@ public final class QuestManager extends BasePlayerManager {
|
|||||||
this.player.sendPacket(new PacketGivingRecordNotify(this.getGivingRecords()));
|
this.player.sendPacket(new PacketGivingRecordNotify(this.getGivingRecords()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPlayerBorn() {
|
public void onLogin() {
|
||||||
if (this.isQuestingEnabled()) {
|
if (this.isQuestingEnabled()) {
|
||||||
this.enableQuests();
|
this.enableQuests();
|
||||||
this.sendGivingRecords();
|
this.sendGivingRecords();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void onLogin() {
|
|
||||||
|
|
||||||
List<GameMainQuest> activeQuests = getActiveMainQuests();
|
List<GameMainQuest> activeQuests = getActiveMainQuests();
|
||||||
List<GameQuest> activeSubs = new ArrayList<>(activeQuests.size());
|
List<GameQuest> activeSubs = new ArrayList<>(activeQuests.size());
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package emu.grasscutter.game.quest.conditions;
|
||||||
|
|
||||||
|
import emu.grasscutter.data.excels.quest.QuestData;
|
||||||
|
import emu.grasscutter.game.player.Player;
|
||||||
|
import emu.grasscutter.game.quest.QuestValueCond;
|
||||||
|
import emu.grasscutter.game.quest.enums.QuestCond;
|
||||||
|
|
||||||
|
@QuestValueCond(QuestCond.QUEST_COND_MAIN_COOP_START)
|
||||||
|
public class ConditionMainCoopStart extends BaseCondition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean execute(
|
||||||
|
Player owner,
|
||||||
|
QuestData questData,
|
||||||
|
QuestData.QuestAcceptCondition condition,
|
||||||
|
String paramStr,
|
||||||
|
int... params) {
|
||||||
|
return condition.getParam()[0] == params[0]
|
||||||
|
&& (condition.getParam()[1] == 0 || condition.getParam()[1] == params[1]);
|
||||||
|
}
|
||||||
|
}
|
@ -54,7 +54,7 @@ public enum QuestCond implements QuestTrigger {
|
|||||||
QUEST_COND_QUEST_GLOBAL_VAR_LESS(46),
|
QUEST_COND_QUEST_GLOBAL_VAR_LESS(46),
|
||||||
QUEST_COND_PERSONAL_LINE_UNLOCK(47),
|
QUEST_COND_PERSONAL_LINE_UNLOCK(47),
|
||||||
QUEST_COND_CITY_REPUTATION_REQUEST(48), // missing
|
QUEST_COND_CITY_REPUTATION_REQUEST(48), // missing
|
||||||
QUEST_COND_MAIN_COOP_START(49), // missing
|
QUEST_COND_MAIN_COOP_START(49),
|
||||||
QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT(50), // missing
|
QUEST_COND_MAIN_COOP_ENTER_SAVE_POINT(50), // missing
|
||||||
QUEST_COND_CITY_REPUTATION_LEVEL(51), // missing, only NPC groups
|
QUEST_COND_CITY_REPUTATION_LEVEL(51), // missing, only NPC groups
|
||||||
QUEST_COND_CITY_REPUTATION_UNLOCK(52), // missing, currently unused
|
QUEST_COND_CITY_REPUTATION_UNLOCK(52), // missing, currently unused
|
||||||
|
@ -816,8 +816,8 @@ public class Scene {
|
|||||||
|
|
||||||
int level = this.getEntityLevel(entry.getLevel(), worldLevelOverride);
|
int level = this.getEntityLevel(entry.getLevel(), worldLevelOverride);
|
||||||
|
|
||||||
EntityMonster monster = new EntityMonster(this, data, entry.getPos(), level);
|
EntityMonster monster =
|
||||||
monster.getRotation().set(entry.getRot());
|
new EntityMonster(this, data, entry.getPos(), entry.getRot(), level);
|
||||||
monster.setGroupId(entry.getGroup().getGroupId());
|
monster.setGroupId(entry.getGroup().getGroupId());
|
||||||
monster.setPoseId(entry.getPoseId());
|
monster.setPoseId(entry.getPoseId());
|
||||||
monster.setConfigId(entry.getConfigId());
|
monster.setConfigId(entry.getConfigId());
|
||||||
|
@ -72,6 +72,8 @@ public class World implements Iterable<Player> {
|
|||||||
this.scenes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
|
this.scenes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
|
||||||
this.entity = new EntityWorld(this);
|
this.entity = new EntityWorld(this);
|
||||||
this.lastUpdateTime = System.currentTimeMillis();
|
this.lastUpdateTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
server.registerWorld(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLevelEntityId() {
|
public int getLevelEntityId() {
|
||||||
@ -396,37 +398,50 @@ public class World implements Iterable<Player> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene oldScene = null;
|
Scene oldScene = player.getScene();
|
||||||
if (player.getScene() != null) {
|
var newScene = this.getSceneById(teleportProperties.getSceneId());
|
||||||
oldScene = player.getScene();
|
|
||||||
|
|
||||||
|
// Move directly in the same scene.
|
||||||
|
if (newScene == oldScene && teleportProperties.getTeleportType() == TeleportType.COMMAND) {
|
||||||
|
// Set player position and rotation
|
||||||
|
if (teleportProperties.getTeleportTo() != null) {
|
||||||
|
player.getPosition().set(teleportProperties.getTeleportTo());
|
||||||
|
}
|
||||||
|
if (teleportProperties.getTeleportRot() != null) {
|
||||||
|
player.getRotation().set(teleportProperties.getTeleportRot());
|
||||||
|
}
|
||||||
|
player.sendPacket(new PacketSceneEntityAppearNotify(player));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldScene != null) {
|
||||||
// Don't deregister scenes if the player is going to tp back into them
|
// Don't deregister scenes if the player is going to tp back into them
|
||||||
if (oldScene.getId() == teleportProperties.getSceneId()) {
|
if (oldScene == newScene) {
|
||||||
oldScene.setDontDestroyWhenEmpty(true);
|
oldScene.setDontDestroyWhenEmpty(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
oldScene.removePlayer(player);
|
oldScene.removePlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
var newScene = this.getSceneById(teleportProperties.getSceneId());
|
if (newScene != null) {
|
||||||
newScene.addPlayer(player);
|
newScene.addPlayer(player);
|
||||||
|
|
||||||
player.getTeamManager().applyAbilities(newScene);
|
player.getTeamManager().applyAbilities(newScene);
|
||||||
|
|
||||||
// Dungeon
|
// Dungeon
|
||||||
// Dungeon system is handling this already
|
// Dungeon system is handling this already
|
||||||
// if(dungeonData!=null){
|
// if(dungeonData!=null){
|
||||||
// var dungeonManager = new DungeonManager(newScene, dungeonData);
|
// var dungeonManager = new DungeonManager(newScene, dungeonData);
|
||||||
// dungeonManager.startDungeon();
|
// dungeonManager.startDungeon();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
SceneConfig config = newScene.getScriptManager().getConfig();
|
SceneConfig config = newScene.getScriptManager().getConfig();
|
||||||
if (teleportProperties.getTeleportTo() == null && config != null) {
|
if (teleportProperties.getTeleportTo() == null && config != null) {
|
||||||
if (config.born_pos != null) {
|
if (config.born_pos != null) {
|
||||||
teleportProperties.setTeleportTo(config.born_pos);
|
teleportProperties.setTeleportTo(config.born_pos);
|
||||||
}
|
}
|
||||||
if (config.born_rot != null) {
|
if (config.born_rot != null) {
|
||||||
teleportProperties.setTeleportRot(config.born_rot);
|
teleportProperties.setTeleportRot(config.born_rot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,7 +453,7 @@ public class World implements Iterable<Player> {
|
|||||||
player.getRotation().set(teleportProperties.getTeleportRot());
|
player.getRotation().set(teleportProperties.getTeleportRot());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldScene != null && newScene != oldScene) {
|
if (oldScene != null && newScene != null && newScene != oldScene) {
|
||||||
newScene.setPrevScenePoint(oldScene.getPrevScenePoint());
|
newScene.setPrevScenePoint(oldScene.getPrevScenePoint());
|
||||||
oldScene.setDontDestroyWhenEmpty(false);
|
oldScene.setDontDestroyWhenEmpty(false);
|
||||||
}
|
}
|
||||||
|
@ -1037,8 +1037,7 @@ public class SceneScriptManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Spawn mob
|
// Spawn mob
|
||||||
EntityMonster entity = new EntityMonster(getScene(), data, monster.pos, level);
|
EntityMonster entity = new EntityMonster(getScene(), data, monster.pos, monster.rot, level);
|
||||||
entity.getRotation().set(monster.rot);
|
|
||||||
entity.setGroupId(groupId);
|
entity.setGroupId(groupId);
|
||||||
entity.setBlockId(blockId);
|
entity.setBlockId(blockId);
|
||||||
entity.setConfigId(monster.config_id);
|
entity.setConfigId(monster.config_id);
|
||||||
|
@ -311,11 +311,6 @@ public final class GameServer extends KcpServer implements Iterable<Player> {
|
|||||||
world.save(); // Save the player's world
|
world.save(); // Save the player's world
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerHomeWorld(HomeWorld homeWorld) {
|
|
||||||
this.getHomeWorlds().put(homeWorld.getOwnerUid(), homeWorld);
|
|
||||||
this.registerWorld(homeWorld);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HomeWorld getHomeWorldOrCreate(Player owner) {
|
public HomeWorld getHomeWorldOrCreate(Player owner) {
|
||||||
return this.getHomeWorlds()
|
return this.getHomeWorlds()
|
||||||
.computeIfAbsent(owner.getUid(), (uid) -> new HomeWorld(this, owner));
|
.computeIfAbsent(owner.getUid(), (uid) -> new HomeWorld(this, owner));
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package emu.grasscutter.server.packet.recv;
|
||||||
|
|
||||||
|
import emu.grasscutter.Grasscutter;
|
||||||
|
import emu.grasscutter.net.packet.*;
|
||||||
|
import emu.grasscutter.net.proto.CancelCoopTaskReqOuterClass;
|
||||||
|
import emu.grasscutter.server.game.GameSession;
|
||||||
|
import emu.grasscutter.server.packet.send.PacketCancelCoopTaskRsp;
|
||||||
|
|
||||||
|
@Opcodes(PacketOpcodes.CancelCoopTaskReq)
|
||||||
|
public class HandlerCancelCoopTaskReq extends PacketHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||||
|
CancelCoopTaskReqOuterClass.CancelCoopTaskReq req =
|
||||||
|
CancelCoopTaskReqOuterClass.CancelCoopTaskReq.parseFrom(payload);
|
||||||
|
var chapterId = req.getChapterId();
|
||||||
|
Grasscutter.getLogger().warn("Call to unimplemented packet CancelCoopTaskReq");
|
||||||
|
// TODO: Actually cancel the quests.
|
||||||
|
session.send(new PacketCancelCoopTaskRsp(chapterId));
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package emu.grasscutter.server.packet.recv;
|
|||||||
|
|
||||||
import emu.grasscutter.net.packet.*;
|
import emu.grasscutter.net.packet.*;
|
||||||
import emu.grasscutter.server.game.GameSession;
|
import emu.grasscutter.server.game.GameSession;
|
||||||
|
import emu.grasscutter.server.packet.send.PacketCoopDataNotify;
|
||||||
import emu.grasscutter.server.packet.send.PacketPersonalLineAllDataRsp;
|
import emu.grasscutter.server.packet.send.PacketPersonalLineAllDataRsp;
|
||||||
|
|
||||||
@Opcodes(PacketOpcodes.PersonalLineAllDataReq)
|
@Opcodes(PacketOpcodes.PersonalLineAllDataReq)
|
||||||
@ -12,5 +13,7 @@ public class HandlerPersonalLineAllDataReq extends PacketHandler {
|
|||||||
session.send(
|
session.send(
|
||||||
new PacketPersonalLineAllDataRsp(
|
new PacketPersonalLineAllDataRsp(
|
||||||
session.getPlayer().getQuestManager().getMainQuests().values()));
|
session.getPlayer().getQuestManager().getMainQuests().values()));
|
||||||
|
// TODO: this should maybe be at player login?
|
||||||
|
session.send(new PacketCoopDataNotify());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ public class HandlerQuestCreateEntityReq extends PacketHandler {
|
|||||||
val monsterId = entity.getMonsterId();
|
val monsterId = entity.getMonsterId();
|
||||||
val level = entity.getLevel();
|
val level = entity.getLevel();
|
||||||
MonsterData monsterData = GameData.getMonsterDataMap().get(monsterId);
|
MonsterData monsterData = GameData.getMonsterDataMap().get(monsterId);
|
||||||
gameEntity = new EntityMonster(scene, monsterData, pos, level);
|
gameEntity = new EntityMonster(scene, monsterData, pos, rot, level);
|
||||||
}
|
}
|
||||||
case NPC_ID -> {}
|
case NPC_ID -> {}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,6 @@ public class HandlerSetPlayerBornDataReq extends PacketHandler {
|
|||||||
|
|
||||||
// Login done
|
// Login done
|
||||||
session.getPlayer().onLogin();
|
session.getPlayer().onLogin();
|
||||||
session.getPlayer().onPlayerBorn();
|
|
||||||
|
|
||||||
// Born resp packet
|
// Born resp packet
|
||||||
session.send(new BasePacket(PacketOpcodes.SetPlayerBornDataRsp));
|
session.send(new BasePacket(PacketOpcodes.SetPlayerBornDataRsp));
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package emu.grasscutter.server.packet.recv;
|
||||||
|
|
||||||
|
import emu.grasscutter.data.GameData;
|
||||||
|
import emu.grasscutter.game.quest.enums.QuestCond;
|
||||||
|
import emu.grasscutter.net.packet.*;
|
||||||
|
import emu.grasscutter.net.proto.StartCoopPointReqOuterClass;
|
||||||
|
import emu.grasscutter.server.game.GameSession;
|
||||||
|
import emu.grasscutter.server.packet.send.PacketStartCoopPointRsp;
|
||||||
|
|
||||||
|
@Opcodes(PacketOpcodes.StartCoopPointReq)
|
||||||
|
public class HandlerStartCoopPointReq extends PacketHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||||
|
StartCoopPointReqOuterClass.StartCoopPointReq req =
|
||||||
|
StartCoopPointReqOuterClass.StartCoopPointReq.parseFrom(payload);
|
||||||
|
var coopPoint = req.getCoopPoint();
|
||||||
|
|
||||||
|
var coopPointData =
|
||||||
|
GameData.getCoopPointDataMap().values().stream()
|
||||||
|
.filter(i -> i.getId() == coopPoint)
|
||||||
|
.toList();
|
||||||
|
if (!coopPointData.isEmpty()) {
|
||||||
|
var player = session.getPlayer();
|
||||||
|
var questManager = player.getQuestManager();
|
||||||
|
questManager.queueEvent(
|
||||||
|
QuestCond.QUEST_COND_MAIN_COOP_START, coopPointData.get(0).getChapterId(), 0);
|
||||||
|
}
|
||||||
|
session.send(new PacketStartCoopPointRsp(coopPoint));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package emu.grasscutter.server.packet.send;
|
||||||
|
|
||||||
|
import emu.grasscutter.net.packet.*;
|
||||||
|
import emu.grasscutter.net.proto.CancelCoopTaskRspOuterClass;
|
||||||
|
|
||||||
|
public class PacketCancelCoopTaskRsp extends BasePacket {
|
||||||
|
|
||||||
|
public PacketCancelCoopTaskRsp(int chapterId) {
|
||||||
|
super(PacketOpcodes.SetCoopChapterViewedRsp);
|
||||||
|
|
||||||
|
CancelCoopTaskRspOuterClass.CancelCoopTaskRsp proto =
|
||||||
|
CancelCoopTaskRspOuterClass.CancelCoopTaskRsp.newBuilder().setChapterId(chapterId).build();
|
||||||
|
|
||||||
|
this.setData(proto);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package emu.grasscutter.server.packet.send;
|
||||||
|
|
||||||
|
import emu.grasscutter.data.GameData;
|
||||||
|
import emu.grasscutter.net.packet.*;
|
||||||
|
import emu.grasscutter.net.proto.CoopChapterOuterClass;
|
||||||
|
import emu.grasscutter.net.proto.CoopDataNotifyOuterClass;
|
||||||
|
import emu.grasscutter.net.proto.CoopPointOuterClass;
|
||||||
|
|
||||||
|
public class PacketCoopDataNotify extends BasePacket {
|
||||||
|
|
||||||
|
public PacketCoopDataNotify() {
|
||||||
|
super(PacketOpcodes.CoopDataNotify);
|
||||||
|
|
||||||
|
var proto = CoopDataNotifyOuterClass.CoopDataNotify.newBuilder();
|
||||||
|
proto.setIsHaveProgress(false);
|
||||||
|
|
||||||
|
// TODO: implement: determine the actual current progress point.
|
||||||
|
// Add every chapter and add the start point to each chapter regardless of actual progress.
|
||||||
|
GameData.getCoopChapterDataMap()
|
||||||
|
.values()
|
||||||
|
.forEach(
|
||||||
|
i -> {
|
||||||
|
var chapter = CoopChapterOuterClass.CoopChapter.newBuilder();
|
||||||
|
chapter.setId(i.getId());
|
||||||
|
|
||||||
|
// TODO: implement: look at unlockCond to determine what state each chapter should be
|
||||||
|
// in.
|
||||||
|
// Set every chapter to "Accept" regardless of accept conditions.
|
||||||
|
chapter.setStateValue(3); // 3 == STATE_ACCEPT
|
||||||
|
|
||||||
|
var point = CoopPointOuterClass.CoopPoint.newBuilder();
|
||||||
|
var pointList =
|
||||||
|
GameData.getCoopPointDataMap().values().stream()
|
||||||
|
.filter(
|
||||||
|
j -> j.getChapterId() == i.getId() && j.getType().equals("POINT_START"))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (!pointList.isEmpty()) {
|
||||||
|
int pointId = pointList.get(0).getId();
|
||||||
|
point.setId(pointId);
|
||||||
|
chapter.addCoopPointList(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
proto.addChapterList(chapter);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setData(proto);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package emu.grasscutter.server.packet.send;
|
||||||
|
|
||||||
|
import emu.grasscutter.net.packet.*;
|
||||||
|
import emu.grasscutter.net.proto.StartCoopPointRspOuterClass;
|
||||||
|
|
||||||
|
public class PacketStartCoopPointRsp extends BasePacket {
|
||||||
|
|
||||||
|
public PacketStartCoopPointRsp(int coopPoint) {
|
||||||
|
super(PacketOpcodes.StartCoopPointRsp);
|
||||||
|
|
||||||
|
StartCoopPointRspOuterClass.StartCoopPointRsp proto =
|
||||||
|
StartCoopPointRspOuterClass.StartCoopPointRsp.newBuilder().setCoopPoint(coopPoint).build();
|
||||||
|
|
||||||
|
this.setData(proto);
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import emu.grasscutter.data.common.ItemUseData;
|
|||||||
import emu.grasscutter.data.excels.*;
|
import emu.grasscutter.data.excels.*;
|
||||||
import emu.grasscutter.data.excels.achievement.AchievementData;
|
import emu.grasscutter.data.excels.achievement.AchievementData;
|
||||||
import emu.grasscutter.data.excels.avatar.AvatarData;
|
import emu.grasscutter.data.excels.avatar.AvatarData;
|
||||||
|
import emu.grasscutter.server.http.handlers.GachaHandler;
|
||||||
import emu.grasscutter.utils.*;
|
import emu.grasscutter.utils.*;
|
||||||
import emu.grasscutter.utils.lang.Language;
|
import emu.grasscutter.utils.lang.Language;
|
||||||
import emu.grasscutter.utils.lang.Language.TextStrings;
|
import emu.grasscutter.utils.lang.Language.TextStrings;
|
||||||
@ -311,8 +312,19 @@ public final class Tools {
|
|||||||
return sbs.stream().map(StringBuilder::toString).toList();
|
return sbs.stream().map(StringBuilder::toString).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void generateGachaMappings() {
|
||||||
|
var path = GachaHandler.getGachaMappingsPath();
|
||||||
|
if (!Files.exists(path)) {
|
||||||
|
try {
|
||||||
|
Grasscutter.getLogger().debug("Creating default '" + path + "' data");
|
||||||
|
Tools.createGachaMappings(path);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
Grasscutter.getLogger().warn("Failed to create gacha mappings. \n" + exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void createGachaMappings(Path location) throws IOException {
|
public static void createGachaMappings(Path location) throws IOException {
|
||||||
ResourceLoader.loadResources();
|
|
||||||
List<String> jsons = createGachaMappingJsons();
|
List<String> jsons = createGachaMappingJsons();
|
||||||
var usedLocales = new HashSet<String>();
|
var usedLocales = new HashSet<String>();
|
||||||
StringBuilder sb = new StringBuilder("mappings = {\n");
|
StringBuilder sb = new StringBuilder("mappings = {\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user