Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/main/java/kinoko/database/AllianceAccessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package kinoko.database;

import kinoko.server.alliance.Alliance;

import java.util.Optional;

public interface AllianceAccessor {
Optional<Alliance> getAllianceById(int allianceId);

boolean checkAllianceNameAvailable(String name);

boolean newAlliance(Alliance alliance);

boolean saveAlliance(Alliance alliance);

boolean deleteAlliance(int allianceId);

}
2 changes: 2 additions & 0 deletions src/main/java/kinoko/database/DatabaseConnector.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public interface DatabaseConnector {
FriendAccessor getFriendAccessor();

GuildAccessor getGuildAccessor();

AllianceAccessor getAllianceAccessor();

GiftAccessor getGiftAccessor();

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/kinoko/database/DatabaseManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public static FriendAccessor friendAccessor() {
public static GuildAccessor guildAccessor() {
return connector.getGuildAccessor();
}

public static AllianceAccessor allianceAccessor() {
return connector.getAllianceAccessor();
}

public static GiftAccessor giftAccessor() {
return connector.getGiftAccessor();
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/kinoko/database/GuildAccessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
public interface GuildAccessor {
Optional<Guild> getGuildById(int guildId);

Optional<Guild> getGuildByName(String guildName);

boolean checkGuildNameAvailable(String name);

boolean newGuild(Guild guild);
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/kinoko/database/IdAccessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public interface IdAccessor {
Optional<Integer> nextPartyId();

Optional<Integer> nextGuildId();

Optional<Integer> nextAllianceId();

Optional<Integer> nextMemoId();
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public final class CassandraConnector implements DatabaseConnector {
private CharacterAccessor characterAccessor;
private FriendAccessor friendAccessor;
private GuildAccessor guildAccessor;
private AllianceAccessor allianceAccessor;
private GiftAccessor giftAccessor;
private MemoAccessor memoAccessor;

Expand Down Expand Up @@ -101,6 +102,11 @@ public FriendAccessor getFriendAccessor() {
public GuildAccessor getGuildAccessor() {
return guildAccessor;
}

@Override
public AllianceAccessor getAllianceAccessor() {
return allianceAccessor;
}

@Override
public GiftAccessor getGiftAccessor() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,28 @@ public Optional<Guild> getGuildById(int guildId) {
}

@Override
public boolean checkGuildNameAvailable(String name) {
public Optional<Guild> getGuildByName(String guildName) {
final ResultSet selectResult = getSession().execute(
selectFrom(getKeyspace(), GuildTable.getTableName()).all()
.whereColumn(GuildTable.GUILD_NAME_INDEX).isEqualTo(literal(lowerName(name)))
.whereColumn(GuildTable.GUILD_NAME_INDEX).isEqualTo(literal(lowerName(guildName)))
.build()
);
for (Row row : selectResult) {
return Optional.of(loadGuild(row));
}
return Optional.empty();
}

@Override
public boolean checkGuildNameAvailable(String guildName) {
final ResultSet selectResult = getSession().execute(
selectFrom(getKeyspace(), GuildTable.getTableName()).all()
.whereColumn(GuildTable.GUILD_NAME_INDEX).isEqualTo(literal(lowerName(guildName)))
.build()
);
for (Row row : selectResult) {
final String existingName = row.getString(GuildTable.GUILD_NAME_INDEX);
if (existingName != null && existingName.equalsIgnoreCase(name)) {
if (existingName != null && existingName.equalsIgnoreCase(guildName)) {
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ public synchronized Optional<Integer> nextPartyId() {
public synchronized Optional<Integer> nextGuildId() {
return getNextId(IdTable.GUILD_ID);
}

@Override
public synchronized Optional<Integer> nextAllianceId() {
return getNextId(IdTable.ALLIANCE_ID);
}

@Override
public synchronized Optional<Integer> nextMemoId() {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/kinoko/database/cassandra/table/IdTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public final class IdTable {
public static final String CHARACTER_ID = "character_id";
public static final String PARTY_ID = "party_id";
public static final String GUILD_ID = "guild_id";
public static final String ALLIANCE_ID = "alliance_id";
public static final String MEMO_ID = "memo_id";

private static final String tableName = "id_table";
Expand All @@ -40,6 +41,7 @@ public static void createTable(CqlSession session, String keyspace) {
CHARACTER_ID,
PARTY_ID,
GUILD_ID,
ALLIANCE_ID,
MEMO_ID
)) {
session.execute(
Expand Down
75 changes: 71 additions & 4 deletions src/main/java/kinoko/handler/user/GuildHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import kinoko.packet.world.MessagePacket;
import kinoko.packet.world.WvsContext;
import kinoko.script.GuildHQ;
import kinoko.server.alliance.AllianceRequestType;
import kinoko.server.alliance.AllianceResultType;
import kinoko.server.alliance.*;
import kinoko.server.guild.*;
import kinoko.server.header.InHeader;
import kinoko.server.packet.InPacket;
Expand Down Expand Up @@ -220,14 +219,82 @@ public static void handleGuildResult(User user, InPacket inPacket) {
public static void handleAllianceRequest(User user, InPacket inPacket) {
final int type = inPacket.decodeByte();
final AllianceRequestType requestType = AllianceRequestType.getByValue(type);
// TODO
switch (requestType) {
case Load -> {
// CWvsContext::OnAllianceResult
user.getConnectedServer().submitAllianceRequest(user, AllianceRequest.load(user.getAllianceId()));
}
case Withdraw -> {
// CTabGuildAlliance::OnWithdraw
user.getConnectedServer().submitAllianceRequest(user, AllianceRequest.withdraw());
}
case Invite -> {
// CTabGuildAlliance::OnInvite
final String guildName = inPacket.decodeString();
user.getConnectedServer().submitAllianceRequest(user, AllianceRequest.invite(guildName));
}
case Join -> {
// CUIFadeYesNo::OnButtonClicked
final int inviterId = inPacket.decodeInt();
final String guildName = inPacket.decodeString();
user.getConnectedServer().submitAllianceRequest(user, AllianceRequest.join(inviterId, user.getGuildInfo().getGuildName()));
}
case Kick -> {
// CTabGuildAlliance::OnKick
final int guildId = inPacket.decodeInt();
final int allianceId = inPacket.decodeInt();
user.getConnectedServer().submitAllianceRequest(user, AllianceRequest.kick(guildId));
}
case ChangeMaster -> {
// CTabGuildAlliance::OnChangeMaster
final int targetId = inPacket.decodeInt();
user.getConnectedServer().submitAllianceRequest(user, AllianceRequest.changeMaster(user.getCharacterId(), targetId));
}
case SetGradeName -> {
// CWndAllianceGrade::OnSaveGradeName
final List<String> gradeNames = new ArrayList<>();
for (int i = 0; i < GameConstants.UNION_GRADE_MAX; i++) {
gradeNames.add(inPacket.decodeString());
}
user.getConnectedServer().submitAllianceRequest(user, AllianceRequest.setGradeName(gradeNames));
}
case ChangeGrade -> {
// CTabGuildAlliance::OnGradeChange
final int targetId = inPacket.decodeInt();
final boolean gradeUp = inPacket.decodeBoolean();
user.getConnectedServer().submitAllianceRequest(user, AllianceRequest.changeGrade(targetId, gradeUp));
}
case SetNotice -> {
// CTabGuildAlliance::OnSetNotice
final String notice = inPacket.decodeString();
user.getConnectedServer().submitAllianceRequest(user, AllianceRequest.setNotice(notice));
}
case null -> {
log.error("Unknown alliance request type : {}", type);
}
default -> {
log.error("Unhandled alliance request type : {}", requestType);
}
}
}

@Handler(InHeader.AllianceResult)
public static void handleAllianceResult(User user, InPacket inPacket) {
final int type = inPacket.decodeByte();
final AllianceResultType resultType = AllianceResultType.getByValue(type);
// TODO
switch (resultType) {
case InviteAlliance_BlockedByOpt, InviteAlliance_AlreadyInvited, InviteAlliance_Rejected -> {
final String inviterName = inPacket.decodeString();
final String guildName = inPacket.decodeString();
// TODO
}
case null -> {
log.error("Unknown alliance result type : {}", type);
}
default -> {
log.error("Unhandled alliance result type : {}", resultType);
}
}
}

@Handler(InHeader.GuildBBS)
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/kinoko/packet/CentralPacket.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package kinoko.packet;

import kinoko.server.alliance.AllianceRequest;
import kinoko.server.guild.GuildBoardRequest;
import kinoko.server.guild.GuildRequest;
import kinoko.server.header.CentralHeader;
Expand Down Expand Up @@ -238,6 +239,13 @@ public static OutPacket guildResult(int characterId, GuildInfo guildInfo) {
}
return outPacket;
}

public static OutPacket allianceRequest(int characterId, AllianceRequest allianceRequest) {
final OutPacket outPacket = OutPacket.of(CentralHeader.AllianceRequest);
outPacket.encodeInt(characterId);
allianceRequest.encode(outPacket);
return outPacket;
}

public static OutPacket boardRequest(int characterId, GuildBoardRequest boardRequest) {
final OutPacket outPacket = OutPacket.of(CentralHeader.BoardRequest);
Expand Down
145 changes: 145 additions & 0 deletions src/main/java/kinoko/packet/world/AlliancePacket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package kinoko.packet.world;

import kinoko.server.alliance.Alliance;
import kinoko.server.alliance.AllianceRequestType;
import kinoko.server.alliance.AllianceResultType;
import kinoko.server.guild.Guild;
import kinoko.server.guild.GuildMember;
import kinoko.server.header.OutHeader;
import kinoko.server.packet.OutPacket;
import kinoko.world.GameConstants;

import java.util.List;

public final class AlliancePacket {
// CWvsContext::OnAllianceResult -----------------------------------------------------------------------------------

public static OutPacket invite(int inviterId, String inviterName) {
final OutPacket outPacket = OutPacket.of(OutHeader.AllianceResult);
outPacket.encodeByte(AllianceRequestType.Invite.getValue());
outPacket.encodeInt(inviterId); // dwInviterID
outPacket.encodeString(inviterName); // sInviter
outPacket.encodeString(""); // not used
return outPacket;
}

public static OutPacket loadDone(Alliance alliance) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.LoadDone);
outPacket.encodeByte(alliance != null);
if (alliance != null) {
alliance.encode(outPacket); // ALLIANCEDATA::Decode
}
return outPacket;
}

public static OutPacket loadGuildDone(List<Guild> guilds) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.LoadAllianceDone);
outPacket.encodeInt(guilds.size());
for (Guild guild : guilds) {
guild.encode(outPacket); // GUILDDATA::Decode
}
return outPacket;
}

public static OutPacket notifyLoginOrLogout(int allianceId, int guildId, int characterId, boolean online) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.NotifyLoginOrLogout);
outPacket.encodeInt(allianceId);
outPacket.encodeInt(guildId);
outPacket.encodeInt(characterId);
outPacket.encodeByte(online);
return outPacket;
}

public static OutPacket createDone(Alliance alliance, List<Guild> guilds) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.CreateDone);
alliance.encode(outPacket); // ALLIANCEDATA::Decode
for (Guild guild : guilds) {
guild.encode(outPacket); // GUILDDATA::Decode
}
return outPacket;
}

public static OutPacket withdrawDone(Alliance alliance, Guild guild, boolean kicked) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.Withdraw_Done);
alliance.encode(outPacket); // ALLIANCEDATA::Decode
outPacket.encodeInt(guild.getGuildId()); // nGuildID
guild.encode(outPacket); // GUILDDATA::Decode
outPacket.encodeByte(kicked); // You have been kicked from the alliance. | You have left the alliance.
return outPacket;
}

public static OutPacket inviteDone(Alliance alliance, Guild guild) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.Invite_Done);
alliance.encode(outPacket); // ALLIANCEDATA::Decode
outPacket.encodeInt(guild.getGuildId()); // nGuildID
guild.encode(outPacket); // GUILDDATA::Decode
return outPacket;
}

public static OutPacket UpdateAllianceInfo(Alliance alliance) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.UpdateAllianceInfo);
alliance.encode(outPacket); // ALLIANCEDATA::Decode
return outPacket;
}

public static OutPacket changeLevelOrJob(int allianceId, int guildId, int characterId, int level, int job) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.ChangeLevelOrJob);
outPacket.encodeInt(allianceId);
outPacket.encodeInt(guildId);
outPacket.encodeInt(characterId);
outPacket.encodeInt(level);
outPacket.encodeInt(job);
return outPacket;
}

public static OutPacket changeMasterDone(int allianceId, int oldMasterId, int newMasterId) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.ChangeLevelOrJob);
outPacket.encodeInt(allianceId);
outPacket.encodeInt(oldMasterId);
outPacket.encodeInt(newMasterId);
return outPacket;
}

public static OutPacket setGradeNameDone(int allianceId, List<String> gradeNames) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.SetGradeName_Done);
outPacket.encodeInt(allianceId);
for (int i = 0; i < GameConstants.UNION_GRADE_MAX; i++) {
outPacket.encodeString(gradeNames.get(i));
}
return outPacket;
}

public static OutPacket changeGradeDone(GuildMember member) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.ChangeGrade_Done);
outPacket.encodeInt(member.getCharacterId());
outPacket.encodeByte(member.getAllianceRank().getValue()); // nAllianceGrade
return outPacket;
}

public static OutPacket setNoticeDone(int allianceId, String notice) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.SetNotice_Done);
outPacket.encodeInt(allianceId);
outPacket.encodeString(notice);
return outPacket;
}

public static OutPacket destroyDone(int allianceId) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.Destroy_Done);
outPacket.encodeInt(allianceId);
return outPacket;
}

public static OutPacket updateGuildInfo(Guild guild) {
final OutPacket outPacket = AlliancePacket.of(AllianceResultType.UpdateGuildInfo);
outPacket.encodeInt(guild.getAllianceId()); // nAllianceID
outPacket.encodeInt(guild.getGuildId()); // nGuildID
guild.encode(outPacket); // GUILDDATA::Decode
return outPacket;
}

private static OutPacket of(AllianceResultType resultType) {
final OutPacket outPacket = OutPacket.of(OutHeader.AllianceResult);
outPacket.encodeByte(resultType.getValue());
return outPacket;
}
}
Loading