Skip to content

Commit

Permalink
Bare-bones Hangouts implementation (#2384)
Browse files Browse the repository at this point in the history
  • Loading branch information
scooterboo authored Sep 23, 2023
1 parent 0f0e7ac commit 0dd9545
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 5 deletions.
8 changes: 8 additions & 0 deletions src/main/java/emu/grasscutter/data/GameData.java
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,14 @@ public final class GameData {
private static final Int2ObjectMap<CookRecipeData> cookRecipeDataMap =
new Int2ObjectOpenHashMap<>();

@Getter
private static final Int2ObjectMap<CoopChapterData> coopChapterDataMap =
new Int2ObjectOpenHashMap<>();

@Getter
private static final Int2ObjectMap<CoopPointData> coopPointDataMap =
new Int2ObjectOpenHashMap<>();

@Getter
private static final Int2ObjectMap<CompoundData> compoundDataMap = new Int2ObjectOpenHashMap<>();

Expand Down
45 changes: 45 additions & 0 deletions src/main/java/emu/grasscutter/data/excels/CoopChapterData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
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;
}
}
23 changes: 23 additions & 0 deletions src/main/java/emu/grasscutter/data/excels/CoopPointData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,9 @@ public final class PlayerProgressManager extends BasePlayerDataManager {

public static final Set<Integer> IGNORED_OPEN_STATES =
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.
// 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
// `map`.
Expand Down
Original file line number Diff line number Diff line change
@@ -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]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public enum QuestCond implements QuestTrigger {
QUEST_COND_QUEST_GLOBAL_VAR_LESS(46),
QUEST_COND_PERSONAL_LINE_UNLOCK(47),
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_CITY_REPUTATION_LEVEL(51), // missing, only NPC groups
QUEST_COND_CITY_REPUTATION_UNLOCK(52), // missing, currently unused
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import emu.grasscutter.net.packet.*;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketCoopDataNotify;
import emu.grasscutter.server.packet.send.PacketPersonalLineAllDataRsp;

@Opcodes(PacketOpcodes.PersonalLineAllDataReq)
Expand All @@ -12,5 +13,7 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex
session.send(
new PacketPersonalLineAllDataRsp(
session.getPlayer().getQuestManager().getMainQuests().values()));
// TODO: this should maybe be at player login?
session.send(new PacketCoopDataNotify());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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));
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}

0 comments on commit 0dd9545

Please sign in to comment.