Format code

This commit is contained in:
KingRainbow44 2023-04-02 21:34:07 -04:00
parent b03870ab48
commit a3970f8e43
No known key found for this signature in database
GPG Key ID: FC2CB64B00D257BE
104 changed files with 15623 additions and 15004 deletions

View File

@ -5,26 +5,28 @@ package emu.grasscutter.net.proto;
public final class GetAllMailNotifyOuterClass { public final class GetAllMailNotifyOuterClass {
private GetAllMailNotifyOuterClass() {} private GetAllMailNotifyOuterClass() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) { public static void registerAllExtensions(com.google.protobuf.ExtensionRegistryLite registry) {}
public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry);
} }
public static void registerAllExtensions( public interface GetAllMailNotifyOrBuilder
com.google.protobuf.ExtensionRegistry registry) { extends
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface GetAllMailNotifyOrBuilder extends
// @@protoc_insertion_point(interface_extends:GetAllMailNotify) // @@protoc_insertion_point(interface_extends:GetAllMailNotify)
com.google.protobuf.MessageOrBuilder { com.google.protobuf.MessageOrBuilder {
/** /**
* <code>bool is_collected = 6;</code> * <code>bool is_collected = 6;</code>
*
* @return The isCollected. * @return The isCollected.
*/ */
boolean getIsCollected(); boolean getIsCollected();
} }
/** /**
*
*
* <pre> * <pre>
* Name: PFHIOOMPNBH * Name: PFHIOOMPNBH
* CmdId: 1442 * CmdId: 1442
@ -32,8 +34,8 @@ public final class GetAllMailNotifyOuterClass {
* *
* Protobuf type {@code GetAllMailNotify} * Protobuf type {@code GetAllMailNotify}
*/ */
public static final class GetAllMailNotify extends public static final class GetAllMailNotify extends com.google.protobuf.GeneratedMessageV3
com.google.protobuf.GeneratedMessageV3 implements implements
// @@protoc_insertion_point(message_implements:GetAllMailNotify) // @@protoc_insertion_point(message_implements:GetAllMailNotify)
GetAllMailNotifyOrBuilder { GetAllMailNotifyOrBuilder {
private static final long serialVersionUID = 0L; private static final long serialVersionUID = 0L;
@ -41,21 +43,20 @@ public final class GetAllMailNotifyOuterClass {
private GetAllMailNotify(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) { private GetAllMailNotify(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder); super(builder);
} }
private GetAllMailNotify() {
} private GetAllMailNotify() {}
@java.lang.Override @java.lang.Override
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
protected java.lang.Object newInstance( protected java.lang.Object newInstance(UnusedPrivateParameter unused) {
UnusedPrivateParameter unused) {
return new GetAllMailNotify(); return new GetAllMailNotify();
} }
@java.lang.Override @java.lang.Override
public final com.google.protobuf.UnknownFieldSet public final com.google.protobuf.UnknownFieldSet getUnknownFields() {
getUnknownFields() {
return this.unknownFields; return this.unknownFields;
} }
private GetAllMailNotify( private GetAllMailNotify(
com.google.protobuf.CodedInputStream input, com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry) com.google.protobuf.ExtensionRegistryLite extensionRegistry)
@ -74,14 +75,14 @@ public final class GetAllMailNotifyOuterClass {
case 0: case 0:
done = true; done = true;
break; break;
case 48: { case 48:
{
isCollected_ = input.readBool(); isCollected_ = input.readBool();
break; break;
} }
default: { default:
if (!parseUnknownField( {
input, unknownFields, extensionRegistry, tag)) { if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) {
done = true; done = true;
} }
break; break;
@ -91,30 +92,33 @@ public final class GetAllMailNotifyOuterClass {
} catch (com.google.protobuf.InvalidProtocolBufferException e) { } catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this); throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) { } catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException( throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this);
e).setUnfinishedMessage(this);
} finally { } finally {
this.unknownFields = unknownFields.build(); this.unknownFields = unknownFields.build();
makeExtensionsImmutable(); makeExtensionsImmutable();
} }
} }
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.internal_static_GetAllMailNotify_descriptor; return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass
.internal_static_GetAllMailNotify_descriptor;
} }
@java.lang.Override @java.lang.Override
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() { internalGetFieldAccessorTable() {
return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.internal_static_GetAllMailNotify_fieldAccessorTable return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass
.internal_static_GetAllMailNotify_fieldAccessorTable
.ensureFieldAccessorsInitialized( .ensureFieldAccessorsInitialized(
emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.class, emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.Builder.class); emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.class,
emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.Builder.class);
} }
public static final int IS_COLLECTED_FIELD_NUMBER = 6; public static final int IS_COLLECTED_FIELD_NUMBER = 6;
private boolean isCollected_; private boolean isCollected_;
/** /**
* <code>bool is_collected = 6;</code> * <code>bool is_collected = 6;</code>
*
* @return The isCollected. * @return The isCollected.
*/ */
@java.lang.Override @java.lang.Override
@ -123,6 +127,7 @@ public final class GetAllMailNotifyOuterClass {
} }
private byte memoizedIsInitialized = -1; private byte memoizedIsInitialized = -1;
@java.lang.Override @java.lang.Override
public final boolean isInitialized() { public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized; byte isInitialized = memoizedIsInitialized;
@ -134,8 +139,7 @@ public final class GetAllMailNotifyOuterClass {
} }
@java.lang.Override @java.lang.Override
public void writeTo(com.google.protobuf.CodedOutputStream output) public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
throws java.io.IOException {
if (isCollected_ != false) { if (isCollected_ != false) {
output.writeBool(6, isCollected_); output.writeBool(6, isCollected_);
} }
@ -149,8 +153,7 @@ public final class GetAllMailNotifyOuterClass {
size = 0; size = 0;
if (isCollected_ != false) { if (isCollected_ != false) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream.computeBoolSize(6, isCollected_);
.computeBoolSize(6, isCollected_);
} }
size += unknownFields.getSerializedSize(); size += unknownFields.getSerializedSize();
memoizedSize = size; memoizedSize = size;
@ -165,10 +168,10 @@ public final class GetAllMailNotifyOuterClass {
if (!(obj instanceof emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify)) { if (!(obj instanceof emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify)) {
return super.equals(obj); return super.equals(obj);
} }
emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify other = (emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify) obj; emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify other =
(emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify) obj;
if (getIsCollected() if (getIsCollected() != other.getIsCollected()) return false;
!= other.getIsCollected()) return false;
if (!unknownFields.equals(other.unknownFields)) return false; if (!unknownFields.equals(other.unknownFields)) return false;
return true; return true;
} }
@ -181,95 +184,102 @@ public final class GetAllMailNotifyOuterClass {
int hash = 41; int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode(); hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + IS_COLLECTED_FIELD_NUMBER; hash = (37 * hash) + IS_COLLECTED_FIELD_NUMBER;
hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(getIsCollected());
getIsCollected());
hash = (29 * hash) + unknownFields.hashCode(); hash = (29 * hash) + unknownFields.hashCode();
memoizedHashCode = hash; memoizedHashCode = hash;
return hash; return hash;
} }
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom( public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(
java.nio.ByteBuffer data) java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException {
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data); return PARSER.parseFrom(data);
} }
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom( public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(
java.nio.ByteBuffer data, java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException { throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry); return PARSER.parseFrom(data, extensionRegistry);
} }
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom( public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(
com.google.protobuf.ByteString data) com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException { throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data); return PARSER.parseFrom(data);
} }
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom( public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(
com.google.protobuf.ByteString data, com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry) com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException { throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry); return PARSER.parseFrom(data, extensionRegistry);
} }
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException { public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(
byte[] data) throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data); return PARSER.parseFrom(data);
} }
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom( public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(
byte[] data, byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException { throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry); return PARSER.parseFrom(data, extensionRegistry);
} }
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom( public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(
java.io.InputStream input, java.io.InputStream input) throws java.io.IOException {
com.google.protobuf.ExtensionRegistryLite extensionRegistry) return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input);
}
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
} }
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom( public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(
com.google.protobuf.CodedInputStream input) java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException { throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3 return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
.parseWithIOException(PARSER, input); PARSER, input, extensionRegistry);
} }
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify
parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input);
}
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify
parseDelimitedFrom(
java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(
PARSER, input, extensionRegistry);
}
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(
com.google.protobuf.CodedInputStream input) throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
}
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom( public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify parseFrom(
com.google.protobuf.CodedInputStream input, com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry) com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException { throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3 return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
.parseWithIOException(PARSER, input, extensionRegistry); PARSER, input, extensionRegistry);
} }
@java.lang.Override @java.lang.Override
public Builder newBuilderForType() { return newBuilder(); } public Builder newBuilderForType() {
return newBuilder();
}
public static Builder newBuilder() { public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder(); return DEFAULT_INSTANCE.toBuilder();
} }
public static Builder newBuilder(emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify prototype) {
public static Builder newBuilder(
emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
} }
@java.lang.Override @java.lang.Override
public Builder toBuilder() { public Builder toBuilder() {
return this == DEFAULT_INSTANCE return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
? new Builder() : new Builder().mergeFrom(this);
} }
@java.lang.Override @java.lang.Override
@ -279,6 +289,8 @@ public final class GetAllMailNotifyOuterClass {
return builder; return builder;
} }
/** /**
*
*
* <pre> * <pre>
* Name: PFHIOOMPNBH * Name: PFHIOOMPNBH
* CmdId: 1442 * CmdId: 1442
@ -286,38 +298,42 @@ public final class GetAllMailNotifyOuterClass {
* *
* Protobuf type {@code GetAllMailNotify} * Protobuf type {@code GetAllMailNotify}
*/ */
public static final class Builder extends public static final class Builder
com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements extends com.google.protobuf.GeneratedMessageV3.Builder<Builder>
implements
// @@protoc_insertion_point(builder_implements:GetAllMailNotify) // @@protoc_insertion_point(builder_implements:GetAllMailNotify)
emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotifyOrBuilder { emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotifyOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
getDescriptor() { return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass
return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.internal_static_GetAllMailNotify_descriptor; .internal_static_GetAllMailNotify_descriptor;
} }
@java.lang.Override @java.lang.Override
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() { internalGetFieldAccessorTable() {
return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.internal_static_GetAllMailNotify_fieldAccessorTable return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass
.internal_static_GetAllMailNotify_fieldAccessorTable
.ensureFieldAccessorsInitialized( .ensureFieldAccessorsInitialized(
emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.class, emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.Builder.class); emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.class,
emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.Builder
.class);
} }
// Construct using emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.newBuilder() // Construct using
// emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.newBuilder()
private Builder() { private Builder() {
maybeForceBuilderInitialization(); maybeForceBuilderInitialization();
} }
private Builder( private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
super(parent); super(parent);
maybeForceBuilderInitialization(); maybeForceBuilderInitialization();
} }
private void maybeForceBuilderInitialization() { private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessageV3 if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {}
.alwaysUseFieldBuilders) {
}
} }
@java.lang.Override @java.lang.Override
public Builder clear() { public Builder clear() {
super.clear(); super.clear();
@ -327,19 +343,22 @@ public final class GetAllMailNotifyOuterClass {
} }
@java.lang.Override @java.lang.Override
public com.google.protobuf.Descriptors.Descriptor public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
getDescriptorForType() { return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass
return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.internal_static_GetAllMailNotify_descriptor; .internal_static_GetAllMailNotify_descriptor;
} }
@java.lang.Override @java.lang.Override
public emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify getDefaultInstanceForType() { public emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify
return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.getDefaultInstance(); getDefaultInstanceForType() {
return emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify
.getDefaultInstance();
} }
@java.lang.Override @java.lang.Override
public emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify build() { public emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify build() {
emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify result = buildPartial(); emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify result =
buildPartial();
if (!result.isInitialized()) { if (!result.isInitialized()) {
throw newUninitializedMessageException(result); throw newUninitializedMessageException(result);
} }
@ -348,7 +367,8 @@ public final class GetAllMailNotifyOuterClass {
@java.lang.Override @java.lang.Override
public emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify buildPartial() { public emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify buildPartial() {
emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify result = new emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify(this); emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify result =
new emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify(this);
result.isCollected_ = isCollected_; result.isCollected_ = isCollected_;
onBuilt(); onBuilt();
return result; return result;
@ -358,46 +378,54 @@ public final class GetAllMailNotifyOuterClass {
public Builder clone() { public Builder clone() {
return super.clone(); return super.clone();
} }
@java.lang.Override @java.lang.Override
public Builder setField( public Builder setField(
com.google.protobuf.Descriptors.FieldDescriptor field, com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
java.lang.Object value) {
return super.setField(field, value); return super.setField(field, value);
} }
@java.lang.Override @java.lang.Override
public Builder clearField( public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) {
com.google.protobuf.Descriptors.FieldDescriptor field) {
return super.clearField(field); return super.clearField(field);
} }
@java.lang.Override @java.lang.Override
public Builder clearOneof( public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) {
com.google.protobuf.Descriptors.OneofDescriptor oneof) {
return super.clearOneof(oneof); return super.clearOneof(oneof);
} }
@java.lang.Override @java.lang.Override
public Builder setRepeatedField( public Builder setRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field, com.google.protobuf.Descriptors.FieldDescriptor field,
int index, java.lang.Object value) { int index,
java.lang.Object value) {
return super.setRepeatedField(field, index, value); return super.setRepeatedField(field, index, value);
} }
@java.lang.Override @java.lang.Override
public Builder addRepeatedField( public Builder addRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field, com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
java.lang.Object value) {
return super.addRepeatedField(field, value); return super.addRepeatedField(field, value);
} }
@java.lang.Override @java.lang.Override
public Builder mergeFrom(com.google.protobuf.Message other) { public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify) { if (other
return mergeFrom((emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify)other); instanceof emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify) {
return mergeFrom(
(emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify) other);
} else { } else {
super.mergeFrom(other); super.mergeFrom(other);
return this; return this;
} }
} }
public Builder mergeFrom(emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify other) { public Builder mergeFrom(
if (other == emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify.getDefaultInstance()) return this; emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify other) {
if (other
== emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify
.getDefaultInstance()) return this;
if (other.getIsCollected() != false) { if (other.getIsCollected() != false) {
setIsCollected(other.getIsCollected()); setIsCollected(other.getIsCollected());
} }
@ -420,7 +448,9 @@ public final class GetAllMailNotifyOuterClass {
try { try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) { } catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify) e.getUnfinishedMessage(); parsedMessage =
(emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify)
e.getUnfinishedMessage();
throw e.unwrapIOException(); throw e.unwrapIOException();
} finally { } finally {
if (parsedMessage != null) { if (parsedMessage != null) {
@ -433,6 +463,7 @@ public final class GetAllMailNotifyOuterClass {
private boolean isCollected_; private boolean isCollected_;
/** /**
* <code>bool is_collected = 6;</code> * <code>bool is_collected = 6;</code>
*
* @return The isCollected. * @return The isCollected.
*/ */
@java.lang.Override @java.lang.Override
@ -441,6 +472,7 @@ public final class GetAllMailNotifyOuterClass {
} }
/** /**
* <code>bool is_collected = 6;</code> * <code>bool is_collected = 6;</code>
*
* @param value The isCollected to set. * @param value The isCollected to set.
* @return This builder for chaining. * @return This builder for chaining.
*/ */
@ -452,6 +484,7 @@ public final class GetAllMailNotifyOuterClass {
} }
/** /**
* <code>bool is_collected = 6;</code> * <code>bool is_collected = 6;</code>
*
* @return This builder for chaining. * @return This builder for chaining.
*/ */
public Builder clearIsCollected() { public Builder clearIsCollected() {
@ -460,6 +493,7 @@ public final class GetAllMailNotifyOuterClass {
onChanged(); onChanged();
return this; return this;
} }
@java.lang.Override @java.lang.Override
public final Builder setUnknownFields( public final Builder setUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) { final com.google.protobuf.UnknownFieldSet unknownFields) {
@ -472,22 +506,25 @@ public final class GetAllMailNotifyOuterClass {
return super.mergeUnknownFields(unknownFields); return super.mergeUnknownFields(unknownFields);
} }
// @@protoc_insertion_point(builder_scope:GetAllMailNotify) // @@protoc_insertion_point(builder_scope:GetAllMailNotify)
} }
// @@protoc_insertion_point(class_scope:GetAllMailNotify) // @@protoc_insertion_point(class_scope:GetAllMailNotify)
private static final emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify DEFAULT_INSTANCE; private static final emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify
DEFAULT_INSTANCE;
static { static {
DEFAULT_INSTANCE = new emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify(); DEFAULT_INSTANCE =
new emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify();
} }
public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify getDefaultInstance() { public static emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify
getDefaultInstance() {
return DEFAULT_INSTANCE; return DEFAULT_INSTANCE;
} }
private static final com.google.protobuf.Parser<GetAllMailNotify> private static final com.google.protobuf.Parser<GetAllMailNotify> PARSER =
PARSER = new com.google.protobuf.AbstractParser<GetAllMailNotify>() { new com.google.protobuf.AbstractParser<GetAllMailNotify>() {
@java.lang.Override @java.lang.Override
public GetAllMailNotify parsePartialFrom( public GetAllMailNotify parsePartialFrom(
com.google.protobuf.CodedInputStream input, com.google.protobuf.CodedInputStream input,
@ -507,40 +544,39 @@ public final class GetAllMailNotifyOuterClass {
} }
@java.lang.Override @java.lang.Override
public emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify getDefaultInstanceForType() { public emu.grasscutter.net.proto.GetAllMailNotifyOuterClass.GetAllMailNotify
getDefaultInstanceForType() {
return DEFAULT_INSTANCE; return DEFAULT_INSTANCE;
} }
} }
private static final com.google.protobuf.Descriptors.Descriptor private static final com.google.protobuf.Descriptors.Descriptor
internal_static_GetAllMailNotify_descriptor; internal_static_GetAllMailNotify_descriptor;
private static final private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_GetAllMailNotify_fieldAccessorTable; internal_static_GetAllMailNotify_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
getDescriptor() {
return descriptor; return descriptor;
} }
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor; private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
static { static {
java.lang.String[] descriptorData = { java.lang.String[] descriptorData = {
"\n\026GetAllMailNotify.proto\"(\n\020GetAllMailNo" + "\n\026GetAllMailNotify.proto\"(\n\020GetAllMailNo"
"tify\022\024\n\014is_collected\030\006 \001(\010B\033\n\031emu.grassc" + + "tify\022\024\n\014is_collected\030\006 \001(\010B\033\n\031emu.grassc"
"utter.net.protob\006proto3" + "utter.net.protob\006proto3"
}; };
descriptor = com.google.protobuf.Descriptors.FileDescriptor descriptor =
.internalBuildGeneratedFileFrom(descriptorData, com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(
new com.google.protobuf.Descriptors.FileDescriptor[] { descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {});
}); internal_static_GetAllMailNotify_descriptor = getDescriptor().getMessageTypes().get(0);
internal_static_GetAllMailNotify_descriptor = internal_static_GetAllMailNotify_fieldAccessorTable =
getDescriptor().getMessageTypes().get(0); new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_GetAllMailNotify_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_GetAllMailNotify_descriptor, internal_static_GetAllMailNotify_descriptor,
new java.lang.String[] { "IsCollected", }); new java.lang.String[] {
"IsCollected",
});
} }
// @@protoc_insertion_point(outer_class_scope) // @@protoc_insertion_point(outer_class_scope)

View File

@ -105,7 +105,9 @@ public final class GameData {
private static final Int2ObjectMap<AvatarCostumeData> avatarCostumeDataMap = private static final Int2ObjectMap<AvatarCostumeData> avatarCostumeDataMap =
new Int2ObjectLinkedOpenHashMap<>(); new Int2ObjectLinkedOpenHashMap<>();
@Getter private static final Int2ObjectMap<AvatarReplaceCostumeData> avatarReplaceCostumeDataMap = new Int2ObjectOpenHashMap<>(); @Getter
private static final Int2ObjectMap<AvatarReplaceCostumeData> avatarReplaceCostumeDataMap =
new Int2ObjectOpenHashMap<>();
@Getter @Getter
private static final Int2ObjectMap<AvatarCurveData> avatarCurveDataMap = private static final Int2ObjectMap<AvatarCurveData> avatarCurveDataMap =
@ -226,8 +228,12 @@ public final class GameData {
@Getter @Getter
private static final Int2ObjectMap<GatherData> gatherDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<GatherData> gatherDataMap = new Int2ObjectOpenHashMap<>();
@Getter @Deprecated // This is to prevent people from using this map. This is for the resource loader only!
private static final Int2ObjectMap<GuideTriggerData> guideTriggerDataMap = new Int2ObjectOpenHashMap<>(); @Getter
@Deprecated // This is to prevent people from using this map. This is for the resource loader
// only!
private static final Int2ObjectMap<GuideTriggerData> guideTriggerDataMap =
new Int2ObjectOpenHashMap<>();
@Getter @Getter
private static final Int2ObjectMap<HomeWorldBgmData> homeWorldBgmDataMap = private static final Int2ObjectMap<HomeWorldBgmData> homeWorldBgmDataMap =
@ -253,7 +259,9 @@ public final class GameData {
@Getter @Getter
private static final Int2ObjectMap<MonsterDescribeData> monsterDescribeDataMap = private static final Int2ObjectMap<MonsterDescribeData> monsterDescribeDataMap =
new Int2ObjectOpenHashMap<>(); new Int2ObjectOpenHashMap<>();
@Getter private static final Int2ObjectMap<MonsterSpecialNameData> monsterSpecialNameDataMap =
@Getter
private static final Int2ObjectMap<MonsterSpecialNameData> monsterSpecialNameDataMap =
new Int2ObjectOpenHashMap<>(); new Int2ObjectOpenHashMap<>();
@Getter @Getter
@ -412,8 +420,12 @@ public final class GameData {
@Getter private static final List<OpenStateData> openStateList = new ArrayList<>(); @Getter private static final List<OpenStateData> openStateList = new ArrayList<>();
@Getter private static final Map<Integer, List<Integer>> scenePointsPerScene = new HashMap<>(); @Getter private static final Map<Integer, List<Integer>> scenePointsPerScene = new HashMap<>();
@Getter private static final Map<String, ScriptSceneData> scriptSceneDataMap = new HashMap<>(); @Getter private static final Map<String, ScriptSceneData> scriptSceneDataMap = new HashMap<>();
@Getter private static final Map<String, GuideTriggerData> guideTriggerDataStringMap = new HashMap<>();
@Getter private static final Map<String, ConfigLevelEntity> configLevelEntityDataMap = new HashMap<>(); @Getter
private static final Map<String, GuideTriggerData> guideTriggerDataStringMap = new HashMap<>();
@Getter
private static final Map<String, ConfigLevelEntity> configLevelEntityDataMap = new HashMap<>();
@Getter @Getter
private static final Int2ObjectMap<IntSet> proudSkillGroupLevels = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<IntSet> proudSkillGroupLevels = new Int2ObjectOpenHashMap<>();

View File

@ -581,40 +581,50 @@ public class ResourceLoader {
private static void loadConfigData() { private static void loadConfigData() {
loadConfigData(GameData.getAvatarConfigData(), "BinOutput/Avatar/", ConfigEntityAvatar.class); loadConfigData(GameData.getAvatarConfigData(), "BinOutput/Avatar/", ConfigEntityAvatar.class);
loadConfigData(GameData.getMonsterConfigData(), "BinOutput/Monster/", ConfigEntityMonster.class); loadConfigData(
loadConfigDataMap(GameData.getGadgetConfigData(), "BinOutput/Gadget/", ConfigEntityGadget.class); GameData.getMonsterConfigData(), "BinOutput/Monster/", ConfigEntityMonster.class);
loadConfigDataMap(
GameData.getGadgetConfigData(), "BinOutput/Gadget/", ConfigEntityGadget.class);
} }
private static <T extends ConfigEntityBase> void loadConfigData(Map<String,T> targetMap, String folderPath, Class<T> configClass) { private static <T extends ConfigEntityBase> void loadConfigData(
Map<String, T> targetMap, String folderPath, Class<T> configClass) {
val className = configClass.getName(); val className = configClass.getName();
try (val stream = Files.newDirectoryStream(getResourcePath(folderPath), "*.json")) { try (val stream = Files.newDirectoryStream(getResourcePath(folderPath), "*.json")) {
stream.forEach(path -> { stream.forEach(
path -> {
try { try {
val name = path.getFileName().toString().replace(".json", ""); val name = path.getFileName().toString().replace(".json", "");
targetMap.put(name, JsonUtils.loadToClass(path, configClass)); targetMap.put(name, JsonUtils.loadToClass(path, configClass));
} catch (Exception e) { } catch (Exception e) {
Grasscutter.getLogger().error("failed to load {} entries for {}", className, path.toString(), e); Grasscutter.getLogger()
.error("failed to load {} entries for {}", className, path.toString(), e);
} }
}); });
Grasscutter.getLogger().debug("Loaded {} {} entries.", GameData.getMonsterConfigData().size(), className); Grasscutter.getLogger()
.debug("Loaded {} {} entries.", GameData.getMonsterConfigData().size(), className);
} catch (IOException e) { } catch (IOException e) {
Grasscutter.getLogger().error("Failed to load {} folder.", className); Grasscutter.getLogger().error("Failed to load {} folder.", className);
} }
} }
private static <T extends ConfigEntityBase> void loadConfigDataMap(Map<String,T> targetMap, String folderPath, Class<T> configClass) { private static <T extends ConfigEntityBase> void loadConfigDataMap(
Map<String, T> targetMap, String folderPath, Class<T> configClass) {
val className = configClass.getName(); val className = configClass.getName();
try (val stream = Files.newDirectoryStream(getResourcePath(folderPath), "*.json")) { try (val stream = Files.newDirectoryStream(getResourcePath(folderPath), "*.json")) {
stream.forEach(path -> { stream.forEach(
path -> {
try { try {
targetMap.putAll(JsonUtils.loadToMap(path, String.class, configClass)); targetMap.putAll(JsonUtils.loadToMap(path, String.class, configClass));
} catch (Exception e) { } catch (Exception e) {
Grasscutter.getLogger().error("failed to load {} entries for {}", className, path.toString(), e); Grasscutter.getLogger()
.error("failed to load {} entries for {}", className, path.toString(), e);
} }
}); });
Grasscutter.getLogger().debug("Loaded {} {} entries.", GameData.getMonsterConfigData().size(), className); Grasscutter.getLogger()
.debug("Loaded {} {} entries.", GameData.getMonsterConfigData().size(), className);
} catch (IOException e) { } catch (IOException e) {
Grasscutter.getLogger().error("Failed to load {} folder.", className); Grasscutter.getLogger().error("Failed to load {} folder.", className);
} }

View File

@ -1,7 +1,6 @@
package emu.grasscutter.data.common; package emu.grasscutter.data.common;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.dungeon.DailyDungeonData; import emu.grasscutter.data.excels.dungeon.DailyDungeonData;
@ -19,17 +18,30 @@ public final class PointData {
@Getter private Position rot; @Getter private Position rot;
@Getter private Position size; @Getter private Position size;
@SerializedName(value="dungeonIds", alternate={"JHHFPGJNMIN"}) @SerializedName(
@Getter private int[] dungeonIds; value = "dungeonIds",
alternate = {"JHHFPGJNMIN"})
@Getter
private int[] dungeonIds;
@SerializedName(value="dungeonRandomList", alternate={"OIBKFJNBLHO"}) @SerializedName(
@Getter private int[] dungeonRandomList; value = "dungeonRandomList",
alternate = {"OIBKFJNBLHO"})
@Getter
private int[] dungeonRandomList;
@SerializedName(value="groupIDs", alternate={"HFOBOOHKBGF"}) @SerializedName(
@Getter private int[] groupIDs; value = "groupIDs",
alternate = {"HFOBOOHKBGF"})
@Getter
private int[] groupIDs;
@SerializedName(value="tranSceneId", alternate={"JHBICGBAPIH"}) @SerializedName(
@Getter @Setter private int tranSceneId; value = "tranSceneId",
alternate = {"JHBICGBAPIH"})
@Getter
@Setter
private int tranSceneId;
public String getType() { public String getType() {
return $type; return $type;

View File

@ -1,11 +1,6 @@
package emu.grasscutter.data.excels.monster; package emu.grasscutter.data.excels.monster;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GameResource; import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType; import emu.grasscutter.data.ResourceType;
@ -14,12 +9,27 @@ import emu.grasscutter.data.common.PropGrowCurve;
import emu.grasscutter.data.excels.GadgetData; import emu.grasscutter.data.excels.GadgetData;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.MonsterType; import emu.grasscutter.game.props.MonsterType;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import lombok.Getter; import lombok.Getter;
@ResourceType(name = "MonsterExcelConfigData.json", loadPriority = LoadPriority.LOW) @ResourceType(name = "MonsterExcelConfigData.json", loadPriority = LoadPriority.LOW)
@Getter @Getter
public class MonsterData extends GameResource { public class MonsterData extends GameResource {
static public Set<FightProperty> definedFightProperties = Set.of(FightProperty.FIGHT_PROP_BASE_HP, FightProperty.FIGHT_PROP_BASE_ATTACK, FightProperty.FIGHT_PROP_BASE_DEFENSE, FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT, FightProperty.FIGHT_PROP_FIRE_SUB_HURT, FightProperty.FIGHT_PROP_ELEC_SUB_HURT, FightProperty.FIGHT_PROP_WATER_SUB_HURT, FightProperty.FIGHT_PROP_GRASS_SUB_HURT, FightProperty.FIGHT_PROP_WIND_SUB_HURT, FightProperty.FIGHT_PROP_ROCK_SUB_HURT, FightProperty.FIGHT_PROP_ICE_SUB_HURT); public static Set<FightProperty> definedFightProperties =
Set.of(
FightProperty.FIGHT_PROP_BASE_HP,
FightProperty.FIGHT_PROP_BASE_ATTACK,
FightProperty.FIGHT_PROP_BASE_DEFENSE,
FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT,
FightProperty.FIGHT_PROP_FIRE_SUB_HURT,
FightProperty.FIGHT_PROP_ELEC_SUB_HURT,
FightProperty.FIGHT_PROP_WATER_SUB_HURT,
FightProperty.FIGHT_PROP_GRASS_SUB_HURT,
FightProperty.FIGHT_PROP_WIND_SUB_HURT,
FightProperty.FIGHT_PROP_ROCK_SUB_HURT,
FightProperty.FIGHT_PROP_ICE_SUB_HURT);
@Getter(onMethod_ = @Override) @Getter(onMethod_ = @Override)
private int id; private int id;
@ -42,8 +52,10 @@ public class MonsterData extends GameResource {
@SerializedName("hpBase") @SerializedName("hpBase")
private float baseHp; private float baseHp;
@SerializedName("attackBase") @SerializedName("attackBase")
private float baseAttack; private float baseAttack;
@SerializedName("defenseBase") @SerializedName("defenseBase")
private float baseDefense; private float baseDefense;
@ -87,7 +99,8 @@ public class MonsterData extends GameResource {
if (this.describeData == null) { if (this.describeData == null) {
return; return;
} }
for(Entry<Integer, MonsterSpecialNameData> entry: GameData.getMonsterSpecialNameDataMap().entrySet()) { for (Entry<Integer, MonsterSpecialNameData> entry :
GameData.getMonsterSpecialNameDataMap().entrySet()) {
if (entry.getValue().getSpecialNameLabId() == this.getDescribeData().getSpecialNameLabId()) { if (entry.getValue().getSpecialNameLabId() == this.getDescribeData().getSpecialNameLabId()) {
this.specialNameId = entry.getKey(); this.specialNameId = entry.getKey();
break; break;

View File

@ -13,9 +13,16 @@ public class MonsterDescribeData extends GameResource {
private int id; private int id;
private long nameTextMapHash; private long nameTextMapHash;
@SerializedName(value = "titleId", alternate={"titleID"})
@SerializedName(
value = "titleId",
alternate = {"titleID"})
private int titleId; private int titleId;
@SerializedName(value = "specialNameLabId", alternate={"specialNameLabID"})
@SerializedName(
value = "specialNameLabId",
alternate = {"specialNameLabID"})
private int specialNameLabId; private int specialNameLabId;
private MonsterSpecialNameData specialNameData; private MonsterSpecialNameData specialNameData;
} }

View File

@ -22,7 +22,6 @@ import emu.grasscutter.game.mail.Mail;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.GameMainQuest; import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.game.world.SceneGroupInstance; import emu.grasscutter.game.world.SceneGroupInstance;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -457,8 +456,9 @@ public final class DatabaseHelper {
} }
public static SceneGroupInstance loadGroupInstance(int groupId, Player owner) { public static SceneGroupInstance loadGroupInstance(int groupId, Player owner) {
return DatabaseManager.getGameDatastore().find(SceneGroupInstance.class) return DatabaseManager.getGameDatastore()
.filter(Filters.and(Filters.eq("ownerUid", owner.getUid()), .find(SceneGroupInstance.class)
Filters.eq("groupId", groupId))).first(); .filter(Filters.and(Filters.eq("ownerUid", owner.getUid()), Filters.eq("groupId", groupId)))
.first();
} }
} }

View File

@ -43,14 +43,13 @@ import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.ints.*;
import java.util.*; import java.util.*;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.annotation.Nonnull;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.val; import lombok.val;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import javax.annotation.Nonnull;
@Entity(value = "avatars", useDiscriminator = false) @Entity(value = "avatars", useDiscriminator = false)
public class Avatar { public class Avatar {
@Transient @Getter private final Int2ObjectMap<GameItem> equips; @Transient @Getter private final Int2ObjectMap<GameItem> equips;
@ -237,8 +236,7 @@ public class Avatar {
} }
/** /**
* Changes this avatar's skill depot. * Changes this avatar's skill depot. Does not notify the player of the change.
* Does not notify the player of the change.
* *
* @param skillDepot The new skill depot. * @param skillDepot The new skill depot.
*/ */
@ -275,7 +273,8 @@ public class Avatar {
} }
/** /**
* Changes the avatar's element to the target element, if the character has values for it set in the candSkillDepot * Changes the avatar's element to the target element, if the character has values for it set in
* the candSkillDepot
* *
* @param elementTypeToChange element to change to * @param elementTypeToChange element to change to
* @return false if failed or already using that element, true if it actually changed * @return false if failed or already using that element, true if it actually changed
@ -285,8 +284,7 @@ public class Avatar {
var candSkillDepotIndex = elementTypeToChange.getDepotIndex(); var candSkillDepotIndex = elementTypeToChange.getDepotIndex();
// if no candidate skill to change or index out of bound // if no candidate skill to change or index out of bound
if (candSkillDepotIdsList == null || if (candSkillDepotIdsList == null || candSkillDepotIndex >= candSkillDepotIdsList.size()) {
candSkillDepotIndex >= candSkillDepotIdsList.size()) {
return false; return false;
} }

View File

@ -6,7 +6,8 @@ import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify;
public class BasicDungeonSettleListener implements DungeonSettleListener { public class BasicDungeonSettleListener implements DungeonSettleListener {
@Override @Override
public void onDungeonSettle(DungeonManager dungeonManager, BaseDungeonResult.DungeonEndReason endReason) { public void onDungeonSettle(
DungeonManager dungeonManager, BaseDungeonResult.DungeonEndReason endReason) {
var scene = dungeonManager.getScene(); var scene = dungeonManager.getScene();
var dungeonData = dungeonManager.getDungeonData(); var dungeonData = dungeonManager.getDungeonData();
var time = scene.getSceneTimeSeconds() - dungeonManager.getStartSceneTime(); var time = scene.getSceneTimeSeconds() - dungeonManager.getStartSceneTime();

View File

@ -24,20 +24,17 @@ import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.val; import lombok.val;
import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/** /**
* TODO handle time limits * TODO handle time limits TODO handle respawn points TODO handle team wipes and respawns TODO check
* TODO handle respawn points * monster level and levelConfigMap
* TODO handle team wipes and respawns
* TODO check monster level and levelConfigMap
*/ */
public final class DungeonManager { public final class DungeonManager {
@Getter private final Scene scene; @Getter private final Scene scene;
@ -71,14 +68,12 @@ public final class DungeonManager {
if (getScene().getWorld().getServer().getDungeonSystem().triggerCondition(cond, params)) { if (getScene().getWorld().getServer().getDungeonSystem().triggerCondition(cond, params)) {
finishedConditions[i] = 1; finishedConditions[i] = 1;
} }
} }
} }
if (isFinishedSuccessfully()) { if (isFinishedSuccessfully()) {
finishDungeon(); finishDungeon();
} }
} }
public boolean isFinishedSuccessfully() { public boolean isFinishedSuccessfully() {
@ -98,15 +93,16 @@ public final class DungeonManager {
return false; return false;
} }
scene.broadcastPacket(new PacketDungeonWayPointNotify(activeDungeonWayPoints.add(pointId), activeDungeonWayPoints)); scene.broadcastPacket(
new PacketDungeonWayPointNotify(
activeDungeonWayPoints.add(pointId), activeDungeonWayPoints));
newestWayPoint = pointId; newestWayPoint = pointId;
Grasscutter.getLogger().debug("[unimplemented respawn] activated respawn point {}", pointId); Grasscutter.getLogger().debug("[unimplemented respawn] activated respawn point {}", pointId);
return true; return true;
} }
@Nullable @Nullable public Position getRespawnLocation() {
public Position getRespawnLocation() {
if (newestWayPoint == 0) { // validity is checked before setting it, so if != 0 its always valid if (newestWayPoint == 0) { // validity is checked before setting it, so if != 0 its always valid
return null; return null;
} }
@ -123,7 +119,9 @@ public final class DungeonManager {
} }
public boolean getStatueDrops(Player player, boolean useCondensed, int groupId) { public boolean getStatueDrops(Player player, boolean useCondensed, int groupId) {
if (!isFinishedSuccessfully() || dungeonData.getRewardPreviewData() == null || dungeonData.getRewardPreviewData().getPreviewItems().length == 0) { if (!isFinishedSuccessfully()
|| dungeonData.getRewardPreviewData() == null
|| dungeonData.getRewardPreviewData().getPreviewItems().length == 0) {
return false; return false;
} }
@ -132,7 +130,6 @@ public final class DungeonManager {
return false; return false;
} }
if (!handleCost(player, useCondensed)) { if (!handleCost(player, useCondensed)) {
return false; return false;
} }
@ -198,8 +195,10 @@ public final class DungeonManager {
// Roll items for this group. // Roll items for this group.
// Here, we have to handle stacking, or the client will not display results correctly. // Here, we have to handle stacking, or the client will not display results correctly.
// For now, we use the following logic: If the possible drop item are a list of multiple items, // For now, we use the following logic: If the possible drop item are a list of multiple
// we roll them separately. If not, we stack them. This should work out in practice, at least // items,
// we roll them separately. If not, we stack them. This should work out in practice, at
// least
// for the currently existing set of dungeons. // for the currently existing set of dungeons.
if (entry.getItems().size() == 1) { if (entry.getItems().size() == 1) {
rewards.add(new GameItem(entry.getItems().get(0), amount)); rewards.add(new GameItem(entry.getItems().get(0), amount));
@ -207,7 +206,8 @@ public final class DungeonManager {
for (int i = 0; i < amount; i++) { for (int i = 0; i < amount; i++) {
// int itemIndex = ThreadLocalRandom.current().nextInt(0, entry.getItems().size()); // int itemIndex = ThreadLocalRandom.current().nextInt(0, entry.getItems().size());
// int itemId = entry.getItems().get(itemIndex); // int itemId = entry.getItems().get(itemIndex);
int itemId = Utils.drawRandomListElement(entry.getItems(), entry.getItemProbabilities()); int itemId =
Utils.drawRandomListElement(entry.getItems(), entry.getItemProbabilities());
rewards.add(new GameItem(itemId, 1)); rewards.add(new GameItem(itemId, 1));
} }
} }
@ -215,7 +215,8 @@ public final class DungeonManager {
} }
// Otherwise, we fall back to the preview data. // Otherwise, we fall back to the preview data.
else { else {
Grasscutter.getLogger().info("No drop data found or dungeon {}, falling back to preview data ...", dungeonId); Grasscutter.getLogger()
.info("No drop data found or dungeon {}, falling back to preview data ...", dungeonId);
for (ItemParamData param : dungeonData.getRewardPreviewData().getPreviewItems()) { for (ItemParamData param : dungeonData.getRewardPreviewData().getPreviewItems()) {
rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1))); rewards.add(new GameItem(param.getId(), Math.max(param.getCount(), 1)));
} }
@ -232,9 +233,13 @@ public final class DungeonManager {
case DUNGEON_ACTIVITY -> { case DUNGEON_ACTIVITY -> {
switch (getDungeonData().getPlayType()) { switch (getDungeonData().getPlayType()) {
case DUNGEON_PLAY_TYPE_TRIAL_AVATAR -> { case DUNGEON_PLAY_TYPE_TRIAL_AVATAR -> {
val activityHandler = player.getActivityManager() val activityHandler =
.getActivityHandlerAs(ActivityType.NEW_ACTIVITY_TRIAL_AVATAR, TrialAvatarActivityHandler.class); player
activityHandler.ifPresent(trialAvatarActivityHandler -> .getActivityManager()
.getActivityHandlerAs(
ActivityType.NEW_ACTIVITY_TRIAL_AVATAR, TrialAvatarActivityHandler.class);
activityHandler.ifPresent(
trialAvatarActivityHandler ->
this.trialTeam = trialAvatarActivityHandler.getTrialAvatarDungeonTeam()); this.trialTeam = trialAvatarActivityHandler.getTrialAvatarDungeonTeam());
} }
} }
@ -256,8 +261,12 @@ public final class DungeonManager {
public void startDungeon() { public void startDungeon() {
this.startSceneTime = scene.getSceneTimeSeconds(); this.startSceneTime = scene.getSceneTimeSeconds();
scene.getPlayers().forEach(p -> { scene
p.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_ENTER_DUNGEON, dungeonData.getId()); .getPlayers()
.forEach(
p -> {
p.getQuestManager()
.queueEvent(QuestContent.QUEST_CONTENT_ENTER_DUNGEON, dungeonData.getId());
applyTrialTeam(p); applyTrialTeam(p);
}); });
} }
@ -268,10 +277,16 @@ public final class DungeonManager {
} }
public void notifyEndDungeon(boolean successfully) { public void notifyEndDungeon(boolean successfully) {
scene.getPlayers().forEach(p -> { scene
.getPlayers()
.forEach(
p -> {
// Quest trigger // Quest trigger
p.getQuestManager().queueEvent(successfully ? p.getQuestManager()
QuestContent.QUEST_CONTENT_FINISH_DUNGEON : QuestContent.QUEST_CONTENT_FAIL_DUNGEON, .queueEvent(
successfully
? QuestContent.QUEST_CONTENT_FINISH_DUNGEON
: QuestContent.QUEST_CONTENT_FAIL_DUNGEON,
dungeonData.getId()); dungeonData.getId());
// Battle pass trigger // Battle pass trigger
@ -279,7 +294,9 @@ public final class DungeonManager {
p.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_FINISH_DUNGEON); p.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_FINISH_DUNGEON);
} }
}); });
scene.getScriptManager().callEvent(new ScriptArgs(0, EventType.EVENT_DUNGEON_SETTLE, successfully ? 1 : 0)); scene
.getScriptManager()
.callEvent(new ScriptArgs(0, EventType.EVENT_DUNGEON_SETTLE, successfully ? 1 : 0));
} }
public void quitDungeon() { public void quitDungeon() {

View File

@ -16,13 +16,13 @@ import emu.grasscutter.server.packet.send.PacketDungeonEntryInfoRsp;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.List;
import lombok.val; import lombok.val;
import org.reflections.Reflections; import org.reflections.Reflections;
import java.util.List;
public class DungeonSystem extends BaseGameSystem { public class DungeonSystem extends BaseGameSystem {
private static final BasicDungeonSettleListener basicDungeonSettleObserver = new BasicDungeonSettleListener(); private static final BasicDungeonSettleListener basicDungeonSettleObserver =
new BasicDungeonSettleListener();
private final Int2ObjectMap<DungeonBaseHandler> passCondHandlers; private final Int2ObjectMap<DungeonBaseHandler> passCondHandlers;
public DungeonSystem(GameServer server) { public DungeonSystem(GameServer server) {
@ -32,7 +32,10 @@ public class DungeonSystem extends BaseGameSystem {
} }
public void registerHandlers() { public void registerHandlers() {
this.registerHandlers(this.passCondHandlers, "emu.grasscutter.game.dungeons.pass_condition", DungeonBaseHandler.class); this.registerHandlers(
this.passCondHandlers,
"emu.grasscutter.game.dungeons.pass_condition",
DungeonBaseHandler.class);
} }
public <T> void registerHandlers(Int2ObjectMap<T> map, String packageName, Class<T> clazz) { public <T> void registerHandlers(Int2ObjectMap<T> map, String packageName, Class<T> clazz) {
@ -70,11 +73,13 @@ public class DungeonSystem extends BaseGameSystem {
player.sendPacket(new PacketDungeonEntryInfoRsp(player, entry.getPointData())); player.sendPacket(new PacketDungeonEntryInfoRsp(player, entry.getPointData()));
} }
public boolean triggerCondition(DungeonPassConfigData.DungeonPassCondition condition, int... params) { public boolean triggerCondition(
DungeonPassConfigData.DungeonPassCondition condition, int... params) {
var handler = passCondHandlers.get(condition.getCondType().ordinal()); var handler = passCondHandlers.get(condition.getCondType().ordinal());
if (handler == null) { if (handler == null) {
Grasscutter.getLogger().debug("Could not trigger condition {} at {}", condition.getCondType(), params); Grasscutter.getLogger()
.debug("Could not trigger condition {} at {}", condition.getCondType(), params);
return false; return false;
} }
@ -87,7 +92,12 @@ public class DungeonSystem extends BaseGameSystem {
if (data == null) { if (data == null) {
return false; return false;
} }
Grasscutter.getLogger().info("{}({}) is trying to enter dungeon {}" ,player.getNickname(),player.getUid(),dungeonId); Grasscutter.getLogger()
.info(
"{}({}) is trying to enter dungeon {}",
player.getNickname(),
player.getUid(),
dungeonId);
int sceneId = data.getSceneId(); int sceneId = data.getSceneId();
var scene = player.getScene(); var scene = player.getScene();
@ -102,16 +112,20 @@ public class DungeonSystem extends BaseGameSystem {
return true; return true;
} }
/** /** used in tower dungeons handoff */
* used in tower dungeons handoff public boolean handoffDungeon(
*/ Player player, int dungeonId, List<DungeonSettleListener> dungeonSettleListeners) {
public boolean handoffDungeon(Player player, int dungeonId, List<DungeonSettleListener> dungeonSettleListeners) {
DungeonData data = GameData.getDungeonDataMap().get(dungeonId); DungeonData data = GameData.getDungeonDataMap().get(dungeonId);
if (data == null) { if (data == null) {
return false; return false;
} }
Grasscutter.getLogger().info("{}({}) is trying to enter tower dungeon {}" ,player.getNickname(),player.getUid(),dungeonId); Grasscutter.getLogger()
.info(
"{}({}) is trying to enter tower dungeon {}",
player.getNickname(),
player.getUid(),
dungeonId);
if (player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)) { if (player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)) {
dungeonSettleListeners.forEach(player.getScene()::addDungeonSettleObserver); dungeonSettleListeners.forEach(player.getScene()::addDungeonSettleObserver);
@ -150,7 +164,6 @@ public class DungeonSystem extends BaseGameSystem {
player.getTeamManager().cleanTemporaryTeam(); player.getTeamManager().cleanTemporaryTeam();
player.getTowerManager().clearEntry(); player.getTowerManager().clearEntry();
// Transfer player back to world // Transfer player back to world
player.getWorld().transferPlayerToScene(player, prevScene, prevPos); player.getWorld().transferPlayerToScene(player, prevScene, prevPos);
} }

View File

@ -1,7 +1,6 @@
package emu.grasscutter.game.dungeons; package emu.grasscutter.game.dungeons;
import emu.grasscutter.game.dungeons.dungeon_results.BaseDungeonResult.DungeonEndReason; import emu.grasscutter.game.dungeons.dungeon_results.BaseDungeonResult.DungeonEndReason;
import emu.grasscutter.game.world.SceneGroupInstance;
import emu.grasscutter.game.dungeons.dungeon_results.TowerResult; import emu.grasscutter.game.dungeons.dungeon_results.TowerResult;
import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify; import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify;
import emu.grasscutter.server.packet.send.PacketTowerFloorRecordChangeNotify; import emu.grasscutter.server.packet.send.PacketTowerFloorRecordChangeNotify;
@ -12,9 +11,13 @@ public class TowerDungeonSettleListener implements DungeonSettleListener {
public void onDungeonSettle(DungeonManager dungeonManager, DungeonEndReason endReason) { public void onDungeonSettle(DungeonManager dungeonManager, DungeonEndReason endReason) {
var scene = dungeonManager.getScene(); var scene = dungeonManager.getScene();
var dungeonData = dungeonManager.getDungeonData(); var dungeonData = dungeonManager.getDungeonData();
if (scene.getLoadedGroups().stream().anyMatch(g -> { if (scene.getLoadedGroups().stream()
.anyMatch(
g -> {
var variables = scene.getScriptManager().getVariables(g.id); var variables = scene.getScriptManager().getVariables(g.id);
return variables != null && variables.containsKey("stage") && variables.get("stage") == 1; return variables != null
&& variables.containsKey("stage")
&& variables.get("stage") == 1;
})) { })) {
return; return;
} }
@ -22,17 +25,16 @@ public class TowerDungeonSettleListener implements DungeonSettleListener {
var towerManager = scene.getPlayers().get(0).getTowerManager(); var towerManager = scene.getPlayers().get(0).getTowerManager();
towerManager.notifyCurLevelRecordChangeWhenDone(3); towerManager.notifyCurLevelRecordChangeWhenDone(3);
scene.broadcastPacket(new PacketTowerFloorRecordChangeNotify( scene.broadcastPacket(
towerManager.getCurrentFloorId(), new PacketTowerFloorRecordChangeNotify(
3, towerManager.getCurrentFloorId(), 3, towerManager.canEnterScheduleFloor()));
towerManager.canEnterScheduleFloor()
));
var challenge = scene.getChallenge(); var challenge = scene.getChallenge();
var dungeonStats = new DungeonEndStats(scene.getKilledMonsterCount(), challenge.getFinishedTime(), 0, endReason); var dungeonStats =
new DungeonEndStats(
scene.getKilledMonsterCount(), challenge.getFinishedTime(), 0, endReason);
var result = new TowerResult(dungeonData, dungeonStats, towerManager, challenge); var result = new TowerResult(dungeonData, dungeonStats, towerManager, challenge);
scene.broadcastPacket(new PacketDungeonSettleNotify(result)); scene.broadcastPacket(new PacketDungeonSettleNotify(result));
} }
} }

View File

@ -17,7 +17,6 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.val;
@Getter @Getter
@Setter @Setter
@ -88,18 +87,29 @@ public class WorldChallenge {
var scene = this.getScene(); var scene = this.getScene();
var dungeonManager = scene.getDungeonManager(); var dungeonManager = scene.getDungeonManager();
if (dungeonManager != null && dungeonManager.getDungeonData() != null) { if (dungeonManager != null && dungeonManager.getDungeonData() != null) {
scene.getPlayers().forEach(p -> p.getActivityManager().triggerWatcher( scene
.getPlayers()
.forEach(
p ->
p.getActivityManager()
.triggerWatcher(
WatcherTriggerType.TRIGGER_FINISH_CHALLENGE, WatcherTriggerType.TRIGGER_FINISH_CHALLENGE,
String.valueOf(dungeonManager.getDungeonData().getId()), String.valueOf(dungeonManager.getDungeonData().getId()),
String.valueOf(this.getGroup().id), String.valueOf(this.getGroup().id),
String.valueOf(this.getChallengeId()) String.valueOf(this.getChallengeId())));
));
} }
scene.getScriptManager().callEvent( scene
.getScriptManager()
.callEvent(
// TODO record the time in PARAM2 and used in action // TODO record the time in PARAM2 and used in action
new ScriptArgs(this.getGroup().id, EventType.EVENT_CHALLENGE_SUCCESS).setParam2(finishedTime)); new ScriptArgs(this.getGroup().id, EventType.EVENT_CHALLENGE_SUCCESS)
this.getScene().triggerDungeonEvent(DungeonPassConditionType.DUNGEON_COND_FINISH_CHALLENGE, getChallengeId(), getChallengeIndex()); .setParam2(finishedTime));
this.getScene()
.triggerDungeonEvent(
DungeonPassConditionType.DUNGEON_COND_FINISH_CHALLENGE,
getChallengeId(),
getChallengeIndex());
this.challengeTriggers.forEach(t -> t.onFinish(this)); this.challengeTriggers.forEach(t -> t.onFinish(this));
} }
@ -108,7 +118,9 @@ public class WorldChallenge {
if (!this.inProgress()) return; if (!this.inProgress()) return;
this.finish(true); this.finish(true);
this.getScene().getScriptManager().callEvent(new ScriptArgs(this.getGroup().id, EventType.EVENT_CHALLENGE_FAIL)); this.getScene()
.getScriptManager()
.callEvent(new ScriptArgs(this.getGroup().id, EventType.EVENT_CHALLENGE_FAIL));
challengeTriggers.forEach(t -> t.onFinish(this)); challengeTriggers.forEach(t -> t.onFinish(this));
} }
@ -147,8 +159,7 @@ public class WorldChallenge {
if (!this.inProgress()) return; if (!this.inProgress()) return;
var triggerGroup = trigger.getCurrentGroup(); var triggerGroup = trigger.getCurrentGroup();
if (triggerGroup == null || if (triggerGroup == null || triggerGroup.id != getGroup().id) {
triggerGroup.id != getGroup().id) {
return; return;
} }

View File

@ -4,10 +4,9 @@ import emu.grasscutter.data.GameData;
import emu.grasscutter.game.dungeons.challenge.WorldChallenge; import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import lombok.val;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import lombok.val;
public abstract class ChallengeFactory { public abstract class ChallengeFactory {
private static final List<ChallengeFactoryHandler> challengeFactoryHandlers = new ArrayList<>(); private static final List<ChallengeFactoryHandler> challengeFactoryHandlers = new ArrayList<>();
@ -21,7 +20,15 @@ public abstract class ChallengeFactory {
challengeFactoryHandlers.add(new TriggerInTimeChallengeFactoryHandler()); challengeFactoryHandlers.add(new TriggerInTimeChallengeFactoryHandler());
} }
public static WorldChallenge getChallenge(int localChallengeId, int challengeDataId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group){ public static WorldChallenge getChallenge(
int localChallengeId,
int challengeDataId,
int param3,
int param4,
int param5,
int param6,
Scene scene,
SceneGroup group) {
val challengeData = GameData.getDungeonChallengeConfigDataMap().get(challengeDataId); val challengeData = GameData.getDungeonChallengeConfigDataMap().get(challengeDataId);
val challengeType = challengeData.getChallengeType(); val challengeType = challengeData.getChallengeType();
@ -29,7 +36,8 @@ public abstract class ChallengeFactory {
if (!handler.isThisType(challengeType)) { if (!handler.isThisType(challengeType)) {
continue; continue;
} }
return handler.build(localChallengeId, challengeDataId, param3, param4, param5, param6, scene, group); return handler.build(
localChallengeId, challengeDataId, param3, param4, param5, param6, scene, group);
} }
return null; return null;
} }

View File

@ -7,5 +7,14 @@ import emu.grasscutter.scripts.data.SceneGroup;
public interface ChallengeFactoryHandler { public interface ChallengeFactoryHandler {
boolean isThisType(ChallengeType challengeType); boolean isThisType(ChallengeType challengeType);
WorldChallenge build(int challengeIndex, int challengeId, int param3, int param4, int param5, int param6, Scene scene, SceneGroup group);
WorldChallenge build(
int challengeIndex,
int challengeId,
int param3,
int param4,
int param5,
int param6,
Scene scene,
SceneGroup group);
} }

View File

@ -1,16 +1,15 @@
package emu.grasscutter.game.dungeons.challenge.factory; package emu.grasscutter.game.dungeons.challenge.factory;
import static emu.grasscutter.game.dungeons.challenge.enums.ChallengeType.CHALLENGE_KILL_COUNT_GUARD_HP;
import emu.grasscutter.game.dungeons.challenge.WorldChallenge; import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType; import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
import emu.grasscutter.game.dungeons.challenge.trigger.GuardTrigger; import emu.grasscutter.game.dungeons.challenge.trigger.GuardTrigger;
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterCountTrigger; import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterCountTrigger;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import lombok.val;
import java.util.List; import java.util.List;
import lombok.val;
import static emu.grasscutter.game.dungeons.challenge.enums.ChallengeType.CHALLENGE_KILL_COUNT_GUARD_HP;
public class KillAndGuardChallengeFactoryHandler implements ChallengeFactoryHandler { public class KillAndGuardChallengeFactoryHandler implements ChallengeFactoryHandler {
@Override @Override
@ -20,10 +19,19 @@ public class KillAndGuardChallengeFactoryHandler implements ChallengeFactoryHand
} }
@Override /*TODO check param4 == monstesToKill*/ @Override /*TODO check param4 == monstesToKill*/
public WorldChallenge build(int challengeIndex, int challengeId, int groupId, int monstersToKill, int gadgetCFGId, int unused, Scene scene, SceneGroup group) { public WorldChallenge build(
int challengeIndex,
int challengeId,
int groupId,
int monstersToKill,
int gadgetCFGId,
int unused,
Scene scene,
SceneGroup group) {
val realGroup = scene.getScriptManager().getGroupById(groupId); val realGroup = scene.getScriptManager().getGroupById(groupId);
return new WorldChallenge( return new WorldChallenge(
scene, realGroup, scene,
realGroup,
challengeId, // Id challengeId, // Id
challengeIndex, // Index challengeIndex, // Index
List.of(monstersToKill, 0), List.of(monstersToKill, 0),

View File

@ -5,9 +5,8 @@ import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterCountTrigger; import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterCountTrigger;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import lombok.val;
import java.util.List; import java.util.List;
import lombok.val;
public class KillMonsterCountChallengeFactoryHandler implements ChallengeFactoryHandler { public class KillMonsterCountChallengeFactoryHandler implements ChallengeFactoryHandler {
@Override @Override
@ -17,16 +16,24 @@ public class KillMonsterCountChallengeFactoryHandler implements ChallengeFactory
} }
@Override @Override
public WorldChallenge build(int challengeIndex, int challengeId, int groupId, int goal, int param5, int param6, Scene scene, SceneGroup group) { public WorldChallenge build(
int challengeIndex,
int challengeId,
int groupId,
int goal,
int param5,
int param6,
Scene scene,
SceneGroup group) {
val realGroup = scene.getScriptManager().getGroupById(groupId); val realGroup = scene.getScriptManager().getGroupById(groupId);
return new WorldChallenge( return new WorldChallenge(
scene, realGroup, scene,
realGroup,
challengeId, // Id challengeId, // Id
challengeIndex, // Index challengeIndex, // Index
List.of(goal, groupId), List.of(goal, groupId),
0, // Limit 0, // Limit
goal, // Goal goal, // Goal
List.of(new KillMonsterCountTrigger()) List.of(new KillMonsterCountTrigger()));
);
} }
} }

View File

@ -6,9 +6,8 @@ import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger;
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger; import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import lombok.val;
import java.util.List; import java.util.List;
import lombok.val;
public class KillMonsterInTimeChallengeFactoryHandler implements ChallengeFactoryHandler { public class KillMonsterInTimeChallengeFactoryHandler implements ChallengeFactoryHandler {
@Override @Override
@ -18,16 +17,24 @@ public class KillMonsterInTimeChallengeFactoryHandler implements ChallengeFactor
} }
@Override @Override
public WorldChallenge build(int challengeIndex, int challengeId, int timeLimit, int groupId, int targetCfgId, int param6, Scene scene, SceneGroup group) { public WorldChallenge build(
int challengeIndex,
int challengeId,
int timeLimit,
int groupId,
int targetCfgId,
int param6,
Scene scene,
SceneGroup group) {
val realGroup = scene.getScriptManager().getGroupById(groupId); val realGroup = scene.getScriptManager().getGroupById(groupId);
return new WorldChallenge( return new WorldChallenge(
scene, realGroup, scene,
realGroup,
challengeId, // Id challengeId, // Id
challengeIndex, // Index challengeIndex, // Index
List.of(timeLimit), List.of(timeLimit),
timeLimit, // Limit timeLimit, // Limit
0, // Goal 0, // Goal
List.of(new KillMonsterTrigger(targetCfgId), new InTimeTrigger()) List.of(new KillMonsterTrigger(targetCfgId), new InTimeTrigger()));
);
} }
} }

View File

@ -6,30 +6,37 @@ import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger;
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterCountTrigger; import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterCountTrigger;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import lombok.val;
import java.util.List; import java.util.List;
import lombok.val;
public class KillMonsterTimeChallengeFactoryHandler implements ChallengeFactoryHandler { public class KillMonsterTimeChallengeFactoryHandler implements ChallengeFactoryHandler {
@Override @Override
public boolean isThisType(ChallengeType challengeType) { public boolean isThisType(ChallengeType challengeType) {
// ActiveChallenge with 180,180,45,133108061,1,0 // ActiveChallenge with 180,180,45,133108061,1,0
// ActiveChallenge Fast with 1001, 5, 15, 240004005, 10, 0 // ActiveChallenge Fast with 1001, 5, 15, 240004005, 10, 0
return challengeType == ChallengeType.CHALLENGE_KILL_COUNT_IN_TIME || return challengeType == ChallengeType.CHALLENGE_KILL_COUNT_IN_TIME
challengeType == ChallengeType.CHALLENGE_KILL_COUNT_FAST; || challengeType == ChallengeType.CHALLENGE_KILL_COUNT_FAST;
} }
@Override @Override
public WorldChallenge build(int challengeIndex, int challengeId, int timeLimit, int groupId, int targetCount, int param6, Scene scene, SceneGroup group) { public WorldChallenge build(
int challengeIndex,
int challengeId,
int timeLimit,
int groupId,
int targetCount,
int param6,
Scene scene,
SceneGroup group) {
val realGroup = scene.getScriptManager().getGroupById(groupId); val realGroup = scene.getScriptManager().getGroupById(groupId);
return new WorldChallenge( return new WorldChallenge(
scene, realGroup, scene,
realGroup,
challengeId, // Id challengeId, // Id
challengeIndex, // Index challengeIndex, // Index
List.of(targetCount, timeLimit), List.of(targetCount, timeLimit),
timeLimit, // Limit timeLimit, // Limit
targetCount, // Goal targetCount, // Goal
List.of(new KillMonsterCountTrigger(), new InTimeTrigger()) List.of(new KillMonsterCountTrigger(), new InTimeTrigger()));
);
} }
} }

View File

@ -1,15 +1,14 @@
package emu.grasscutter.game.dungeons.challenge.factory; package emu.grasscutter.game.dungeons.challenge.factory;
import static emu.grasscutter.game.dungeons.challenge.enums.ChallengeType.CHALLENGE_SURVIVE;
import emu.grasscutter.game.dungeons.challenge.WorldChallenge; import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType; import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
import emu.grasscutter.game.dungeons.challenge.trigger.ForTimeTrigger; import emu.grasscutter.game.dungeons.challenge.trigger.ForTimeTrigger;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import java.util.List; import java.util.List;
import static emu.grasscutter.game.dungeons.challenge.enums.ChallengeType.CHALLENGE_SURVIVE;
public class SurviveChallengeFactoryHandler implements ChallengeFactoryHandler { public class SurviveChallengeFactoryHandler implements ChallengeFactoryHandler {
@Override @Override
public boolean isThisType(ChallengeType challengeType) { public boolean isThisType(ChallengeType challengeType) {
@ -19,15 +18,23 @@ public class SurviveChallengeFactoryHandler implements ChallengeFactoryHandler {
} }
@Override @Override
public WorldChallenge build(int challengeIndex, int challengeId, int timeToSurvive, int unused4, int unused5, int unused6, Scene scene, SceneGroup group) { public WorldChallenge build(
int challengeIndex,
int challengeId,
int timeToSurvive,
int unused4,
int unused5,
int unused6,
Scene scene,
SceneGroup group) {
return new WorldChallenge( return new WorldChallenge(
scene, group, scene,
group,
challengeId, // Id challengeId, // Id
challengeIndex, // Index challengeIndex, // Index
List.of(timeToSurvive), List.of(timeToSurvive),
timeToSurvive, // Limit timeToSurvive, // Limit
0, // Goal 0, // Goal
List.of(new ForTimeTrigger()) List.of(new ForTimeTrigger()));
);
} }
} }

View File

@ -1,16 +1,15 @@
package emu.grasscutter.game.dungeons.challenge.factory; package emu.grasscutter.game.dungeons.challenge.factory;
import static emu.grasscutter.game.dungeons.challenge.enums.ChallengeType.CHALLENGE_TRIGGER_IN_TIME;
import emu.grasscutter.game.dungeons.challenge.WorldChallenge; import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType; import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger; import emu.grasscutter.game.dungeons.challenge.trigger.InTimeTrigger;
import emu.grasscutter.game.dungeons.challenge.trigger.TriggerGroupTriggerTrigger; import emu.grasscutter.game.dungeons.challenge.trigger.TriggerGroupTriggerTrigger;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import java.util.List; import java.util.List;
import static emu.grasscutter.game.dungeons.challenge.enums.ChallengeType.CHALLENGE_TRIGGER_IN_TIME;
public class TriggerInTimeChallengeFactoryHandler implements ChallengeFactoryHandler { public class TriggerInTimeChallengeFactoryHandler implements ChallengeFactoryHandler {
@Override @Override
public boolean isThisType(ChallengeType challengeType) { public boolean isThisType(ChallengeType challengeType) {
@ -22,15 +21,23 @@ public class TriggerInTimeChallengeFactoryHandler implements ChallengeFactoryHan
} }
@Override @Override
public WorldChallenge build(int challengeIndex, int challengeId, int timeLimit, int param4, int triggerTag, int triggerCount, Scene scene, SceneGroup group) { public WorldChallenge build(
int challengeIndex,
int challengeId,
int timeLimit,
int param4,
int triggerTag,
int triggerCount,
Scene scene,
SceneGroup group) {
return new WorldChallenge( return new WorldChallenge(
scene, group, scene,
group,
challengeId, // Id challengeId, // Id
challengeIndex, // Index challengeIndex, // Index
List.of(timeLimit, triggerCount), List.of(timeLimit, triggerCount),
timeLimit, // Limit timeLimit, // Limit
triggerCount, // Goal triggerCount, // Goal
List.of(new InTimeTrigger(), new TriggerGroupTriggerTrigger(Integer.toString(triggerTag))) List.of(new InTimeTrigger(), new TriggerGroupTriggerTrigger(Integer.toString(triggerTag))));
);
} }
} }

View File

@ -7,10 +7,16 @@ import emu.grasscutter.scripts.data.SceneTrigger;
public abstract class ChallengeTrigger { public abstract class ChallengeTrigger {
public void onBegin(WorldChallenge challenge) {} public void onBegin(WorldChallenge challenge) {}
public void onFinish(WorldChallenge challenge) {} public void onFinish(WorldChallenge challenge) {}
public void onMonsterDeath(WorldChallenge challenge, EntityMonster monster) {} public void onMonsterDeath(WorldChallenge challenge, EntityMonster monster) {}
public void onGadgetDeath(WorldChallenge challenge, EntityGadget gadget) {} public void onGadgetDeath(WorldChallenge challenge, EntityGadget gadget) {}
public void onCheckTimeout(WorldChallenge challenge) {} public void onCheckTimeout(WorldChallenge challenge) {}
public void onGadgetDamage(WorldChallenge challenge, EntityGadget gadget) {} public void onGadgetDamage(WorldChallenge challenge, EntityGadget gadget) {}
public void onGroupTrigger(WorldChallenge challenge, SceneTrigger trigger) {} public void onGroupTrigger(WorldChallenge challenge, SceneTrigger trigger) {}
} }

View File

@ -2,13 +2,13 @@ package emu.grasscutter.game.dungeons.challenge.trigger;
import emu.grasscutter.game.dungeons.challenge.WorldChallenge; import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.server.packet.send.PacketChallengeDataNotify; import emu.grasscutter.server.packet.send.PacketChallengeDataNotify;
public class GuardTrigger extends ChallengeTrigger { public class GuardTrigger extends ChallengeTrigger {
private final int entityToProtectCFGId; private final int entityToProtectCFGId;
private int lastSendPercent = 100; private int lastSendPercent = 100;
public GuardTrigger(int entityToProtectCFGId) { public GuardTrigger(int entityToProtectCFGId) {
this.entityToProtectCFGId = entityToProtectCFGId; this.entityToProtectCFGId = entityToProtectCFGId;
} }

View File

@ -8,9 +8,12 @@ import lombok.AllArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
public class KillMonsterTrigger extends ChallengeTrigger { public class KillMonsterTrigger extends ChallengeTrigger {
private int monsterCfgId; private int monsterCfgId;
@Override @Override
public void onBegin(WorldChallenge challenge) { public void onBegin(WorldChallenge challenge) {
challenge.getScene().broadcastPacket(new PacketChallengeDataNotify(challenge, 1, challenge.getScore().get())); challenge
.getScene()
.broadcastPacket(new PacketChallengeDataNotify(challenge, 1, challenge.getScore().get()));
} }
@Override @Override

View File

@ -37,19 +37,21 @@ import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper; import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatMap; import it.unimi.dsi.fastutil.ints.Int2FloatMap;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
@ToString(callSuper = true) @ToString(callSuper = true)
public class EntityGadget extends EntityBaseGadget { public class EntityGadget extends EntityBaseGadget {
@Getter private final GadgetData gadgetData; @Getter private final GadgetData gadgetData;
@Getter(onMethod = @__(@Override)) @Setter
@Getter(onMethod = @__(@Override))
@Setter
private int gadgetId; private int gadgetId;
@Getter private final Position bornPos; @Getter private final Position bornPos;
@Getter private final Position bornRot; @Getter private final Position bornRot;
@Getter @Setter private GameEntity owner = null; @Getter @Setter private GameEntity owner = null;
@ -58,18 +60,18 @@ public class EntityGadget extends EntityBaseGadget {
@Getter private int state; @Getter private int state;
@Getter @Setter private int pointType; @Getter @Setter private int pointType;
@Getter private GadgetContent content; @Getter private GadgetContent content;
@Getter(onMethod = @__(@Override), lazy = true) @Getter(onMethod = @__(@Override), lazy = true)
private final Int2FloatMap fightProperties = new Int2FloatOpenHashMap(); private final Int2FloatMap fightProperties = new Int2FloatOpenHashMap();
@Getter @Setter private SceneGadget metaGadget; @Getter @Setter private SceneGadget metaGadget;
@Nullable @Getter @Nullable @Getter private ConfigEntityGadget configGadget;
private ConfigEntityGadget configGadget;
@Getter @Setter private BaseRoute routeConfig; @Getter @Setter private BaseRoute routeConfig;
@Getter @Setter private int stopValue = 0; // Controller related, inited to zero @Getter @Setter private int stopValue = 0; // Controller related, inited to zero
@Getter @Setter private int startValue = 0; // Controller related, inited to zero @Getter @Setter private int startValue = 0; // Controller related, inited to zero
@Getter @Setter private int ticksSinceChange; @Getter @Setter private int ticksSinceChange;
public EntityGadget(Scene scene, int gadgetId, Position pos) { public EntityGadget(Scene scene, int gadgetId, Position pos) {
this(scene, gadgetId, pos, null, null); this(scene, gadgetId, pos, null, null);
} }
@ -78,7 +80,8 @@ public class EntityGadget extends EntityBaseGadget {
this(scene, gadgetId, pos, rot, null); this(scene, gadgetId, pos, rot, null);
} }
public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot, GadgetContent content) { public EntityGadget(
Scene scene, int gadgetId, Position pos, Position rot, GadgetContent content) {
super(scene, pos, rot); super(scene, pos, rot);
this.gadgetData = GameData.getGadgetDataMap().get(gadgetId); this.gadgetData = GameData.getGadgetDataMap().get(gadgetId);
@ -114,7 +117,11 @@ public class EntityGadget extends EntityBaseGadget {
this.setState(state); this.setState(state);
ticksSinceChange = getScene().getSceneTimeSeconds(); ticksSinceChange = getScene().getSceneTimeSeconds();
this.getScene().broadcastPacket(new PacketGadgetStateNotify(this, state)); this.getScene().broadcastPacket(new PacketGadgetStateNotify(this, state));
getScene().getScriptManager().callEvent(new ScriptArgs(this.getGroupId(), EventType.EVENT_GADGET_STATE_CHANGE, state, this.getConfigId())); getScene()
.getScriptManager()
.callEvent(
new ScriptArgs(
this.getGroupId(), EventType.EVENT_GADGET_STATE_CHANGE, state, this.getConfigId()));
} }
@Deprecated(forRemoval = true) // Dont use! @Deprecated(forRemoval = true) // Dont use!
@ -124,11 +131,14 @@ public class EntityGadget extends EntityBaseGadget {
// TODO refactor // TODO refactor
public void buildContent() { public void buildContent() {
if (this.getContent() != null || this.getGadgetData() == null || this.getGadgetData().getType() == null) { if (this.getContent() != null
|| this.getGadgetData() == null
|| this.getGadgetData().getType() == null) {
return; return;
} }
this.content = switch (this.getGadgetData().getType()) { this.content =
switch (this.getGadgetData().getType()) {
case GatherPoint -> new GadgetGatherPoint(this); case GatherPoint -> new GadgetGatherPoint(this);
case GatherObject -> new GadgetGatherObject(this); case GatherObject -> new GadgetGatherObject(this);
case Worktop, SealGadget -> new GadgetWorktop(this); case Worktop, SealGadget -> new GadgetWorktop(this);
@ -155,7 +165,10 @@ public class EntityGadget extends EntityBaseGadget {
@Override @Override
public void onCreate() { public void onCreate() {
// Lua event // Lua event
getScene().getScriptManager().callEvent(new ScriptArgs(this.getGroupId(), EventType.EVENT_GADGET_CREATE, this.getConfigId())); getScene()
.getScriptManager()
.callEvent(
new ScriptArgs(this.getGroupId(), EventType.EVENT_GADGET_CREATE, this.getConfigId()));
} }
@Override @Override
@ -177,9 +190,13 @@ public class EntityGadget extends EntityBaseGadget {
if (getScene().getChallenge() != null) { if (getScene().getChallenge() != null) {
getScene().getChallenge().onGadgetDeath(this); getScene().getChallenge().onGadgetDeath(this);
} }
getScene().getScriptManager().callEvent(new ScriptArgs(this.getGroupId(), EventType.EVENT_ANY_GADGET_DIE, this.getConfigId())); getScene()
.getScriptManager()
.callEvent(
new ScriptArgs(this.getGroupId(), EventType.EVENT_ANY_GADGET_DIE, this.getConfigId()));
SceneGroupInstance groupInstance = getScene().getScriptManager().getCachedGroupInstanceById(this.getGroupId()); SceneGroupInstance groupInstance =
getScene().getScriptManager().getCachedGroupInstanceById(this.getGroupId());
if (groupInstance != null && metaGadget != null) if (groupInstance != null && metaGadget != null)
groupInstance.getDeadEntities().add(metaGadget.config_id); groupInstance.getDeadEntities().add(metaGadget.config_id);
} }
@ -215,34 +232,44 @@ public class EntityGadget extends EntityBaseGadget {
@Override @Override
public SceneEntityInfo toProto() { public SceneEntityInfo toProto() {
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder() EntityAuthorityInfo authority =
EntityAuthorityInfo.newBuilder()
.setAbilityInfo(AbilitySyncStateInfo.newBuilder()) .setAbilityInfo(AbilitySyncStateInfo.newBuilder())
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(bornPos.toProto())) .setAiInfo(
SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(bornPos.toProto()))
.setBornPos(bornPos.toProto()) .setBornPos(bornPos.toProto())
.build(); .build();
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() SceneEntityInfo.Builder entityInfo =
SceneEntityInfo.newBuilder()
.setEntityId(getId()) .setEntityId(getId())
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) .setMotionInfo(
MotionInfo.newBuilder()
.setPos(getPosition().toProto())
.setRot(getRotation().toProto())
.setSpeed(Vector.newBuilder()))
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setEntityClientData(EntityClientData.newBuilder()) .setEntityClientData(EntityClientData.newBuilder())
.setEntityAuthorityInfo(authority) .setEntityAuthorityInfo(authority)
.setLifeState(1); .setLifeState(1);
PropPair pair = PropPair.newBuilder() PropPair pair =
PropPair.newBuilder()
.setType(PlayerProperty.PROP_LEVEL.getId()) .setType(PlayerProperty.PROP_LEVEL.getId())
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1)) .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1))
.build(); .build();
entityInfo.addPropList(pair); entityInfo.addPropList(pair);
// We do not use the getter to null check because the getter will create a fight prop map if it is null // We do not use the getter to null check because the getter will create a fight prop map if it
// is null
if (this.fightProperties != null) { if (this.fightProperties != null) {
addAllFightPropsToEntityInfo(entityInfo); addAllFightPropsToEntityInfo(entityInfo);
} }
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder() SceneGadgetInfo.Builder gadgetInfo =
SceneGadgetInfo.newBuilder()
.setGadgetId(this.getGadgetId()) .setGadgetId(this.getGadgetId())
.setGroupId(this.getGroupId()) .setGroupId(this.getGroupId())
.setConfigId(this.getConfigId()) .setConfigId(this.getConfigId())

View File

@ -11,14 +11,17 @@ public class EntitySolarIsotomaClientGadget extends EntityClientGadget {
public static final int ELEVATOR_GADGET_ID = 41038002; public static final int ELEVATOR_GADGET_ID = 41038002;
@Getter private EntityGadget platformGadget; @Getter private EntityGadget platformGadget;
public EntitySolarIsotomaClientGadget(Scene scene, Player player, EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify notify) { public EntitySolarIsotomaClientGadget(
Scene scene, Player player, EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify notify) {
super(scene, player, notify); super(scene, player, notify);
} }
@Override @Override
public void onCreate() { public void onCreate() {
// Create solar isotoma elevator and send to all. // Create solar isotoma elevator and send to all.
this.platformGadget = new EntitySolarIsotomaElevatorPlatform(this, getScene(), ELEVATOR_GADGET_ID, getPosition(), getRotation()); this.platformGadget =
new EntitySolarIsotomaElevatorPlatform(
this, getScene(), ELEVATOR_GADGET_ID, getPosition(), getRotation());
getScene().addEntity(this.platformGadget); getScene().addEntity(this.platformGadget);
} }

View File

@ -25,16 +25,16 @@ import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper; import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatMap; import it.unimi.dsi.fastutil.ints.Int2FloatMap;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
import lombok.Getter;
import lombok.Setter;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import lombok.Getter;
import lombok.Setter;
public class EntityVehicle extends EntityBaseGadget { public class EntityVehicle extends EntityBaseGadget {
@Getter private final Player owner; @Getter private final Player owner;
@Getter(onMethod = @__(@Override)) @Getter(onMethod = @__(@Override))
private final Int2FloatMap fightProperties; private final Int2FloatMap fightProperties;
@ -45,7 +45,8 @@ public class EntityVehicle extends EntityBaseGadget {
@Getter private final List<VehicleMember> vehicleMembers; @Getter private final List<VehicleMember> vehicleMembers;
@Nullable @Getter private ConfigEntityGadget configGadget; @Nullable @Getter private ConfigEntityGadget configGadget;
public EntityVehicle(Scene scene, Player player, int gadgetId, int pointId, Position pos, Position rot) { public EntityVehicle(
Scene scene, Player player, int gadgetId, int pointId, Position pos, Position rot) {
super(scene, pos, rot); super(scene, pos, rot);
this.owner = player; this.owner = player;
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET); this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
@ -72,34 +73,46 @@ public class EntityVehicle extends EntityBaseGadget {
@Override @Override
public SceneEntityInfo toProto() { public SceneEntityInfo toProto() {
VehicleInfo vehicle = VehicleInfo.newBuilder() VehicleInfo vehicle =
VehicleInfo.newBuilder()
.setOwnerUid(this.owner.getUid()) .setOwnerUid(this.owner.getUid())
.setCurStamina(getCurStamina()) .setCurStamina(getCurStamina())
.build(); .build();
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder() EntityAuthorityInfo authority =
EntityAuthorityInfo.newBuilder()
.setAbilityInfo(AbilitySyncStateInfo.newBuilder()) .setAbilityInfo(AbilitySyncStateInfo.newBuilder())
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder()) .setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(getPosition().toProto())) .setAiInfo(
SceneEntityAiInfo.newBuilder()
.setIsAiOpen(true)
.setBornPos(getPosition().toProto()))
.setBornPos(getPosition().toProto()) .setBornPos(getPosition().toProto())
.build(); .build();
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder() SceneGadgetInfo.Builder gadgetInfo =
SceneGadgetInfo.newBuilder()
.setGadgetId(this.getGadgetId()) .setGadgetId(this.getGadgetId())
.setAuthorityPeerId(this.getOwner().getPeerId()) .setAuthorityPeerId(this.getOwner().getPeerId())
.setIsEnableInteract(true) .setIsEnableInteract(true)
.setVehicleInfo(vehicle); .setVehicleInfo(vehicle);
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder() SceneEntityInfo.Builder entityInfo =
SceneEntityInfo.newBuilder()
.setEntityId(getId()) .setEntityId(getId())
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET) .setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder())) .setMotionInfo(
MotionInfo.newBuilder()
.setPos(getPosition().toProto())
.setRot(getRotation().toProto())
.setSpeed(Vector.newBuilder()))
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder()) .addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
.setGadget(gadgetInfo) .setGadget(gadgetInfo)
.setEntityAuthorityInfo(authority) .setEntityAuthorityInfo(authority)
.setLifeState(1); .setLifeState(1);
PropPair pair = PropPair.newBuilder() PropPair pair =
PropPair.newBuilder()
.setType(PlayerProperty.PROP_LEVEL.getId()) .setType(PlayerProperty.PROP_LEVEL.getId())
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 47)) .setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 47))
.build(); .build();

View File

@ -19,7 +19,8 @@ public final class GadgetRewardStatue extends GadgetContent {
var dungeonManager = player.getScene().getDungeonManager(); var dungeonManager = player.getScene().getDungeonManager();
if (player.getScene().getChallenge() instanceof DungeonChallenge) { if (player.getScene().getChallenge() instanceof DungeonChallenge) {
var useCondensed = req.getResinCostType() == ResinCostTypeOuterClass.ResinCostType.RESIN_COST_TYPE_CONDENSE; var useCondensed =
req.getResinCostType() == ResinCostTypeOuterClass.ResinCostType.RESIN_COST_TYPE_CONDENSE;
dungeonManager.getStatueDrops(player, useCondensed, getGadget().getGroupId()); dungeonManager.getStatueDrops(player, useCondensed, getGadget().getGroupId());
} }

View File

@ -9,7 +9,12 @@ import emu.grasscutter.game.world.Scene;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
public class EntitySolarIsotomaElevatorPlatform extends EntityGadget { public class EntitySolarIsotomaElevatorPlatform extends EntityGadget {
public EntitySolarIsotomaElevatorPlatform(EntitySolarIsotomaClientGadget isotoma, Scene scene, int gadgetId, Position pos, Position rot) { public EntitySolarIsotomaElevatorPlatform(
EntitySolarIsotomaClientGadget isotoma,
Scene scene,
int gadgetId,
Position pos,
Position rot) {
super(scene, gadgetId, pos, rot); super(scene, gadgetId, pos, rot);
setOwner(isotoma); setOwner(isotoma);
this.setRouteConfig(new AbilityRoute(rot, false, false, pos)); this.setRouteConfig(new AbilityRoute(rot, false, false, pos));

View File

@ -1,5 +1,7 @@
package emu.grasscutter.game.mail; package emu.grasscutter.game.mail;
import static emu.grasscutter.net.proto.MailItemOuterClass.MailItem.*;
import dev.morphia.annotations.Entity; import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id; import dev.morphia.annotations.Id;
import dev.morphia.annotations.Indexed; import dev.morphia.annotations.Indexed;
@ -10,13 +12,10 @@ import emu.grasscutter.net.proto.*;
import emu.grasscutter.net.proto.EquipParamOuterClass.EquipParam; import emu.grasscutter.net.proto.EquipParamOuterClass.EquipParam;
import emu.grasscutter.net.proto.MailCollectStateOuterClass.MailCollectState; import emu.grasscutter.net.proto.MailCollectStateOuterClass.MailCollectState;
import emu.grasscutter.net.proto.MailTextContentOuterClass.MailTextContent; import emu.grasscutter.net.proto.MailTextContentOuterClass.MailTextContent;
import org.bson.types.ObjectId;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.bson.types.ObjectId;
import static emu.grasscutter.net.proto.MailItemOuterClass.MailItem.*;
@Entity(value = "mail", useDiscriminator = false) @Entity(value = "mail", useDiscriminator = false)
public final class Mail { public final class Mail {
@ -33,7 +32,11 @@ public final class Mail {
@Transient private boolean shouldDelete; @Transient private boolean shouldDelete;
public Mail() { public Mail() {
this(new MailContent(), new ArrayList<MailItem>(), (int) Instant.now().getEpochSecond() + 604800); // TODO: add expire time to send mail command this(
new MailContent(),
new ArrayList<MailItem>(),
(int) Instant.now().getEpochSecond()
+ 604800); // TODO: add expire time to send mail command
} }
public Mail(MailContent mailContent, List<MailItem> itemList, long expireTime) { public Mail(MailContent mailContent, List<MailItem> itemList, long expireTime) {
@ -44,7 +47,12 @@ public final class Mail {
this(mailContent, itemList, expireTime, importance, 1); this(mailContent, itemList, expireTime, importance, 1);
} }
public Mail(MailContent mailContent, List<MailItem> itemList, long expireTime, int importance, int state) { public Mail(
MailContent mailContent,
List<MailItem> itemList,
long expireTime,
int importance,
int state) {
this.mailContent = mailContent; this.mailContent = mailContent;
this.itemList = itemList; this.itemList = itemList;
this.sendTime = (int) Instant.now().getEpochSecond(); this.sendTime = (int) Instant.now().getEpochSecond();
@ -143,7 +151,9 @@ public final class Mail {
} }
public MailItemOuterClass.MailItem toProto() { public MailItemOuterClass.MailItem toProto() {
return newBuilder().setEquipParam(EquipParam.newBuilder() return newBuilder()
.setEquipParam(
EquipParam.newBuilder()
.setItemId(this.itemId) .setItemId(this.itemId)
.setItemNum(this.itemCount) .setItemNum(this.itemCount)
.setItemLevel(this.itemLevel) .setItemLevel(this.itemLevel)

View File

@ -13,7 +13,6 @@ import emu.grasscutter.scripts.data.SceneGadget;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -33,7 +32,9 @@ public final class BlossomActivity {
private final List<EntityMonster> activeMonsters = new ArrayList<>(); private final List<EntityMonster> activeMonsters = new ArrayList<>();
private final Queue<Integer> candidateMonsters = new ArrayDeque<>(); private final Queue<Integer> candidateMonsters = new ArrayDeque<>();
private static final int BLOOMING_GADGET_ID = 70210109; private static final int BLOOMING_GADGET_ID = 70210109;
public BlossomActivity(EntityGadget entityGadget, List<Integer> monsters, int timeout, int worldLevel) {
public BlossomActivity(
EntityGadget entityGadget, List<Integer> monsters, int timeout, int worldLevel) {
this.tempSceneGroup = new SceneGroup(); this.tempSceneGroup = new SceneGroup();
this.tempSceneGroup.id = entityGadget.getId(); this.tempSceneGroup.id = entityGadget.getId();
this.gadget = entityGadget; this.gadget = entityGadget;
@ -42,19 +43,24 @@ public final class BlossomActivity {
this.candidateMonsters.addAll(monsters); this.candidateMonsters.addAll(monsters);
this.worldLevel = worldLevel; this.worldLevel = worldLevel;
ArrayList<ChallengeTrigger> challengeTriggers = new ArrayList<>(); ArrayList<ChallengeTrigger> challengeTriggers = new ArrayList<>();
this.challenge = new WorldChallenge(entityGadget.getScene(), this.challenge =
new WorldChallenge(
entityGadget.getScene(),
tempSceneGroup, tempSceneGroup,
1, 1,
1, 1,
List.of(goal, timeout), List.of(goal, timeout),
timeout, timeout,
goal, challengeTriggers); goal,
challengeTriggers);
challengeTriggers.add(new KillMonsterCountTrigger()); challengeTriggers.add(new KillMonsterCountTrigger());
// this.challengeTriggers.add(new InTimeTrigger()); // this.challengeTriggers.add(new InTimeTrigger());
} }
public WorldChallenge getChallenge() { public WorldChallenge getChallenge() {
return this.challenge; return this.challenge;
} }
public void setMonsters(List<EntityMonster> monsters) { public void setMonsters(List<EntityMonster> monsters) {
this.activeMonsters.clear(); this.activeMonsters.clear();
this.activeMonsters.addAll(monsters); this.activeMonsters.addAll(monsters);
@ -62,6 +68,7 @@ public final class BlossomActivity {
monster.setGroupId(this.tempSceneGroup.id); monster.setGroupId(this.tempSceneGroup.id);
} }
} }
public int getAliveMonstersCount() { public int getAliveMonstersCount() {
int count = 0; int count = 0;
for (EntityMonster monster : activeMonsters) { for (EntityMonster monster : activeMonsters) {
@ -71,12 +78,15 @@ public final class BlossomActivity {
} }
return count; return count;
} }
public boolean getPass() { public boolean getPass() {
return pass; return pass;
} }
public void start() { public void start() {
challenge.start(); challenge.start();
} }
public void onTick() { public void onTick() {
Scene scene = gadget.getScene(); Scene scene = gadget.getScene();
Position pos = gadget.getPosition(); Position pos = gadget.getPosition();
@ -112,12 +122,15 @@ public final class BlossomActivity {
} }
} }
} }
public EntityGadget getGadget() { public EntityGadget getGadget() {
return gadget; return gadget;
} }
public EntityGadget getChest() { public EntityGadget getChest() {
if (chest == null) { if (chest == null) {
EntityGadget rewardGadget = new EntityGadget(gadget.getScene(), BLOOMING_GADGET_ID, gadget.getPosition()); EntityGadget rewardGadget =
new EntityGadget(gadget.getScene(), BLOOMING_GADGET_ID, gadget.getPosition());
SceneGadget metaGadget = new SceneGadget(); SceneGadget metaGadget = new SceneGadget();
metaGadget.boss_chest = new SceneBossChest(); metaGadget.boss_chest = new SceneBossChest();
metaGadget.boss_chest.resin = 20; metaGadget.boss_chest.resin = 20;

View File

@ -30,11 +30,10 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.Getter;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import lombok.Getter;
public class EnergyManager extends BasePlayerManager { public class EnergyManager extends BasePlayerManager {
private static final Int2ObjectMap<List<EnergyDropInfo>> energyDropData = private static final Int2ObjectMap<List<EnergyDropInfo>> energyDropData =
@ -390,7 +389,8 @@ public class EnergyManager extends BasePlayerManager {
*/ */
public boolean refillActiveEnergy() { public boolean refillActiveEnergy() {
var activeEntity = this.player.getTeamManager().getCurrentAvatarEntity(); var activeEntity = this.player.getTeamManager().getCurrentAvatarEntity();
return activeEntity.addEnergy(activeEntity.getAvatar().getSkillDepot().getEnergySkillData().getCostElemVal()); return activeEntity.addEnergy(
activeEntity.getAvatar().getSkillDepot().getEnergySkillData().getCostElemVal());
} }
/** /**
@ -402,8 +402,10 @@ public class EnergyManager extends BasePlayerManager {
public void refillTeamEnergy(PropChangeReason changeReason, boolean isFlat) { public void refillTeamEnergy(PropChangeReason changeReason, boolean isFlat) {
for (var entityAvatar : this.player.getTeamManager().getActiveTeam()) { for (var entityAvatar : this.player.getTeamManager().getActiveTeam()) {
// giving the exact amount read off the AvatarSkillData.json // giving the exact amount read off the AvatarSkillData.json
entityAvatar.addEnergy(entityAvatar.getAvatar().getSkillDepot() entityAvatar.addEnergy(
.getEnergySkillData().getCostElemVal(), changeReason, isFlat); entityAvatar.getAvatar().getSkillDepot().getEnergySkillData().getCostElemVal(),
changeReason,
isFlat);
} }
} }

View File

@ -10,8 +10,6 @@ import emu.grasscutter.game.quest.enums.QuestContent;
import emu.grasscutter.game.quest.enums.QuestState; import emu.grasscutter.game.quest.enums.QuestState;
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
import emu.grasscutter.server.packet.send.*; import emu.grasscutter.server.packet.send.*;
import lombok.val;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -149,9 +147,7 @@ public final class PlayerProgressManager extends BasePlayerDataManager {
this.player.sendPacket(new PacketSetOpenStateRsp(openState, value)); this.player.sendPacket(new PacketSetOpenStateRsp(openState, value));
} }
/** /** This force sets an open state, ignoring all conditions and permissions */
* This force sets an open state, ignoring all conditions and permissions
*/
public void forceSetOpenState(int openState, int value) { public void forceSetOpenState(int openState, int value) {
this.setOpenState(openState, value); this.setOpenState(openState, value);
} }
@ -247,31 +243,31 @@ public final class PlayerProgressManager extends BasePlayerDataManager {
this.player.sendPacket(new PacketSceneAreaUnlockNotify(sceneId, areaId)); this.player.sendPacket(new PacketSceneAreaUnlockNotify(sceneId, areaId));
} }
/** /** Give replace costume to player (Amber, Jean, Mona, Rosaria) */
* Give replace costume to player (Amber, Jean, Mona, Rosaria)
*/
public void addReplaceCostumes() { public void addReplaceCostumes() {
var currentPlayerCostumes = player.getCostumeList(); var currentPlayerCostumes = player.getCostumeList();
GameData.getAvatarReplaceCostumeDataMap().keySet().forEach(costumeId -> { GameData.getAvatarReplaceCostumeDataMap()
if (GameData.getAvatarCostumeDataMap().get(costumeId) == null || currentPlayerCostumes.contains(costumeId)){ .keySet()
.forEach(
costumeId -> {
if (GameData.getAvatarCostumeDataMap().get(costumeId) == null
|| currentPlayerCostumes.contains(costumeId)) {
return; return;
} }
this.player.addCostume(costumeId); this.player.addCostume(costumeId);
}); });
} }
/** /** Quest progress */
* Quest progress
*/
public void addQuestProgress(int id, int count) { public void addQuestProgress(int id, int count) {
var newCount = player.getPlayerProgress().addToCurrentProgress(id, count); var newCount = player.getPlayerProgress().addToCurrentProgress(id, count);
player.save(); player.save();
player.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_ADD_QUEST_PROGRESS, id, newCount); player
.getQuestManager()
.queueEvent(QuestContent.QUEST_CONTENT_ADD_QUEST_PROGRESS, id, newCount);
} }
/** /** Item history */
* Item history
*/
public void addItemObtainedHistory(int id, int count) { public void addItemObtainedHistory(int id, int count) {
var newCount = player.getPlayerProgress().addToItemHistory(id, count); var newCount = player.getPlayerProgress().addToItemHistory(id, count);
player.save(); player.save();

View File

@ -659,11 +659,13 @@ public final class TeamManager extends BasePlayerDataManager {
} }
/** /**
* Applies 10% of the avatar's max HP as damage. * Applies 10% of the avatar's max HP as damage. This occurs when the avatar is killed by the
* This occurs when the avatar is killed by the void. * void.
*/ */
public void applyVoidDamage() { public void applyVoidDamage() {
this.getActiveTeam().forEach(entity -> { this.getActiveTeam()
.forEach(
entity -> {
entity.damage(entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * .1f); entity.damage(entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) * .1f);
player.sendPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); player.sendPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar()));
}); });

View File

@ -1,34 +1,82 @@
package emu.grasscutter.game.props; package emu.grasscutter.game.props;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import emu.grasscutter.scripts.constants.IntValueEnum; import emu.grasscutter.scripts.constants.IntValueEnum;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import lombok.Getter; import lombok.Getter;
public enum ElementType implements IntValueEnum { public enum ElementType implements IntValueEnum {
None(0, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), None(0, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY),
Fire (1, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10101, "TeamResonance_Fire_Lv2", 1), Fire(
Water (2, FightProperty.FIGHT_PROP_CUR_WATER_ENERGY, FightProperty.FIGHT_PROP_MAX_WATER_ENERGY, 10201, "TeamResonance_Water_Lv2", 2), 1,
Grass (3, FightProperty.FIGHT_PROP_CUR_GRASS_ENERGY, FightProperty.FIGHT_PROP_MAX_GRASS_ENERGY, 10501, "TeamResonance_Grass_Lv2", 7), FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY,
Electric (4, FightProperty.FIGHT_PROP_CUR_ELEC_ENERGY, FightProperty.FIGHT_PROP_MAX_ELEC_ENERGY, 10401, "TeamResonance_Electric_Lv2", 6), FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY,
Ice (5, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY, 10601, "TeamResonance_Ice_Lv2", 4), 10101,
"TeamResonance_Fire_Lv2",
1),
Water(
2,
FightProperty.FIGHT_PROP_CUR_WATER_ENERGY,
FightProperty.FIGHT_PROP_MAX_WATER_ENERGY,
10201,
"TeamResonance_Water_Lv2",
2),
Grass(
3,
FightProperty.FIGHT_PROP_CUR_GRASS_ENERGY,
FightProperty.FIGHT_PROP_MAX_GRASS_ENERGY,
10501,
"TeamResonance_Grass_Lv2",
7),
Electric(
4,
FightProperty.FIGHT_PROP_CUR_ELEC_ENERGY,
FightProperty.FIGHT_PROP_MAX_ELEC_ENERGY,
10401,
"TeamResonance_Electric_Lv2",
6),
Ice(
5,
FightProperty.FIGHT_PROP_CUR_ICE_ENERGY,
FightProperty.FIGHT_PROP_MAX_ICE_ENERGY,
10601,
"TeamResonance_Ice_Lv2",
4),
Frozen(6, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY), Frozen(6, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY),
Wind (7, FightProperty.FIGHT_PROP_CUR_WIND_ENERGY, FightProperty.FIGHT_PROP_MAX_WIND_ENERGY, 10301, "TeamResonance_Wind_Lv2", 3), Wind(
Rock (8, FightProperty.FIGHT_PROP_CUR_ROCK_ENERGY, FightProperty.FIGHT_PROP_MAX_ROCK_ENERGY, 10701, "TeamResonance_Rock_Lv2", 5), 7,
FightProperty.FIGHT_PROP_CUR_WIND_ENERGY,
FightProperty.FIGHT_PROP_MAX_WIND_ENERGY,
10301,
"TeamResonance_Wind_Lv2",
3),
Rock(
8,
FightProperty.FIGHT_PROP_CUR_ROCK_ENERGY,
FightProperty.FIGHT_PROP_MAX_ROCK_ENERGY,
10701,
"TeamResonance_Rock_Lv2",
5),
AntiFire(9, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), AntiFire(9, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY),
Default (255, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10801, "TeamResonance_AllDifferent"); Default(
255,
FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY,
FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY,
10801,
"TeamResonance_AllDifferent");
private static final Int2ObjectMap<ElementType> map = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<ElementType> map = new Int2ObjectOpenHashMap<>();
private static final Map<String, ElementType> stringMap = new HashMap<>(); private static final Map<String, ElementType> stringMap = new HashMap<>();
static { static {
// Create bindings for each value. // Create bindings for each value.
Stream.of(ElementType.values()).forEach(entry -> { Stream.of(ElementType.values())
.forEach(
entry -> {
map.put(entry.getValue(), entry); map.put(entry.getValue(), entry);
stringMap.put(entry.name(), entry); stringMap.put(entry.name(), entry);
}); });
@ -45,11 +93,22 @@ public enum ElementType implements IntValueEnum {
this(value, curEnergyProp, maxEnergyProp, 0, null, 1); this(value, curEnergyProp, maxEnergyProp, 0, null, 1);
} }
ElementType(int value, FightProperty curEnergyProp, FightProperty maxEnergyProp, int teamResonanceId, String configName) { ElementType(
int value,
FightProperty curEnergyProp,
FightProperty maxEnergyProp,
int teamResonanceId,
String configName) {
this(value, curEnergyProp, maxEnergyProp, teamResonanceId, configName, 1); this(value, curEnergyProp, maxEnergyProp, teamResonanceId, configName, 1);
} }
ElementType(int value, FightProperty curEnergyProp, FightProperty maxEnergyProp, int teamResonanceId, String configName, int depotIndex) { ElementType(
int value,
FightProperty curEnergyProp,
FightProperty maxEnergyProp,
int teamResonanceId,
String configName,
int depotIndex) {
this.value = value; this.value = value;
this.curEnergyProp = curEnergyProp; this.curEnergyProp = curEnergyProp;
this.maxEnergyProp = maxEnergyProp; this.maxEnergyProp = maxEnergyProp;

View File

@ -4,7 +4,6 @@ import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.quest.QuestValueCond; import emu.grasscutter.game.quest.QuestValueCond;
import emu.grasscutter.game.quest.enums.QuestCond; import emu.grasscutter.game.quest.enums.QuestCond;
import lombok.val;
@QuestValueCond(QuestCond.QUEST_COND_PERSONAL_LINE_UNLOCK) @QuestValueCond(QuestCond.QUEST_COND_PERSONAL_LINE_UNLOCK)
public class ConditionPersonalLineUnlock extends BaseCondition { public class ConditionPersonalLineUnlock extends BaseCondition {
@ -15,8 +14,7 @@ public class ConditionPersonalLineUnlock extends BaseCondition {
QuestData questData, QuestData questData,
QuestData.QuestAcceptCondition condition, QuestData.QuestAcceptCondition condition,
String paramStr, String paramStr,
int... params int... params) {
) {
var personalLineId = condition.getParam()[0]; var personalLineId = condition.getParam()[0];
return owner.getPersonalLineList().contains(personalLineId); return owner.getPersonalLineList().contains(personalLineId);
} }

View File

@ -437,20 +437,17 @@ public final class Scene {
this.finishLoading(); this.finishLoading();
this.checkPlayerRespawn(); this.checkPlayerRespawn();
if (this.tickCount++ % 10 == 0) if (this.tickCount++ % 10 == 0) broadcastPacket(new PacketSceneTimeNotify(this));
broadcastPacket(new PacketSceneTimeNotify(this));
} }
/** /** Validates a player's current position. Teleports the player if the player is out of bounds. */
* Validates a player's current position.
* Teleports the player if the player is out of bounds.
*/
private void checkPlayerRespawn() { private void checkPlayerRespawn() {
if (this.getScriptManager().getConfig() == null) return; if (this.getScriptManager().getConfig() == null) return;
var diePos = this.getScriptManager().getConfig().die_y; var diePos = this.getScriptManager().getConfig().die_y;
// Check players in the scene. // Check players in the scene.
this.players.forEach(player -> { this.players.forEach(
player -> {
if (this.getScriptManager().getConfig() == null) return; if (this.getScriptManager().getConfig() == null) return;
// Check if we need a respawn // Check if we need a respawn
@ -461,7 +458,9 @@ public final class Scene {
}); });
// Check entities in the scene. // Check entities in the scene.
this.getEntities().forEach((id, entity) -> { this.getEntities()
.forEach(
(id, entity) -> {
if (diePos >= entity.getPosition().getY()) { if (diePos >= entity.getPosition().getY()) {
this.killEntity(entity); this.killEntity(entity);
} }
@ -503,7 +502,8 @@ public final class Scene {
* @return The respawn rotation for the player. * @return The respawn rotation for the player.
*/ */
private Position getRespawnRotation(Player player) { private Position getRespawnRotation(Player player) {
var lastCheckpointRot = this.dungeonManager != null ? this.dungeonManager.getRespawnRotation() : null; var lastCheckpointRot =
this.dungeonManager != null ? this.dungeonManager.getRespawnRotation() : null;
return lastCheckpointRot != null ? lastCheckpointRot : this.getDefaultRot(player); return lastCheckpointRot != null ? lastCheckpointRot : this.getDefaultRot(player);
} }
@ -520,20 +520,22 @@ public final class Scene {
// TODO: Respawn the player at the last valid location. // TODO: Respawn the player at the last valid location.
var targetPos = getRespawnLocation(player); var targetPos = getRespawnLocation(player);
var targetRot = getRespawnRotation(player); var targetRot = getRespawnRotation(player);
var teleportProps = TeleportProperties.builder() var teleportProps =
TeleportProperties.builder()
.sceneId(getId()) .sceneId(getId())
.teleportTo(targetPos) .teleportTo(targetPos)
.teleportRot(targetRot) .teleportRot(targetRot)
.teleportType(PlayerTeleportEvent.TeleportType.INTERNAL) .teleportType(PlayerTeleportEvent.TeleportType.INTERNAL)
.enterType(EnterTypeOuterClass.EnterType.ENTER_TYPE_GOTO) .enterType(EnterTypeOuterClass.EnterType.ENTER_TYPE_GOTO)
.enterReason(dungeonManager != null ? EnterReason.DungeonReviveOnWaypoint : EnterReason.Revival); .enterReason(
dungeonManager != null ? EnterReason.DungeonReviveOnWaypoint : EnterReason.Revival);
return this.getWorld().transferPlayerToScene(player, teleportProps.build()); return this.getWorld().transferPlayerToScene(player, teleportProps.build());
} }
/** /**
* Invoked when the scene finishes loading. * Invoked when the scene finishes loading. Runs all callbacks that were added with {@link
* Runs all callbacks that were added with {@link #runWhenFinished(Runnable)}. * #runWhenFinished(Runnable)}.
*/ */
public void finishLoading() { public void finishLoading() {
if (this.finishedLoading) return; if (this.finishedLoading) return;
@ -544,14 +546,15 @@ public final class Scene {
} }
/** /**
* Adds a callback to be executed when the scene is finished loading. * Adds a callback to be executed when the scene is finished loading. If the scene is already
* If the scene is already finished loading, the callback will be executed immediately. * finished loading, the callback will be executed immediately.
* *
* @param runnable The callback to be executed. * @param runnable The callback to be executed.
*/ */
public void runWhenFinished(Runnable runnable) { public void runWhenFinished(Runnable runnable) {
if (this.isFinishedLoading()) { if (this.isFinishedLoading()) {
runnable.run();return; runnable.run();
return;
} }
this.afterLoadedCallbacks.add(runnable); this.afterLoadedCallbacks.add(runnable);
@ -774,7 +777,8 @@ public final class Scene {
public int loadDynamicGroup(int group_id) { public int loadDynamicGroup(int group_id) {
SceneGroup group = getScriptManager().getGroupById(group_id); SceneGroup group = getScriptManager().getGroupById(group_id);
if(group == null || getScriptManager().getGroupInstanceById(group_id) != null) return -1; //Group not found or already instanced if (group == null || getScriptManager().getGroupInstanceById(group_id) != null)
return -1; // Group not found or already instanced
onLoadGroup(new ArrayList<>(List.of(group))); onLoadGroup(new ArrayList<>(List.of(group)));
@ -795,29 +799,27 @@ public final class Scene {
public void onRegisterGroups() { public void onRegisterGroups() {
var sceneGroups = this.loadedGroups; var sceneGroups = this.loadedGroups;
var sceneGroupMap = sceneGroups.stream() var sceneGroupMap =
.collect(Collectors.toMap(item -> item.id, item -> item)); sceneGroups.stream().collect(Collectors.toMap(item -> item.id, item -> item));
var sceneGroupsIds = sceneGroups.stream() var sceneGroupsIds = sceneGroups.stream().map(group -> group.id).toList();
.map(group -> group.id) var dynamicGroups =
.toList(); sceneGroups.stream().filter(group -> group.dynamic_load).map(group -> group.id).toList();
var dynamicGroups = sceneGroups.stream()
.filter(group -> group.dynamic_load)
.map(group -> group.id)
.toList();
// Create the graph // Create the graph
var nodes = new ArrayList<KahnsSort.Node>(); var nodes = new ArrayList<KahnsSort.Node>();
var groupList = new ArrayList<Integer>(); var groupList = new ArrayList<Integer>();
GameData.getGroupReplacements().values().stream().filter(replacement -> dynamicGroups.contains(replacement.id)).forEach(replacement -> { GameData.getGroupReplacements().values().stream()
.filter(replacement -> dynamicGroups.contains(replacement.id))
.forEach(
replacement -> {
Grasscutter.getLogger().info("Graph ordering replacement {}", replacement); Grasscutter.getLogger().info("Graph ordering replacement {}", replacement);
replacement.replace_groups.forEach(group -> { replacement.replace_groups.forEach(
group -> {
nodes.add(new KahnsSort.Node(replacement.id, group)); nodes.add(new KahnsSort.Node(replacement.id, group));
if (!groupList.contains(group)) if (!groupList.contains(group)) groupList.add(group);
groupList.add(group);
}); });
if (!groupList.contains(replacement.id)) if (!groupList.contains(replacement.id)) groupList.add(replacement.id);
groupList.add(replacement.id);
}); });
KahnsSort.Graph graph = new KahnsSort.Graph(nodes, groupList); KahnsSort.Graph graph = new KahnsSort.Graph(nodes, groupList);
@ -825,10 +827,12 @@ public final class Scene {
if (dynamicGroupsOrdered == null) throw new RuntimeException("Invalid group replacement graph"); if (dynamicGroupsOrdered == null) throw new RuntimeException("Invalid group replacement graph");
// Now we can start unloading and loading groups :D // Now we can start unloading and loading groups :D
dynamicGroupsOrdered.forEach(group -> { dynamicGroupsOrdered.forEach(
group -> {
if (GameData.getGroupReplacements().containsKey((int) group)) { // isGroupJoinReplacement if (GameData.getGroupReplacements().containsKey((int) group)) { // isGroupJoinReplacement
var data = GameData.getGroupReplacements().get((int) group); var data = GameData.getGroupReplacements().get((int) group);
var sceneGroupReplacement = this.loadedGroups.stream().filter(g -> g.id == group).findFirst().orElseThrow(); var sceneGroupReplacement =
this.loadedGroups.stream().filter(g -> g.id == group).findFirst().orElseThrow();
if (sceneGroupReplacement.is_replaceable != null) { if (sceneGroupReplacement.is_replaceable != null) {
var it = data.replace_groups.iterator(); var it = data.replace_groups.iterator();
while (it.hasNext()) { while (it.hasNext()) {
@ -837,11 +841,14 @@ public final class Scene {
// Check if we can replace this group // Check if we can replace this group
SceneGroup sceneGroup = sceneGroupMap.get(replace_group); SceneGroup sceneGroup = sceneGroupMap.get(replace_group);
if (sceneGroup != null && sceneGroup.is_replaceable != null && if (sceneGroup != null
((sceneGroup.is_replaceable.value && && sceneGroup.is_replaceable != null
sceneGroup.is_replaceable.version <= sceneGroupReplacement.is_replaceable.version) || && ((sceneGroup.is_replaceable.value
sceneGroup.is_replaceable.new_bin_only)) { && sceneGroup.is_replaceable.version
this.unloadGroup(scriptManager.getBlocks().get(sceneGroup.block_id), replace_group); <= sceneGroupReplacement.is_replaceable.version)
|| sceneGroup.is_replaceable.new_bin_only)) {
this.unloadGroup(
scriptManager.getBlocks().get(sceneGroup.block_id), replace_group);
it.remove(); it.remove();
Grasscutter.getLogger().info("Graph ordering: unloaded {}", replace_group); Grasscutter.getLogger().info("Graph ordering: unloaded {}", replace_group);
} }
@ -853,8 +860,11 @@ public final class Scene {
public void loadTriggerFromGroup(SceneGroup group, String triggerName) { public void loadTriggerFromGroup(SceneGroup group, String triggerName) {
// Load triggers and regions // Load triggers and regions
this.getScriptManager().registerTrigger(group.triggers.values().stream() this.getScriptManager()
.filter(p -> p.getName().contains(triggerName)).toList()); .registerTrigger(
group.triggers.values().stream()
.filter(p -> p.getName().contains(triggerName))
.toList());
group.regions.values().stream() group.regions.values().stream()
.filter(q -> q.config_id == Integer.parseInt(triggerName.substring(13))) .filter(q -> q.config_id == Integer.parseInt(triggerName.substring(13)))
.map(region -> new EntityRegion(this, region)) .map(region -> new EntityRegion(this, region))
@ -897,20 +907,24 @@ public final class Scene {
var garbageGadgets = group.getGarbageGadgets(); var garbageGadgets = group.getGarbageGadgets();
if (garbageGadgets != null) { if (garbageGadgets != null) {
entities.addAll(garbageGadgets.stream() entities.addAll(
garbageGadgets.stream()
.map(g -> scriptManager.createGadget(group.id, group.block_id, g)) .map(g -> scriptManager.createGadget(group.id, group.block_id, g))
.filter(Objects::nonNull).toList()); .filter(Objects::nonNull)
.toList());
} }
// Load suites // Load suites
// int suite = group.findInitSuiteIndex(0); // int suite = group.findInitSuiteIndex(0);
this.getScriptManager().refreshGroup(groupInstance, 0, false); //This is what the official server does this.getScriptManager()
.refreshGroup(groupInstance, 0, false); // This is what the official server does
this.loadedGroups.add(group); this.loadedGroups.add(group);
} }
this.scriptManager.meetEntities(entities); this.scriptManager.meetEntities(entities);
groups.forEach(g -> scriptManager.callEvent(new ScriptArgs(g.id, EventType.EVENT_GROUP_LOAD, g.id))); groups.forEach(
g -> scriptManager.callEvent(new ScriptArgs(g.id, EventType.EVENT_GROUP_LOAD, g.id)));
Grasscutter.getLogger().info("Scene {} loaded {} group(s)", this.getId(), groups.size()); Grasscutter.getLogger().info("Scene {} loaded {} group(s)", this.getId(), groups.size());
} }
@ -944,25 +958,23 @@ public final class Scene {
* @param groupId The group ID. * @param groupId The group ID.
*/ */
public void unloadGroup(SceneBlock block, int groupId) { public void unloadGroup(SceneBlock block, int groupId) {
var toRemove = this.getEntities().values().stream() var toRemove =
.filter(e -> e != null && ( this.getEntities().values().stream()
e.getBlockId() == block.id && .filter(e -> e != null && (e.getBlockId() == block.id && e.getGroupId() == groupId))
e.getGroupId() == groupId) .toList();
).toList();
if (toRemove.size() > 0) { if (toRemove.size() > 0) {
toRemove.forEach(this::removeEntityDirectly); toRemove.forEach(this::removeEntityDirectly);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_TYPE_REMOVE)); this.broadcastPacket(
new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_TYPE_REMOVE));
} }
var group = block.groups.get(groupId); var group = block.groups.get(groupId);
if (group.triggers != null) { if (group.triggers != null) {
group.triggers.values().forEach( group.triggers.values().forEach(this.getScriptManager()::deregisterTrigger);
this.getScriptManager()::deregisterTrigger);
} }
if (group.regions != null) { if (group.regions != null) {
group.regions.values().forEach( group.regions.values().forEach(this.getScriptManager()::deregisterRegion);
this.getScriptManager()::deregisterRegion);
} }
this.scriptManager.getLoadedGroupSetPerBlock().get(block.id).remove(group); this.scriptManager.getLoadedGroupSetPerBlock().get(block.id).remove(group);
@ -1093,7 +1105,8 @@ public final class Scene {
return; return;
} }
sceneGroupSuite.forEach(i -> { sceneGroupSuite.forEach(
i -> {
var group = scriptManager.getGroupById(i.getGroup()); var group = scriptManager.getGroupById(i.getGroup());
if (group == null) return; if (group == null) return;

View File

@ -1,12 +1,5 @@
package emu.grasscutter.game.world; package emu.grasscutter.game.world;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.bson.types.ObjectId;
import dev.morphia.annotations.Entity; import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id; import dev.morphia.annotations.Id;
import dev.morphia.annotations.Indexed; import dev.morphia.annotations.Indexed;
@ -14,8 +7,13 @@ import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.scripts.data.SceneGadget; import emu.grasscutter.scripts.data.SceneGadget;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.bson.types.ObjectId;
@Entity(value = "group_instances", useDiscriminator = false) @Entity(value = "group_instances", useDiscriminator = false)
public final class SceneGroupInstance { public final class SceneGroupInstance {
@ -46,7 +44,8 @@ public final class SceneGroupInstance {
this.cachedGadgetStates = new ConcurrentHashMap<>(); this.cachedGadgetStates = new ConcurrentHashMap<>();
this.cachedVariables = new ConcurrentHashMap<>(); this.cachedVariables = new ConcurrentHashMap<>();
this.isCached = false; //This is true when the group is not loaded on scene but caches suite data this.isCached =
false; // This is true when the group is not loaded on scene but caches suite data
} }
@Deprecated // Morphia only! @Deprecated // Morphia only!

View File

@ -1,8 +1,9 @@
package emu.grasscutter.scripts; package emu.grasscutter.scripts;
import static emu.grasscutter.scripts.constants.EventType.*;
import com.github.davidmoten.rtreemulti.RTree; import com.github.davidmoten.rtreemulti.RTree;
import com.github.davidmoten.rtreemulti.geometry.Geometry; import com.github.davidmoten.rtreemulti.geometry.Geometry;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameData;
import emu.grasscutter.data.server.Grid; import emu.grasscutter.data.server.Grid;
@ -25,34 +26,28 @@ import emu.grasscutter.utils.GridPosition;
import emu.grasscutter.utils.JsonUtils; import emu.grasscutter.utils.JsonUtils;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import io.netty.util.concurrent.FastThreadLocalThread; import io.netty.util.concurrent.FastThreadLocalThread;
import kotlin.Pair;
import lombok.val;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import static emu.grasscutter.scripts.constants.EventType.*; import javax.annotation.Nullable;
import kotlin.Pair;
import lombok.val;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
public class SceneScriptManager { public class SceneScriptManager {
private final Scene scene; private final Scene scene;
private final Map<String, Integer> variables; private final Map<String, Integer> variables;
private SceneMeta meta; private SceneMeta meta;
private boolean isInit; private boolean isInit;
/** /** current triggers controlled by RefreshGroup */
* current triggers controlled by RefreshGroup
*/
private final Map<Integer, Set<SceneTrigger>> currentTriggers; private final Map<Integer, Set<SceneTrigger>> currentTriggers;
private final Map<String, Set<SceneTrigger>> triggersByGroupScene; private final Map<String, Set<SceneTrigger>> triggersByGroupScene;
private final Map<Integer, Set<Pair<String, Integer>>> activeGroupTimers; private final Map<Integer, Set<Pair<String, Integer>>> activeGroupTimers;
private final Map<String, AtomicInteger> triggerInvocations; private final Map<String, AtomicInteger> triggerInvocations;
@ -62,17 +57,24 @@ public class SceneScriptManager {
private final Map<Integer, SceneGroupInstance> cachedSceneGroupsInstances; private final Map<Integer, SceneGroupInstance> cachedSceneGroupsInstances;
private ScriptMonsterTideService scriptMonsterTideService; private ScriptMonsterTideService scriptMonsterTideService;
private ScriptMonsterSpawnService scriptMonsterSpawnService; private ScriptMonsterSpawnService scriptMonsterSpawnService;
/** /** blockid - loaded groupSet */
* blockid - loaded groupSet
*/
private final Map<Integer, Set<SceneGroup>> loadedGroupSetPerBlock; private final Map<Integer, Set<SceneGroup>> loadedGroupSetPerBlock;
private List<Grid> groupGrids; private List<Grid> groupGrids;
public static final ExecutorService eventExecutor; public static final ExecutorService eventExecutor;
static { static {
eventExecutor = new ThreadPoolExecutor(4, 4, eventExecutor =
60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10000), new ThreadPoolExecutor(
FastThreadLocalThread::new, new ThreadPoolExecutor.AbortPolicy()); 4,
4,
60,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(10000),
FastThreadLocalThread::new,
new ThreadPoolExecutor.AbortPolicy());
} }
public SceneScriptManager(Scene scene) { public SceneScriptManager(Scene scene) {
this.scene = scene; this.scene = scene;
this.currentTriggers = new ConcurrentHashMap<>(); this.currentTriggers = new ConcurrentHashMap<>();
@ -90,7 +92,8 @@ public class SceneScriptManager {
this.groupGrids = null; // This is changed on init this.groupGrids = null; // This is changed on init
// TEMPORARY // TEMPORARY
if (this.getScene().getId() < 10 && !Grasscutter.getConfig().server.game.enableScriptInBigWorld) { if (this.getScene().getId() < 10
&& !Grasscutter.getConfig().server.game.enableScriptInBigWorld) {
return; return;
} }
@ -114,8 +117,7 @@ public class SceneScriptManager {
return meta.blocks; return meta.blocks;
} }
@Nullable @Nullable public Map<String, Integer> getVariables(int group_id) {
public Map<String, Integer> getVariables(int group_id) {
if (getCachedGroupInstanceById(group_id) == null) return null; if (getCachedGroupInstanceById(group_id) == null) return null;
return getCachedGroupInstanceById(group_id).getCachedVariables(); return getCachedGroupInstanceById(group_id).getCachedVariables();
} }
@ -123,12 +125,15 @@ public class SceneScriptManager {
public Set<SceneTrigger> getTriggersByEvent(int eventId) { public Set<SceneTrigger> getTriggersByEvent(int eventId) {
return currentTriggers.computeIfAbsent(eventId, e -> ConcurrentHashMap.newKeySet()); return currentTriggers.computeIfAbsent(eventId, e -> ConcurrentHashMap.newKeySet());
} }
public int getTriggerCount() { public int getTriggerCount() {
return currentTriggers.size(); return currentTriggers.size();
} }
public void registerTrigger(List<SceneTrigger> triggers) { public void registerTrigger(List<SceneTrigger> triggers) {
triggers.forEach(this::registerTrigger); triggers.forEach(this::registerTrigger);
} }
public void registerTrigger(SceneTrigger trigger) { public void registerTrigger(SceneTrigger trigger) {
triggerInvocations.put(trigger.getName(), new AtomicInteger(0)); triggerInvocations.put(trigger.getName(), new AtomicInteger(0));
getTriggersByEvent(trigger.getEvent()).add(trigger); getTriggersByEvent(trigger.getEvent()).add(trigger);
@ -138,6 +143,7 @@ public class SceneScriptManager {
public void deregisterTrigger(List<SceneTrigger> triggers) { public void deregisterTrigger(List<SceneTrigger> triggers) {
triggers.forEach(this::deregisterTrigger); triggers.forEach(this::deregisterTrigger);
} }
public void deregisterTrigger(SceneTrigger trigger) { public void deregisterTrigger(SceneTrigger trigger) {
getTriggersByEvent(trigger.getEvent()).remove(trigger); getTriggersByEvent(trigger.getEvent()).remove(trigger);
Grasscutter.getLogger().debug("deregistered trigger {}", trigger.getName()); Grasscutter.getLogger().debug("deregistered trigger {}", trigger.getName());
@ -151,7 +157,11 @@ public class SceneScriptManager {
Grasscutter.getLogger().debug("reset triggers for group {} suite {}", group.id, suiteIndex); Grasscutter.getLogger().debug("reset triggers for group {} suite {}", group.id, suiteIndex);
var suite = group.getSuiteByIndex(suiteIndex); var suite = group.getSuiteByIndex(suiteIndex);
if (suite == null) { if (suite == null) {
Grasscutter.getLogger().warn("Trying to load null suite Triggers for group {} with suiteindex {}", group.id, suiteIndex); Grasscutter.getLogger()
.warn(
"Trying to load null suite Triggers for group {} with suiteindex {}",
group.id,
suiteIndex);
return; return;
} }
@ -184,16 +194,18 @@ public class SceneScriptManager {
} }
// for (int i = 1; i<= group.suites.size();i++){ // for (int i = 1; i<= group.suites.size();i++){
// refreshGroup(group, i); // refreshGroup(group, i);
refreshGroup(groupInstance, groupInstance.getActiveSuiteId(), false); //Refresh the last group triggers refreshGroup(
groupInstance, groupInstance.getActiveSuiteId(), false); // Refresh the last group triggers
// } // }
} }
public int refreshGroup(SceneGroupInstance groupInstance, int suiteIndex, boolean excludePrevSuite) {
public int refreshGroup(
SceneGroupInstance groupInstance, int suiteIndex, boolean excludePrevSuite) {
SceneGroup group = groupInstance.getLuaGroup(); SceneGroup group = groupInstance.getLuaGroup();
if (suiteIndex == 0) { if (suiteIndex == 0) {
if (excludePrevSuite) { if (excludePrevSuite) {
suiteIndex = group.findInitSuiteIndex(groupInstance.getActiveSuiteId()); suiteIndex = group.findInitSuiteIndex(groupInstance.getActiveSuiteId());
} else } else suiteIndex = group.findInitSuiteIndex(0);
suiteIndex = group.findInitSuiteIndex(0);
} }
if (suiteIndex == 0) return 0; if (suiteIndex == 0) return 0;
@ -215,9 +227,12 @@ public class SceneScriptManager {
} }
} }
if(waitForOne && (groupInstance.getTargetSuiteId() == 0 || prevSuiteIndex != groupInstance.getTargetSuiteId())) { if (waitForOne
&& (groupInstance.getTargetSuiteId() == 0
|| prevSuiteIndex != groupInstance.getTargetSuiteId())) {
groupInstance.setTargetSuiteId(suiteIndex); groupInstance.setTargetSuiteId(suiteIndex);
Grasscutter.getLogger().debug("Group {} suite {} wating one more refresh", group.id, suiteIndex); Grasscutter.getLogger()
.debug("Group {} suite {} wating one more refresh", group.id, suiteIndex);
return 0; return 0;
} }
@ -230,7 +245,8 @@ public class SceneScriptManager {
addGroupSuite(groupInstance, suiteData); addGroupSuite(groupInstance, suiteData);
// Refesh variables here // Refesh variables here
group.variables.forEach(variable -> { group.variables.forEach(
variable -> {
if (!variable.no_refresh) if (!variable.no_refresh)
groupInstance.getCachedVariables().put(variable.name, variable.value); groupInstance.getCachedVariables().put(variable.name, variable.value);
}); });
@ -243,21 +259,32 @@ public class SceneScriptManager {
public boolean refreshGroupSuite(int groupId, int suiteId, GameQuest quest) { public boolean refreshGroupSuite(int groupId, int suiteId, GameQuest quest) {
var targetGroupInstance = getGroupInstanceById(groupId); var targetGroupInstance = getGroupInstanceById(groupId);
if (targetGroupInstance == null) { if (targetGroupInstance == null) {
getGroupById(groupId); //Load the group, this ensures an instance is created and the if neccesary unloaded, but the suite data is stored getGroupById(
groupId); // Load the group, this ensures an instance is created and the if neccesary
// unloaded, but the suite data is stored
targetGroupInstance = getGroupInstanceById(groupId); targetGroupInstance = getGroupInstanceById(groupId);
Grasscutter.getLogger().debug("trying to regresh group suite {} in an unloaded and uncached group {} in scene {}", suiteId, groupId, getScene().getId()); Grasscutter.getLogger()
.debug(
"trying to regresh group suite {} in an unloaded and uncached group {} in scene {}",
suiteId,
groupId,
getScene().getId());
} else { } else {
Grasscutter.getLogger().debug("Refreshing group {} suite {}", groupId, suiteId); Grasscutter.getLogger().debug("Refreshing group {} suite {}", groupId, suiteId);
suiteId = refreshGroup(targetGroupInstance, suiteId, false); //If suiteId is zero, the value of suiteId changes suiteId =
refreshGroup(
targetGroupInstance,
suiteId,
false); // If suiteId is zero, the value of suiteId changes
quest.getOwner().sendPacket(new PacketGroupSuiteNotify(groupId, suiteId)); quest.getOwner().sendPacket(new PacketGroupSuiteNotify(groupId, suiteId));
} }
if (suiteId != 0 && quest != null) { if (suiteId != 0 && quest != null) {
quest.getMainQuest().getQuestGroupSuites().add(QuestGroupSuite.of() quest
.scene(getScene().getId()) .getMainQuest()
.group(groupId) .getQuestGroupSuites()
.suite(suiteId) .add(
.build()); QuestGroupSuite.of().scene(getScene().getId()).group(groupId).suite(suiteId).build());
} }
return true; return true;
@ -266,15 +293,24 @@ public class SceneScriptManager {
public boolean refreshGroupMonster(int groupId) { public boolean refreshGroupMonster(int groupId) {
var groupInstance = getGroupInstanceById(groupId); var groupInstance = getGroupInstanceById(groupId);
if (groupInstance == null) { if (groupInstance == null) {
Grasscutter.getLogger().warn("trying to refesh monster group in unloaded and uncached group {} in scene {}", groupId, getScene().getId()); Grasscutter.getLogger()
.warn(
"trying to refesh monster group in unloaded and uncached group {} in scene {}",
groupId,
getScene().getId());
return false; return false;
} }
var group = groupInstance.getLuaGroup(); var group = groupInstance.getLuaGroup();
var monstersToSpawn = group.monsters.values().stream() var monstersToSpawn =
.filter(m -> { group.monsters.values().stream()
.filter(
m -> {
var entity = scene.getEntityByConfigId(m.config_id); var entity = scene.getEntityByConfigId(m.config_id);
return (entity == null || entity.getGroupId()!=group.id);/*&& !groupInstance.getDeadEntities().contains(entity); */ //TODO: Investigate the usage of deadEntities return (entity == null
|| entity.getGroupId()
!= group
.id); /*&& !groupInstance.getDeadEntities().contains(entity); */ // TODO: Investigate the usage of deadEntities
}) })
.map(mob -> createMonster(group.id, group.block_id, mob)) .map(mob -> createMonster(group.id, group.block_id, mob))
.toList(); // TODO check if it interferes with bigworld or anything else .toList(); // TODO check if it interferes with bigworld or anything else
@ -282,22 +318,29 @@ public class SceneScriptManager {
return true; return true;
} }
public EntityRegion getRegionById(int id) { public EntityRegion getRegionById(int id) {
return regions.get(id); return regions.get(id);
} }
public void registerRegion(EntityRegion region) { public void registerRegion(EntityRegion region) {
regions.put(region.getId(), region); regions.put(region.getId(), region);
Grasscutter.getLogger().debug("Registered region {} from group {}", region.getMetaRegion().config_id, region.getGroupId()); Grasscutter.getLogger()
.debug(
"Registered region {} from group {}",
region.getMetaRegion().config_id,
region.getGroupId());
} }
public void registerRegionInGroupSuite(SceneGroup group, SceneSuite suite) { public void registerRegionInGroupSuite(SceneGroup group, SceneSuite suite) {
suite.sceneRegions.stream().map(region -> new EntityRegion(this.getScene(), region)) suite.sceneRegions.stream()
.map(region -> new EntityRegion(this.getScene(), region))
.forEach(this::registerRegion); .forEach(this::registerRegion);
} }
public synchronized void deregisterRegion(SceneRegion region) { public synchronized void deregisterRegion(SceneRegion region) {
var instance = regions.values().stream() var instance =
.filter(r -> r.getConfigId() == region.config_id) regions.values().stream().filter(r -> r.getConfigId() == region.config_id).findFirst();
.findFirst();
instance.ifPresent(entityRegion -> regions.remove(entityRegion.getId())); instance.ifPresent(entityRegion -> regions.remove(entityRegion.getId()));
} }
@ -342,11 +385,13 @@ public class SceneScriptManager {
return instance; return instance;
} }
private static void addGridPositionToMap(Map<GridPosition, Set<Integer>> map, int group_id, int vision_level, Position position) { private static void addGridPositionToMap(
Map<GridPosition, Set<Integer>> map, int group_id, int vision_level, Position position) {
// Convert position to grid position // Convert position to grid position
GridPosition gridPos; GridPosition gridPos;
int width = Grasscutter.getConfig().server.game.visionOptions[vision_level].gridWidth; int width = Grasscutter.getConfig().server.game.visionOptions[vision_level].gridWidth;
gridPos = new GridPosition((int)(position.getX() / width), (int)(position.getZ() / width), width); gridPos =
new GridPosition((int) (position.getX() / width), (int) (position.getZ() / width), width);
Set<Integer> groups = map.getOrDefault(gridPos, new HashSet<>()); Set<Integer> groups = map.getOrDefault(gridPos, new HashSet<>());
groups.add(group_id); groups.add(group_id);
@ -391,36 +436,87 @@ public class SceneScriptManager {
for (int i = 0; i < 6; i++) groupPositions.add(new HashMap<>()); for (int i = 0; i < 6; i++) groupPositions.add(new HashMap<>());
var visionOptions = Grasscutter.getConfig().server.game.visionOptions; var visionOptions = Grasscutter.getConfig().server.game.visionOptions;
meta.blocks.values().forEach(block -> { meta.blocks
.values()
.forEach(
block -> {
block.load(scene.getId(), meta.context); block.load(scene.getId(), meta.context);
block.groups.values().stream().filter(g -> !g.dynamic_load).forEach(group -> { block.groups.values().stream()
.filter(g -> !g.dynamic_load)
.forEach(
group -> {
group.load(this.scene.getId()); group.load(this.scene.getId());
// Add all entitites here // Add all entitites here
Set<Integer> vision_levels = new HashSet<>(); Set<Integer> vision_levels = new HashSet<>();
group.monsters.values().forEach(m -> { group
addGridPositionToMap(groupPositions.get(m.vision_level), group.id, m.vision_level, m.pos); .monsters
.values()
.forEach(
m -> {
addGridPositionToMap(
groupPositions.get(m.vision_level),
group.id,
m.vision_level,
m.pos);
vision_levels.add(m.vision_level); vision_levels.add(m.vision_level);
}); });
group.gadgets.values().forEach(g -> { group
int vision_level = Math.max(getGadgetVisionLevel(g.gadget_id), g.vision_level); .gadgets
addGridPositionToMap(groupPositions.get(vision_level), group.id, vision_level, g.pos); .values()
.forEach(
g -> {
int vision_level =
Math.max(getGadgetVisionLevel(g.gadget_id), g.vision_level);
addGridPositionToMap(
groupPositions.get(vision_level),
group.id,
vision_level,
g.pos);
vision_levels.add(vision_level); vision_levels.add(vision_level);
}); });
group.npcs.values().forEach(n -> addGridPositionToMap(groupPositions.get(n.vision_level), group.id, n.vision_level, n.pos)); group
group.regions.values().forEach(r -> addGridPositionToMap(groupPositions.get(0), group.id, 0, r.pos)); .npcs
if(group.garbages != null && group.garbages.gadgets != null) group.garbages.gadgets.forEach(g -> addGridPositionToMap(groupPositions.get(g.vision_level), group.id, g.vision_level, g.pos)); .values()
.forEach(
n ->
addGridPositionToMap(
groupPositions.get(n.vision_level),
group.id,
n.vision_level,
n.pos));
group
.regions
.values()
.forEach(
r ->
addGridPositionToMap(
groupPositions.get(0), group.id, 0, r.pos));
if (group.garbages != null && group.garbages.gadgets != null)
group.garbages.gadgets.forEach(
g ->
addGridPositionToMap(
groupPositions.get(g.vision_level),
group.id,
g.vision_level,
g.pos));
int max_vision_level = -1; int max_vision_level = -1;
if (!vision_levels.isEmpty()) { if (!vision_levels.isEmpty()) {
for (int vision_level : vision_levels) { for (int vision_level : vision_levels) {
if(max_vision_level == -1 || visionOptions[max_vision_level].visionRange < visionOptions[vision_level].visionRange) if (max_vision_level == -1
|| visionOptions[max_vision_level].visionRange
< visionOptions[vision_level].visionRange)
max_vision_level = vision_level; max_vision_level = vision_level;
} }
} }
if (max_vision_level == -1) max_vision_level = 0; if (max_vision_level == -1) max_vision_level = 0;
addGridPositionToMap(groupPositions.get(max_vision_level), group.id, max_vision_level, group.pos); addGridPositionToMap(
groupPositions.get(max_vision_level),
group.id,
max_vision_level,
group.pos);
}); });
}); });
@ -469,7 +565,8 @@ public class SceneScriptManager {
} }
if (group.variables != null) { if (group.variables != null) {
group.variables.forEach(variable -> { group.variables.forEach(
variable -> {
val variables = this.getVariables(group.id); val variables = this.getVariables(group.id);
if (variables != null && !variables.containsKey(variable.name)) if (variables != null && !variables.containsKey(variable.name))
variables.put(variable.name, variable.value); variables.put(variable.name, variable.value);
@ -480,7 +577,9 @@ public class SceneScriptManager {
public void unregisterGroup(SceneGroup group) { public void unregisterGroup(SceneGroup group) {
this.sceneGroups.remove(group.id); this.sceneGroups.remove(group.id);
this.sceneGroupsInstances.values().removeIf(i -> i.getLuaGroup().equals(group)); this.sceneGroupsInstances.values().removeIf(i -> i.getLuaGroup().equals(group));
this.cachedSceneGroupsInstances.values().stream().filter(i -> i.getLuaGroup().equals(group)).forEach(s -> s.setCached(true)); this.cachedSceneGroupsInstances.values().stream()
.filter(i -> i.getLuaGroup().equals(group))
.forEach(s -> s.setCached(true));
} }
public void checkRegions() { public void checkRegions() {
@ -489,10 +588,14 @@ public class SceneScriptManager {
} }
for (var region : this.regions.values()) { for (var region : this.regions.values()) {
// currently all condition_ENTER_REGION Events check for avatar, so we have no necessary to add other types of entity // currently all condition_ENTER_REGION Events check for avatar, so we have no necessary to
var entities = getScene().getEntities().values() // add other types of entity
.stream() var entities =
.filter(e -> e.getEntityType() == EntityType.Avatar.getValue() && region.getMetaRegion().contains(e.getPosition())) getScene().getEntities().values().stream()
.filter(
e ->
e.getEntityType() == EntityType.Avatar.getValue()
&& region.getMetaRegion().contains(e.getPosition()))
.toList(); .toList();
entities.forEach(region::addEntity); entities.forEach(region::addEntity);
@ -502,50 +605,63 @@ public class SceneScriptManager {
} }
if (region.hasNewEntities()) { if (region.hasNewEntities()) {
Grasscutter.getLogger().trace("Call EVENT_ENTER_REGION_{}",region.getMetaRegion().config_id); Grasscutter.getLogger()
callEvent(new ScriptArgs(region.getGroupId(), EventType.EVENT_ENTER_REGION, region.getConfigId()) .trace("Call EVENT_ENTER_REGION_{}", region.getMetaRegion().config_id);
callEvent(
new ScriptArgs(region.getGroupId(), EventType.EVENT_ENTER_REGION, region.getConfigId())
.setSourceEntityId(region.getId()) .setSourceEntityId(region.getId())
.setTargetEntityId(targetID) .setTargetEntityId(targetID));
);
region.resetNewEntities(); region.resetNewEntities();
} }
for (int entityId : region.getEntities()) { for (int entityId : region.getEntities()) {
if (getScene().getEntityById(entityId) == null || !region.getMetaRegion().contains(getScene().getEntityById(entityId).getPosition())) { if (getScene().getEntityById(entityId) == null
|| !region.getMetaRegion().contains(getScene().getEntityById(entityId).getPosition())) {
region.removeEntity(entityId); region.removeEntity(entityId);
} }
} }
if (region.entityLeave()) { if (region.entityLeave()) {
callEvent(new ScriptArgs(region.getGroupId(), EventType.EVENT_LEAVE_REGION, region.getConfigId()) callEvent(
new ScriptArgs(region.getGroupId(), EventType.EVENT_LEAVE_REGION, region.getConfigId())
.setSourceEntityId(region.getId()) .setSourceEntityId(region.getId())
.setTargetEntityId(region.getFirstEntityId()) .setTargetEntityId(region.getFirstEntityId()));
);
region.resetNewEntities(); region.resetNewEntities();
} }
} }
} }
public List<EntityGadget> getGadgetsInGroupSuite(SceneGroupInstance groupInstance, SceneSuite suite) { public List<EntityGadget> getGadgetsInGroupSuite(
SceneGroupInstance groupInstance, SceneSuite suite) {
var group = groupInstance.getLuaGroup(); var group = groupInstance.getLuaGroup();
return suite.sceneGadgets.stream() return suite.sceneGadgets.stream()
.filter(m -> { .filter(
m -> {
var entity = scene.getEntityByConfigId(m.config_id); var entity = scene.getEntityByConfigId(m.config_id);
return (entity == null || entity.getGroupId()!=group.id) && (!m.isOneoff || !m.persistent || !groupInstance.getDeadEntities().contains(m.config_id)); return (entity == null || entity.getGroupId() != group.id)
&& (!m.isOneoff
|| !m.persistent
|| !groupInstance.getDeadEntities().contains(m.config_id));
}) })
.map(g -> createGadget(group.id, group.block_id, g, groupInstance.getCachedGadgetState(g))) .map(g -> createGadget(group.id, group.block_id, g, groupInstance.getCachedGadgetState(g)))
.peek(g -> groupInstance.cacheGadgetState(g.getMetaGadget(), g.getState())) .peek(g -> groupInstance.cacheGadgetState(g.getMetaGadget(), g.getState()))
.filter(Objects::nonNull) .filter(Objects::nonNull)
.toList(); .toList();
} }
public List<EntityMonster> getMonstersInGroupSuite(SceneGroupInstance groupInstance, SceneSuite suite) {
public List<EntityMonster> getMonstersInGroupSuite(
SceneGroupInstance groupInstance, SceneSuite suite) {
var group = groupInstance.getLuaGroup(); var group = groupInstance.getLuaGroup();
return suite.sceneMonsters.stream() return suite.sceneMonsters.stream()
.filter(m -> { .filter(
m -> {
var entity = scene.getEntityByConfigId(m.config_id); var entity = scene.getEntityByConfigId(m.config_id);
return (entity == null || entity.getGroupId()!=group.id);/*&& !groupInstance.getDeadEntities().contains(entity); */ //TODO: Investigate the usage of deadEntities return (entity == null
|| entity.getGroupId()
!= group
.id); /*&& !groupInstance.getDeadEntities().contains(entity); */ // TODO:
// Investigate the usage of deadEntities
}) // TODO: Add persistent monster cached data }) // TODO: Add persistent monster cached data
.map(mob -> createMonster(group.id, group.block_id, mob)) .map(mob -> createMonster(group.id, group.block_id, mob))
.filter(Objects::nonNull) .filter(Objects::nonNull)
@ -564,6 +680,7 @@ public class SceneScriptManager {
registerRegionInGroupSuite(group, suite); registerRegionInGroupSuite(group, suite);
} }
public void refreshGroupSuite(SceneGroupInstance groupInstance, SceneSuite suite) { public void refreshGroupSuite(SceneGroupInstance groupInstance, SceneSuite suite) {
// we added trigger first // we added trigger first
registerTrigger(suite.sceneTriggers); registerTrigger(suite.sceneTriggers);
@ -576,6 +693,7 @@ public class SceneScriptManager {
registerRegionInGroupSuite(group, suite); registerRegionInGroupSuite(group, suite);
} }
public void removeGroupSuite(SceneGroup group, SceneSuite suite) { public void removeGroupSuite(SceneGroup group, SceneSuite suite) {
deregisterTrigger(suite.sceneTriggers); deregisterTrigger(suite.sceneTriggers);
removeMonstersInGroup(group, suite); removeMonstersInGroup(group, suite);
@ -583,6 +701,7 @@ public class SceneScriptManager {
suite.sceneRegions.forEach(this::deregisterRegion); suite.sceneRegions.forEach(this::deregisterRegion);
} }
public void killGroupSuite(SceneGroup group, SceneSuite suite) { public void killGroupSuite(SceneGroup group, SceneSuite suite) {
deregisterTrigger(suite.sceneTriggers); deregisterTrigger(suite.sceneTriggers);
@ -592,41 +711,47 @@ public class SceneScriptManager {
suite.sceneRegions.forEach(this::deregisterRegion); suite.sceneRegions.forEach(this::deregisterRegion);
} }
public void startMonsterTideInGroup(SceneGroup group, Integer[] ordersConfigId, int tideCount, int sceneLimit) { public void startMonsterTideInGroup(
SceneGroup group, Integer[] ordersConfigId, int tideCount, int sceneLimit) {
this.scriptMonsterTideService = this.scriptMonsterTideService =
new ScriptMonsterTideService(this, group, tideCount, sceneLimit, ordersConfigId); new ScriptMonsterTideService(this, group, tideCount, sceneLimit, ordersConfigId);
} }
public void unloadCurrentMonsterTide() { public void unloadCurrentMonsterTide() {
if (this.getScriptMonsterTideService() == null) { if (this.getScriptMonsterTideService() == null) {
return; return;
} }
this.getScriptMonsterTideService().unload(); this.getScriptMonsterTideService().unload();
} }
public void spawnMonstersByConfigId(SceneGroup group, int configId, int delayTime) { public void spawnMonstersByConfigId(SceneGroup group, int configId, int delayTime) {
// TODO delay // TODO delay
var entity = scene.getEntityByConfigId(configId); var entity = scene.getEntityByConfigId(configId);
if (entity != null && entity.getGroupId() == group.id) { if (entity != null && entity.getGroupId() == group.id) {
Grasscutter.getLogger().debug("entity already exists failed in group {} with config {}", group.id, configId); Grasscutter.getLogger()
.debug("entity already exists failed in group {} with config {}", group.id, configId);
return; return;
} }
entity = createMonster(group.id, group.block_id, group.monsters.get(configId)); entity = createMonster(group.id, group.block_id, group.monsters.get(configId));
if (entity != null) { if (entity != null) {
getScene().addEntity(entity); getScene().addEntity(entity);
} else { } else {
Grasscutter.getLogger().warn("failed to create entity with group {} and config {}", group.id, configId); Grasscutter.getLogger()
.warn("failed to create entity with group {} and config {}", group.id, configId);
} }
} }
// Events // Events
public void callEvent(int groupId, int eventType) { public void callEvent(int groupId, int eventType) {
callEvent(new ScriptArgs(groupId, eventType)); callEvent(new ScriptArgs(groupId, eventType));
} }
public void callEvent(@Nonnull ScriptArgs params) { public void callEvent(@Nonnull ScriptArgs params) {
/** /**
* We use ThreadLocal to trans SceneScriptManager context to ScriptLib, to avoid eval script for every groups' trigger in every scene instances. * We use ThreadLocal to trans SceneScriptManager context to ScriptLib, to avoid eval script for
* But when callEvent is called in a ScriptLib func, it may cause NPE because the inner call cleans the ThreadLocal so that outer call could not get it. * every groups' trigger in every scene instances. But when callEvent is called in a ScriptLib
* e.g. CallEvent -> set -> ScriptLib.xxx -> CallEvent -> set -> remove -> NPE -> (remove) * func, it may cause NPE because the inner call cleans the ThreadLocal so that outer call could
* So we use thread pool to clean the stack to avoid this new issue. * not get it. e.g. CallEvent -> set -> ScriptLib.xxx -> CallEvent -> set -> remove -> NPE ->
* (remove) So we use thread pool to clean the stack to avoid this new issue.
*/ */
eventExecutor.submit(() -> this.realCallEvent(params)); eventExecutor.submit(() -> this.realCallEvent(params));
} }
@ -637,20 +762,28 @@ public class SceneScriptManager {
int eventType = params.type; int eventType = params.type;
Set<SceneTrigger> relevantTriggers = new HashSet<>(); Set<SceneTrigger> relevantTriggers = new HashSet<>();
if (eventType == EventType.EVENT_ENTER_REGION || eventType == EventType.EVENT_LEAVE_REGION) { if (eventType == EventType.EVENT_ENTER_REGION || eventType == EventType.EVENT_LEAVE_REGION) {
List<SceneTrigger> relevantTriggersList = this.getTriggersByEvent(eventType).stream() List<SceneTrigger> relevantTriggersList =
.filter(p -> p.getCondition().contains(String.valueOf(params.param1)) && this.getTriggersByEvent(eventType).stream()
(p.getSource().isEmpty() || p.getSource().equals(params.getEventSource()))).toList(); .filter(
p ->
p.getCondition().contains(String.valueOf(params.param1))
&& (p.getSource().isEmpty()
|| p.getSource().equals(params.getEventSource())))
.toList();
relevantTriggers = new HashSet<>(relevantTriggersList); relevantTriggers = new HashSet<>(relevantTriggersList);
} else { } else {
relevantTriggers = this.getTriggersByEvent(eventType).stream() relevantTriggers =
.filter(t -> params.getGroupId() == 0 || t.getCurrentGroup().id == params.getGroupId()) this.getTriggersByEvent(eventType).stream()
.filter(
t -> params.getGroupId() == 0 || t.getCurrentGroup().id == params.getGroupId())
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
for (SceneTrigger trigger : relevantTriggers) { for (SceneTrigger trigger : relevantTriggers) {
handleEventForTrigger(params, trigger); handleEventForTrigger(params, trigger);
} }
} catch (Throwable throwable) { } catch (Throwable throwable) {
Grasscutter.getLogger().error("Condition Trigger "+ params.type +" triggered exception", throwable); Grasscutter.getLogger()
.error("Condition Trigger " + params.type + " triggered exception", throwable);
} finally { } finally {
// make sure it is removed // make sure it is removed
ScriptLoader.getScriptLib().removeSceneScriptManager(); ScriptLoader.getScriptLib().removeSceneScriptManager();
@ -658,7 +791,8 @@ public class SceneScriptManager {
} }
private boolean handleEventForTrigger(ScriptArgs params, SceneTrigger trigger) { private boolean handleEventForTrigger(ScriptArgs params, SceneTrigger trigger) {
Grasscutter.getLogger().debug("checking trigger {} for event {}", trigger.getName(), params.type); Grasscutter.getLogger()
.debug("checking trigger {} for event {}", trigger.getName(), params.type);
try { try {
// setup execution // setup execution
ScriptLoader.getScriptLib().setCurrentGroup(trigger.currentGroup); ScriptLoader.getScriptLib().setCurrentGroup(trigger.currentGroup);
@ -668,13 +802,14 @@ public class SceneScriptManager {
callTrigger(trigger, params); callTrigger(trigger, params);
return true; return true;
} else { } else {
Grasscutter.getLogger().debug("Condition Trigger {} returned false", trigger.getCondition()); Grasscutter.getLogger()
.debug("Condition Trigger {} returned false", trigger.getCondition());
} }
// TODO some ret do not bool // TODO some ret do not bool
return false; return false;
} } catch (Throwable ex) {
catch (Throwable ex){ Grasscutter.getLogger()
Grasscutter.getLogger().error("Condition Trigger "+trigger.getName()+" triggered exception", ex); .error("Condition Trigger " + trigger.getName() + " triggered exception", ex);
return false; return false;
} finally { } finally {
ScriptLoader.getScriptLib().removeCurrentGroup(); ScriptLoader.getScriptLib().removeCurrentGroup();
@ -682,7 +817,13 @@ public class SceneScriptManager {
} }
private boolean evaluateTriggerCondition(SceneTrigger trigger, ScriptArgs params) { private boolean evaluateTriggerCondition(SceneTrigger trigger, ScriptArgs params) {
Grasscutter.getLogger().trace("Call Condition Trigger {}, [{},{},{}]", trigger.getCondition(), params.param1, params.source_eid, params.target_eid); Grasscutter.getLogger()
.trace(
"Call Condition Trigger {}, [{},{},{}]",
trigger.getCondition(),
params.param1,
params.source_eid,
params.target_eid);
LuaValue ret = this.callScriptFunc(trigger.getCondition(), trigger.currentGroup, params); LuaValue ret = this.callScriptFunc(trigger.getCondition(), trigger.currentGroup, params);
return ret.isboolean() && ret.checkboolean(); return ret.isboolean() && ret.checkboolean();
} }
@ -700,18 +841,20 @@ public class SceneScriptManager {
} }
if (trigger.getEvent() == EventType.EVENT_ENTER_REGION) { if (trigger.getEvent() == EventType.EVENT_ENTER_REGION) {
var region = this.regions.values().stream() var region =
this.regions.values().stream()
.filter(p -> p.getConfigId() == params.param1) .filter(p -> p.getConfigId() == params.param1)
.toList().get(0); .toList()
this.getScene().getPlayers() .get(0);
.forEach(p -> p.onEnterRegion(region.getMetaRegion())); this.getScene().getPlayers().forEach(p -> p.onEnterRegion(region.getMetaRegion()));
this.deregisterRegion(region.getMetaRegion()); this.deregisterRegion(region.getMetaRegion());
} else if (trigger.getEvent() == EventType.EVENT_LEAVE_REGION) { } else if (trigger.getEvent() == EventType.EVENT_LEAVE_REGION) {
var region = this.regions.values().stream() var region =
this.regions.values().stream()
.filter(p -> p.getConfigId() == params.param1) .filter(p -> p.getConfigId() == params.param1)
.toList().get(0); .toList()
this.getScene().getPlayers() .get(0);
.forEach(p -> p.onLeaveRegion(region.getMetaRegion())); this.getScene().getPlayers().forEach(p -> p.onLeaveRegion(region.getMetaRegion()));
this.deregisterRegion(region.getMetaRegion()); this.deregisterRegion(region.getMetaRegion());
} }
@ -720,7 +863,8 @@ public class SceneScriptManager {
} }
// always deregister on error, otherwise only if the count is reached // always deregister on error, otherwise only if the count is reached
if (ret.isboolean() && !ret.checkboolean() || ret.isint() && ret.checkint()!=0 if (ret.isboolean() && !ret.checkboolean()
|| ret.isint() && ret.checkint() != 0
|| trigger.getTrigger_count() > 0 && invocations >= trigger.getTrigger_count()) { || trigger.getTrigger_count() > 0 && invocations >= trigger.getTrigger_count()) {
deregisterTrigger(trigger); deregisterTrigger(trigger);
} }
@ -750,7 +894,8 @@ public class SceneScriptManager {
try { try {
return func.call(ScriptLoader.getScriptLibLua(), args); return func.call(ScriptLoader.getScriptLibLua(), args);
} catch (LuaError error) { } catch (LuaError error) {
ScriptLib.logger.error("[LUA] call trigger failed in group {} with {},{}",group.id,name,args,error); ScriptLib.logger.error(
"[LUA] call trigger failed in group {} with {},{}", group.id, name, args, error);
return LuaValue.valueOf(-1); return LuaValue.valueOf(-1);
} }
} }
@ -769,7 +914,8 @@ public class SceneScriptManager {
public EntityGadget createGadget(int groupId, int blockId, SceneGadget g, int state) { public EntityGadget createGadget(int groupId, int blockId, SceneGadget g, int state) {
if (g.isOneoff) { if (g.isOneoff) {
var hasEntity = getScene().getEntities().values().stream() var hasEntity =
getScene().getEntities().values().stream()
.filter(e -> e instanceof EntityGadget) .filter(e -> e instanceof EntityGadget)
.filter(e -> e.getGroupId() == g.group.id) .filter(e -> e.getGroupId() == g.group.id)
.filter(e -> e.getConfigId() == g.config_id) .filter(e -> e.getConfigId() == g.config_id)
@ -797,9 +943,11 @@ public class SceneScriptManager {
return entity; return entity;
} }
public EntityNPC createNPC(SceneNPC npc, int blockId, int suiteId) { public EntityNPC createNPC(SceneNPC npc, int blockId, int suiteId) {
return new EntityNPC(getScene(), npc, blockId, suiteId); return new EntityNPC(getScene(), npc, blockId, suiteId);
} }
public EntityMonster createMonster(int groupId, int blockId, SceneMonster monster) { public EntityMonster createMonster(int groupId, int blockId, SceneMonster monster) {
if (monster == null) { if (monster == null) {
return null; return null;
@ -817,7 +965,8 @@ public class SceneScriptManager {
if (getScene().getDungeonManager() != null) { if (getScene().getDungeonManager() != null) {
level = getScene().getDungeonManager().getLevelForMonster(monster.config_id); level = getScene().getDungeonManager().getLevelForMonster(monster.config_id);
} else if (getScene().getWorld().getWorldLevel() > 0) { } else if (getScene().getWorld().getWorldLevel() > 0) {
var worldLevelData = GameData.getWorldLevelDataMap().get(getScene().getWorld().getWorldLevel()); var worldLevelData =
GameData.getWorldLevelDataMap().get(getScene().getWorld().getWorldLevel());
if (worldLevelData != null) { if (worldLevelData != null) {
level = worldLevelData.getMonsterLevel(); level = worldLevelData.getMonsterLevel();
@ -834,7 +983,8 @@ public class SceneScriptManager {
entity.setMetaMonster(monster); entity.setMetaMonster(monster);
this.getScriptMonsterSpawnService() this.getScriptMonsterSpawnService()
.onMonsterCreatedListener.forEach(action -> action.onNotify(entity)); .onMonsterCreatedListener
.forEach(action -> action.onNotify(entity));
return entity; return entity;
} }
@ -852,17 +1002,20 @@ public class SceneScriptManager {
} }
public void removeEntities(List<? extends GameEntity> gameEntity) { public void removeEntities(List<? extends GameEntity> gameEntity) {
getScene().removeEntities(gameEntity.stream().map(e -> (GameEntity) e).collect(Collectors.toList()), VisionTypeOuterClass.VisionType.VISION_TYPE_REFRESH); getScene()
.removeEntities(
gameEntity.stream().map(e -> (GameEntity) e).collect(Collectors.toList()),
VisionTypeOuterClass.VisionType.VISION_TYPE_REFRESH);
} }
public RTree<SceneBlock, Geometry> getBlocksIndex() { public RTree<SceneBlock, Geometry> getBlocksIndex() {
return meta.sceneBlockIndex; return meta.sceneBlockIndex;
} }
public void removeMonstersInGroup(SceneGroup group, SceneSuite suite) { public void removeMonstersInGroup(SceneGroup group, SceneSuite suite) {
var configSet = suite.sceneMonsters.stream() var configSet = suite.sceneMonsters.stream().map(m -> m.config_id).collect(Collectors.toSet());
.map(m -> m.config_id) var toRemove =
.collect(Collectors.toSet()); getScene().getEntities().values().stream()
var toRemove = getScene().getEntities().values().stream()
.filter(e -> e instanceof EntityMonster) .filter(e -> e instanceof EntityMonster)
.filter(e -> e.getGroupId() == group.id) .filter(e -> e.getGroupId() == group.id)
.filter(e -> configSet.contains(e.getConfigId())) .filter(e -> configSet.contains(e.getConfigId()))
@ -870,11 +1023,11 @@ public class SceneScriptManager {
getScene().removeEntities(toRemove, VisionTypeOuterClass.VisionType.VISION_TYPE_MISS); getScene().removeEntities(toRemove, VisionTypeOuterClass.VisionType.VISION_TYPE_MISS);
} }
public void removeGadgetsInGroup(SceneGroup group, SceneSuite suite) { public void removeGadgetsInGroup(SceneGroup group, SceneSuite suite) {
var configSet = suite.sceneGadgets.stream() var configSet = suite.sceneGadgets.stream().map(m -> m.config_id).collect(Collectors.toSet());
.map(m -> m.config_id) var toRemove =
.collect(Collectors.toSet()); getScene().getEntities().values().stream()
var toRemove = getScene().getEntities().values().stream()
.filter(e -> e instanceof EntityGadget) .filter(e -> e instanceof EntityGadget)
.filter(e -> e.getGroupId() == group.id) .filter(e -> e.getGroupId() == group.id)
.filter(e -> configSet.contains(e.getConfigId())) .filter(e -> configSet.contains(e.getConfigId()))
@ -884,10 +1037,9 @@ public class SceneScriptManager {
} }
public void killMonstersInGroup(SceneGroup group, SceneSuite suite) { public void killMonstersInGroup(SceneGroup group, SceneSuite suite) {
var configSet = suite.sceneMonsters.stream() var configSet = suite.sceneMonsters.stream().map(m -> m.config_id).collect(Collectors.toSet());
.map(m -> m.config_id) var toRemove =
.collect(Collectors.toSet()); getScene().getEntities().values().stream()
var toRemove = getScene().getEntities().values().stream()
.filter(e -> e instanceof EntityMonster) .filter(e -> e instanceof EntityMonster)
.filter(e -> e.getGroupId() == group.id) .filter(e -> e.getGroupId() == group.id)
.filter(e -> configSet.contains(e.getConfigId())) .filter(e -> configSet.contains(e.getConfigId()))
@ -895,11 +1047,11 @@ public class SceneScriptManager {
toRemove.forEach(getScene()::killEntity); toRemove.forEach(getScene()::killEntity);
} }
public void killGadgetsInGroup(SceneGroup group, SceneSuite suite) { public void killGadgetsInGroup(SceneGroup group, SceneSuite suite) {
var configSet = suite.sceneGadgets.stream() var configSet = suite.sceneGadgets.stream().map(m -> m.config_id).collect(Collectors.toSet());
.map(m -> m.config_id) var toRemove =
.collect(Collectors.toSet()); getScene().getEntities().values().stream()
var toRemove = getScene().getEntities().values().stream()
.filter(e -> e instanceof EntityGadget) .filter(e -> e instanceof EntityGadget)
.filter(e -> e.getGroupId() == group.id) .filter(e -> e.getGroupId() == group.id)
.filter(e -> configSet.contains(e.getConfigId())) .filter(e -> configSet.contains(e.getConfigId()))
@ -912,25 +1064,43 @@ public class SceneScriptManager {
// TODO also remove timers when refreshing and test // TODO also remove timers when refreshing and test
var group = getGroupById(groupID); var group = getGroupById(groupID);
if (group == null || group.triggers == null) { if (group == null || group.triggers == null) {
Grasscutter.getLogger().warn("trying to create a timer for unknown group with id {} and source {}", groupID, source); Grasscutter.getLogger()
.warn(
"trying to create a timer for unknown group with id {} and source {}",
groupID,
source);
return 1; return 1;
} }
Grasscutter.getLogger().info("creating group timer event for group {} with source {} and time {}", Grasscutter.getLogger()
groupID, source, time); .info(
"creating group timer event for group {} with source {} and time {}",
groupID,
source,
time);
for (SceneTrigger trigger : group.triggers.values()) { for (SceneTrigger trigger : group.triggers.values()) {
if (trigger.getEvent() == EVENT_TIMER_EVENT && trigger.getSource().equals(source)) { if (trigger.getEvent() == EVENT_TIMER_EVENT && trigger.getSource().equals(source)) {
Grasscutter.getLogger().warn("[LUA] Found timer trigger with source {} for group {} : {}", Grasscutter.getLogger()
source, groupID, trigger.getName()); .warn(
var taskIdentifier = Grasscutter.getGameServer().getScheduler().scheduleDelayedRepeatingTask(() -> "[LUA] Found timer trigger with source {} for group {} : {}",
callEvent(new ScriptArgs(groupID, EVENT_TIMER_EVENT) source,
.setEventSource(source)), (int)time, (int)time); groupID,
trigger.getName());
var taskIdentifier =
Grasscutter.getGameServer()
.getScheduler()
.scheduleDelayedRepeatingTask(
() ->
callEvent(
new ScriptArgs(groupID, EVENT_TIMER_EVENT).setEventSource(source)),
(int) time,
(int) time);
var groupTasks = activeGroupTimers.computeIfAbsent(groupID, k -> new HashSet<>()); var groupTasks = activeGroupTimers.computeIfAbsent(groupID, k -> new HashSet<>());
groupTasks.add(new Pair<>(source, taskIdentifier)); groupTasks.add(new Pair<>(source, taskIdentifier));
} }
} }
return 0; return 0;
} }
public int cancelGroupTimerEvent(int groupID, String source) { public int cancelGroupTimerEvent(int groupID, String source) {
// TODO test // TODO test
var groupTimers = activeGroupTimers.get(groupID); var groupTimers = activeGroupTimers.get(groupID);
@ -942,7 +1112,8 @@ public class SceneScriptManager {
} }
} }
Grasscutter.getLogger().warn("trying to cancel a timer that's not active {} {}", groupID, source); Grasscutter.getLogger()
.warn("trying to cancel a timer that's not active {} {}", groupID, source);
return 1; return 1;
} }
@ -955,14 +1126,19 @@ public class SceneScriptManager {
if (monsters == null || monsters.isEmpty()) return true; if (monsters == null || monsters.isEmpty()) return true;
return monsters.values().stream().noneMatch(m -> { return monsters.values().stream()
.noneMatch(
m -> {
val entity = scene.getEntityByConfigId(m.config_id); val entity = scene.getEntityByConfigId(m.config_id);
return entity != null && entity.getGroupId() == groupId; return entity != null && entity.getGroupId() == groupId;
}); });
} }
public void onDestroy() { public void onDestroy() {
activeGroupTimers.forEach((gid,times) -> times.forEach((e)->Grasscutter.getGameServer().getScheduler().cancelTask(e.getSecond()))); activeGroupTimers.forEach(
(gid, times) ->
times.forEach(
(e) -> Grasscutter.getGameServer().getScheduler().cancelTask(e.getSecond())));
activeGroupTimers.clear(); activeGroupTimers.clear();
} }
} }

View File

@ -1,10 +1,8 @@
package emu.grasscutter.scripts; package emu.grasscutter.scripts;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import java.util.HashMap;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import lombok.val; import java.util.HashMap;
import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;

View File

@ -3,26 +3,25 @@ package emu.grasscutter.scripts.data;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.scripts.ScriptLoader; import emu.grasscutter.scripts.ScriptLoader;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.luaj.vm2.LuaValue;
import javax.script.Bindings;
import javax.script.CompiledScript;
import javax.script.ScriptException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.script.Bindings;
import javax.script.CompiledScript;
import javax.script.ScriptException;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.luaj.vm2.LuaValue;
@ToString @ToString
@Setter @Setter
public final class SceneGroup { public final class SceneGroup {
public transient int block_id; // Not an actual variable in the scripts but we will keep it here for reference public transient int
block_id; // Not an actual variable in the scripts but we will keep it here for reference
public int id; public int id;
public int refresh_id; public int refresh_id;
@ -46,6 +45,7 @@ public final class SceneGroup {
private transient boolean loaded; // Not an actual variable in the scripts either private transient boolean loaded; // Not an actual variable in the scripts either
private transient CompiledScript script; private transient CompiledScript script;
private transient Bindings bindings; private transient Bindings bindings;
public static SceneGroup of(int groupId) { public static SceneGroup of(int groupId) {
var group = new SceneGroup(); var group = new SceneGroup();
group.id = groupId; group.id = groupId;
@ -92,7 +92,9 @@ public final class SceneGroup {
this.bindings = ScriptLoader.getEngine().createBindings(); this.bindings = ScriptLoader.getEngine().createBindings();
CompiledScript cs = ScriptLoader.getScript("Scene/" + sceneId + "/scene" + sceneId + "_group" + this.id + ".lua"); CompiledScript cs =
ScriptLoader.getScript(
"Scene/" + sceneId + "/scene" + sceneId + "_group" + this.id + ".lua");
if (cs == null) { if (cs == null) {
return this; return this;
@ -105,47 +107,69 @@ public final class SceneGroup {
cs.eval(this.bindings); cs.eval(this.bindings);
// Set // Set
this.monsters = ScriptLoader.getSerializer().toList(SceneMonster.class, this.bindings.get("monsters")).stream() this.monsters =
ScriptLoader.getSerializer()
.toList(SceneMonster.class, this.bindings.get("monsters"))
.stream()
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
this.monsters.values().forEach(m -> m.group = this); this.monsters.values().forEach(m -> m.group = this);
this.npcs = ScriptLoader.getSerializer().toList(SceneNPC.class, this.bindings.get("npcs")).stream() this.npcs =
ScriptLoader.getSerializer().toList(SceneNPC.class, this.bindings.get("npcs")).stream()
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
this.npcs.values().forEach(m -> m.group = this); this.npcs.values().forEach(m -> m.group = this);
this.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, this.bindings.get("gadgets")).stream() this.gadgets =
ScriptLoader.getSerializer()
.toList(SceneGadget.class, this.bindings.get("gadgets"))
.stream()
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
this.gadgets.values().forEach(m -> m.group = this); this.gadgets.values().forEach(m -> m.group = this);
this.triggers = ScriptLoader.getSerializer().toList(SceneTrigger.class, this.bindings.get("triggers")).stream() this.triggers =
ScriptLoader.getSerializer()
.toList(SceneTrigger.class, this.bindings.get("triggers"))
.stream()
.collect(Collectors.toMap(SceneTrigger::getName, y -> y, (a, b) -> a)); .collect(Collectors.toMap(SceneTrigger::getName, y -> y, (a, b) -> a));
this.triggers.values().forEach(t -> t.currentGroup = this); this.triggers.values().forEach(t -> t.currentGroup = this);
this.suites = ScriptLoader.getSerializer().toList(SceneSuite.class, this.bindings.get("suites")); this.suites =
this.regions = ScriptLoader.getSerializer().toList(SceneRegion.class, this.bindings.get("regions")).stream() ScriptLoader.getSerializer().toList(SceneSuite.class, this.bindings.get("suites"));
this.regions =
ScriptLoader.getSerializer()
.toList(SceneRegion.class, this.bindings.get("regions"))
.stream()
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a)); .collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
this.regions.values().forEach(m -> m.group = this); this.regions.values().forEach(m -> m.group = this);
this.init_config = ScriptLoader.getSerializer().toObject(SceneInitConfig.class, this.bindings.get("init_config")); this.init_config =
ScriptLoader.getSerializer()
.toObject(SceneInitConfig.class, this.bindings.get("init_config"));
// Garbages // TODO: fix properly later // Garbages // TODO: fix properly later
Object garbagesValue = this.bindings.get("garbages"); Object garbagesValue = this.bindings.get("garbages");
if (garbagesValue instanceof LuaValue garbagesTable) { if (garbagesValue instanceof LuaValue garbagesTable) {
this.garbages = new SceneGarbage(); this.garbages = new SceneGarbage();
if (garbagesTable.checktable().get("gadgets") != LuaValue.NIL) { if (garbagesTable.checktable().get("gadgets") != LuaValue.NIL) {
this.garbages.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, garbagesTable.checktable().get("gadgets").checktable()); this.garbages.gadgets =
ScriptLoader.getSerializer()
.toList(
SceneGadget.class, garbagesTable.checktable().get("gadgets").checktable());
this.garbages.gadgets.forEach(m -> m.group = this); this.garbages.gadgets.forEach(m -> m.group = this);
} }
} }
// Add variables to suite // Add variables to suite
this.variables = ScriptLoader.getSerializer().toList(SceneVar.class, this.bindings.get("variables")); this.variables =
ScriptLoader.getSerializer().toList(SceneVar.class, this.bindings.get("variables"));
// Add monsters and gadgets to suite // Add monsters and gadgets to suite
this.suites.forEach(i -> i.init(this)); this.suites.forEach(i -> i.init(this));
} catch (ScriptException e) { } catch (ScriptException e) {
Grasscutter.getLogger().error("An error occurred while loading group " + this.id + " in scene " + sceneId + ".", e); Grasscutter.getLogger()
.error(
"An error occurred while loading group " + this.id + " in scene " + sceneId + ".", e);
} }
Grasscutter.getLogger().debug("Successfully loaded group {} in scene {}.", this.id, sceneId); Grasscutter.getLogger().debug("Successfully loaded group {} in scene {}.", this.id, sceneId);
@ -179,5 +203,4 @@ public final class SceneGroup {
.map(g -> g.boss_chest) .map(g -> g.boss_chest)
.findFirst(); .findFirst();
} }
} }

View File

@ -2,7 +2,6 @@ package emu.grasscutter.scripts.data;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@ -25,39 +24,38 @@ public class SceneSuite {
public void init(SceneGroup sceneGroup) { public void init(SceneGroup sceneGroup) {
if (sceneGroup.monsters != null) { if (sceneGroup.monsters != null) {
this.sceneMonsters = new ArrayList<>( this.sceneMonsters =
new ArrayList<>(
this.monsters.stream() this.monsters.stream()
.filter(sceneGroup.monsters::containsKey) .filter(sceneGroup.monsters::containsKey)
.map(sceneGroup.monsters::get) .map(sceneGroup.monsters::get)
.toList() .toList());
);
} }
if (sceneGroup.gadgets != null) { if (sceneGroup.gadgets != null) {
this.sceneGadgets = new ArrayList<>( this.sceneGadgets =
new ArrayList<>(
this.gadgets.stream() this.gadgets.stream()
.filter(sceneGroup.gadgets::containsKey) .filter(sceneGroup.gadgets::containsKey)
.map(sceneGroup.gadgets::get) .map(sceneGroup.gadgets::get)
.toList() .toList());
);
} }
if (sceneGroup.triggers != null) { if (sceneGroup.triggers != null) {
this.sceneTriggers = new ArrayList<>( this.sceneTriggers =
new ArrayList<>(
this.triggers.stream() this.triggers.stream()
.filter(sceneGroup.triggers::containsKey) .filter(sceneGroup.triggers::containsKey)
.map(sceneGroup.triggers::get) .map(sceneGroup.triggers::get)
.toList() .toList());
);
} }
if (sceneGroup.regions != null) { if (sceneGroup.regions != null) {
this.sceneRegions = new ArrayList<>( this.sceneRegions =
new ArrayList<>(
this.regions.stream() this.regions.stream()
.filter(sceneGroup.regions::containsKey) .filter(sceneGroup.regions::containsKey)
.map(sceneGroup.regions::get) .map(sceneGroup.regions::get)
.toList() .toList());
); }
}
} }
} }

View File

@ -32,14 +32,26 @@ public final class SceneTrigger {
@Override @Override
public String toString() { public String toString() {
return "SceneTrigger{" + return "SceneTrigger{"
"name='" + name + '\'' + + "name='"
", config_id=" + config_id + + name
", event=" + event + + '\''
", source='" + source + '\'' + + ", config_id="
", condition='" + condition + '\'' + + config_id
", action='" + action + '\'' + + ", event="
", trigger_count='" + trigger_count + '\'' + + event
'}'; + ", source='"
+ source
+ '\''
+ ", condition='"
+ condition
+ '\''
+ ", action='"
+ action
+ '\''
+ ", trigger_count='"
+ trigger_count
+ '\''
+ '}';
} }
} }

View File

@ -7,8 +7,6 @@ import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.SceneMonster; import emu.grasscutter.scripts.data.SceneMonster;
import emu.grasscutter.scripts.data.ScriptArgs; import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.scripts.listener.ScriptMonsterListener; import emu.grasscutter.scripts.listener.ScriptMonsterListener;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -25,8 +23,12 @@ public final class ScriptMonsterTideService {
private final OnMonsterCreated onMonsterCreated = new OnMonsterCreated(); private final OnMonsterCreated onMonsterCreated = new OnMonsterCreated();
private final OnMonsterDead onMonsterDead = new OnMonsterDead(); private final OnMonsterDead onMonsterDead = new OnMonsterDead();
public ScriptMonsterTideService(SceneScriptManager sceneScriptManager, public ScriptMonsterTideService(
SceneGroup group, int tideCount, int monsterSceneLimit, Integer[] ordersConfigId){ SceneScriptManager sceneScriptManager,
SceneGroup group,
int tideCount,
int monsterSceneLimit,
Integer[] ordersConfigId) {
this.sceneScriptManager = sceneScriptManager; this.sceneScriptManager = sceneScriptManager;
this.currentGroup = group; this.currentGroup = group;
this.monsterSceneLimit = monsterSceneLimit; this.monsterSceneLimit = monsterSceneLimit;
@ -36,11 +38,14 @@ public final class ScriptMonsterTideService {
this.monsterConfigOrders = new ConcurrentLinkedQueue<>(List.of(ordersConfigId)); this.monsterConfigOrders = new ConcurrentLinkedQueue<>(List.of(ordersConfigId));
this.monsterConfigIds = List.of(ordersConfigId); this.monsterConfigIds = List.of(ordersConfigId);
this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterCreatedListener(onMonsterCreated); this.sceneScriptManager
.getScriptMonsterSpawnService()
.addMonsterCreatedListener(onMonsterCreated);
this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterDeadListener(onMonsterDead); this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterDeadListener(onMonsterDead);
// spawn the first turn // spawn the first turn
for (int i = 0; i < this.monsterSceneLimit; i++) { for (int i = 0; i < this.monsterSceneLimit; i++) {
sceneScriptManager.addEntity(this.sceneScriptManager.createMonster(group.id, group.block_id, getNextMonster())); sceneScriptManager.addEntity(
this.sceneScriptManager.createMonster(group.id, group.block_id, getNextMonster()));
} }
} }
@ -76,17 +81,22 @@ public final class ScriptMonsterTideService {
monsterKillCount.incrementAndGet(); monsterKillCount.incrementAndGet();
if (monsterTideCount.get() > 0) { if (monsterTideCount.get() > 0) {
// add more // add more
sceneScriptManager.addEntity(sceneScriptManager.createMonster(currentGroup.id, currentGroup.block_id, getNextMonster())); sceneScriptManager.addEntity(
sceneScriptManager.createMonster(
currentGroup.id, currentGroup.block_id, getNextMonster()));
} }
// spawn the last turn of monsters // spawn the last turn of monsters
// fix the 5-2 // fix the 5-2
sceneScriptManager.callEvent(new ScriptArgs(currentGroup.id, EventType.EVENT_MONSTER_TIDE_DIE, monsterKillCount.get())); sceneScriptManager.callEvent(
new ScriptArgs(
currentGroup.id, EventType.EVENT_MONSTER_TIDE_DIE, monsterKillCount.get()));
} }
} }
public void unload() { public void unload() {
this.sceneScriptManager.getScriptMonsterSpawnService().removeMonsterCreatedListener(onMonsterCreated); this.sceneScriptManager
.getScriptMonsterSpawnService()
.removeMonsterCreatedListener(onMonsterCreated);
this.sceneScriptManager.getScriptMonsterSpawnService().removeMonsterDeadListener(onMonsterDead); this.sceneScriptManager.getScriptMonsterSpawnService().removeMonsterDeadListener(onMonsterDead);
} }
} }

View File

@ -4,17 +4,20 @@ import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.props.ElementType; import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.server.event.Cancellable; import emu.grasscutter.server.event.Cancellable;
import emu.grasscutter.server.event.types.EntityEvent; import emu.grasscutter.server.event.types.EntityEvent;
import javax.annotation.Nullable;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import javax.annotation.Nullable;
public final class EntityDamageEvent extends EntityEvent implements Cancellable { public final class EntityDamageEvent extends EntityEvent implements Cancellable {
@Getter @Setter private float damage; @Getter @Setter private float damage;
@Getter @Setter private ElementType attackElementType; @Getter @Setter private ElementType attackElementType;
@Getter @Nullable private final GameEntity damager; @Getter @Nullable private final GameEntity damager;
public EntityDamageEvent(GameEntity entity, float damage, ElementType attackElementType, @Nullable GameEntity damager) { public EntityDamageEvent(
GameEntity entity,
float damage,
ElementType attackElementType,
@Nullable GameEntity damager) {
super(entity); super(entity);
this.damage = damage; this.damage = damage;

View File

@ -22,5 +22,4 @@ public class HandlerAddQuestContentProgressReq extends PacketHandler {
session.send(new PacketAddQuestContentProgressRsp(req.getContentType())); session.send(new PacketAddQuestContentProgressRsp(req.getContentType()));
} }
} }

View File

@ -10,9 +10,7 @@ import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketAvatarChangeElementTypeRsp; import emu.grasscutter.server.packet.send.PacketAvatarChangeElementTypeRsp;
import lombok.val; import lombok.val;
/** /** Changes the currently active avatars Element if possible */
* Changes the currently active avatars Element if possible
*/
@Opcodes(PacketOpcodes.AvatarChangeElementTypeReq) @Opcodes(PacketOpcodes.AvatarChangeElementTypeReq)
public class HandlerAvatarChangeElementTypeReq extends PacketHandler { public class HandlerAvatarChangeElementTypeReq extends PacketHandler {
@ -21,7 +19,9 @@ public class HandlerAvatarChangeElementTypeReq extends PacketHandler {
var req = AvatarChangeElementTypeReq.parseFrom(payload); var req = AvatarChangeElementTypeReq.parseFrom(payload);
var area = GameData.getWorldAreaDataMap().get(req.getAreaId()); var area = GameData.getWorldAreaDataMap().get(req.getAreaId());
if (area == null || area.getElementType() == null || area.getElementType().getDepotIndex() <= 0) { if (area == null
|| area.getElementType() == null
|| area.getElementType().getDepotIndex() <= 0) {
session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE)); session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE));
return; return;
} }
@ -35,5 +35,4 @@ public class HandlerAvatarChangeElementTypeReq extends PacketHandler {
// Success // Success
session.send(new PacketAvatarChangeElementTypeRsp()); session.send(new PacketAvatarChangeElementTypeRsp());
} }
} }

View File

@ -23,9 +23,12 @@ public class HandlerMusicGameSettleReq extends PacketHandler {
val activityManager = session.getPlayer().getActivityManager(); val activityManager = session.getPlayer().getActivityManager();
val playerDataOpt = activityManager.getPlayerActivityDataByActivityType(ActivityType.NEW_ACTIVITY_MUSIC_GAME); val playerDataOpt =
activityManager.getPlayerActivityDataByActivityType(ActivityType.NEW_ACTIVITY_MUSIC_GAME);
if (playerDataOpt.isEmpty()) { if (playerDataOpt.isEmpty()) {
session.send(new PacketMusicGameSettleRsp(RetcodeOuterClass.Retcode.RET_MUSIC_GAME_LEVEL_CONFIG_NOT_FOUND, req)); session.send(
new PacketMusicGameSettleRsp(
RetcodeOuterClass.Retcode.RET_MUSIC_GAME_LEVEL_CONFIG_NOT_FOUND, req));
return; return;
} }
@ -35,13 +38,17 @@ public class HandlerMusicGameSettleReq extends PacketHandler {
// check if custom beatmap // check if custom beatmap
if (req.getUgcGuid() == 0) { if (req.getUgcGuid() == 0) {
session.getPlayer().getActivityManager().triggerWatcher( session
.getPlayer()
.getActivityManager()
.triggerWatcher(
WatcherTriggerType.TRIGGER_FLEUR_FAIR_MUSIC_GAME_REACH_SCORE, WatcherTriggerType.TRIGGER_FLEUR_FAIR_MUSIC_GAME_REACH_SCORE,
String.valueOf(req.getMusicBasicId()), String.valueOf(req.getMusicBasicId()),
String.valueOf(req.getScore()) String.valueOf(req.getScore()));
);
isNewRecord = handler.setMusicGameRecord(playerData, isNewRecord =
handler.setMusicGameRecord(
playerData,
MusicGamePlayerData.MusicGameRecord.of() MusicGamePlayerData.MusicGameRecord.of()
.musicId(req.getMusicBasicId()) .musicId(req.getMusicBasicId())
.maxCombo(req.getMaxCombo()) .maxCombo(req.getMaxCombo())
@ -49,9 +56,12 @@ public class HandlerMusicGameSettleReq extends PacketHandler {
.build()); .build());
// update activity info // update activity info
session.send(new PacketActivityInfoNotify(handler.toProto(playerData, activityManager.getConditionExecutor()))); session.send(
new PacketActivityInfoNotify(
handler.toProto(playerData, activityManager.getConditionExecutor())));
} else { } else {
handler.setMusicGameCustomBeatmapRecord(playerData, handler.setMusicGameCustomBeatmapRecord(
playerData,
MusicGamePlayerData.CustomBeatmapRecord.of() MusicGamePlayerData.CustomBeatmapRecord.of()
.musicShareId(req.getUgcGuid()) .musicShareId(req.getUgcGuid())
.score(req.getMaxCombo()) .score(req.getMaxCombo())
@ -59,8 +69,7 @@ public class HandlerMusicGameSettleReq extends PacketHandler {
.build()); .build());
} }
session.send(
session.send(new PacketMusicGameSettleRsp(req.getMusicBasicId(), req.getUgcGuid(), isNewRecord)); new PacketMusicGameSettleRsp(req.getMusicBasicId(), req.getUgcGuid(), isNewRecord));
} }
} }

View File

@ -48,6 +48,7 @@
// .realTimeEditTime(briefInfo.getRealTimeEditTime()) // .realTimeEditTime(briefInfo.getRealTimeEditTime())
// .maxScore(briefInfo.getMaxScore()) // .maxScore(briefInfo.getMaxScore())
// .authorUid(session.getPlayer().getUid()) // .authorUid(session.getPlayer().getUid())
//
// .beatmap(MusicGameBeatmap.parse(req.getMusicRecord().getMusicTrackListList())) // .beatmap(MusicGameBeatmap.parse(req.getMusicRecord().getMusicTrackListList()))
// .createTime(Utils.getCurrentSeconds()) // .createTime(Utils.getCurrentSeconds())
// .build(); // .build();
@ -58,6 +59,7 @@
// session // session
// .getPlayer() // .getPlayer()
// .getActivityManager() // .getActivityManager()
//
// .getPlayerActivityDataByActivityType(ActivityType.NEW_ACTIVITY_MUSIC_GAME); // .getPlayerActivityDataByActivityType(ActivityType.NEW_ACTIVITY_MUSIC_GAME);
// if (playerData.isEmpty()) { // if (playerData.isEmpty()) {
// session.send( // session.send(
@ -76,7 +78,8 @@
// .filter(Objects::nonNull) // .filter(Objects::nonNull)
// .filter(item -> item.getAuthorUid() == session.getPlayer().getUid()) // .filter(item -> item.getAuthorUid() == session.getPlayer().getUid())
// .filter(item -> item.getMusicId() == req.getMusicBriefInfo().getMusicId()) // .filter(item -> item.getMusicId() == req.getMusicBriefInfo().getMusicId())
// .filter(item -> item.getSavePosition() == req.getMusicBriefInfo().getSaveIdx()) // .filter(item -> item.getSavePosition() ==
// req.getMusicBriefInfo().getSaveIdx())
// .findFirst(); // .findFirst();
// //
// // delete old beatmap for player // // delete old beatmap for player
@ -90,8 +93,10 @@
// new PacketActivityInfoNotify( // new PacketActivityInfoNotify(
// handler.toProto( // handler.toProto(
// playerData.get(), // playerData.get(),
//
// session.getPlayer().getActivityManager().getConditionExecutor()))); // session.getPlayer().getActivityManager().getConditionExecutor())));
// session.send( // session.send(
// new PacketMusicGameCreateBeatmapRsp(musicGameBeatmap.getMusicShareId(), req.getUgcType())); // new PacketMusicGameCreateBeatmapRsp(musicGameBeatmap.getMusicShareId(),
// req.getUgcType()));
// } // }
// } // }

View File

@ -4,11 +4,11 @@ import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.entity.GameEntity; import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.quest.enums.QuestContent; import emu.grasscutter.game.quest.enums.QuestContent;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.SelectWorktopOptionReqOuterClass.SelectWorktopOptionReq; import emu.grasscutter.net.proto.SelectWorktopOptionReqOuterClass.SelectWorktopOptionReq;
import emu.grasscutter.scripts.constants.EventType; import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.data.ScriptArgs; import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketSelectWorktopOptionRsp; import emu.grasscutter.server.packet.send.PacketSelectWorktopOptionRsp;
@ -26,14 +26,24 @@ public class HandlerSelectWorktopOptionReq extends PacketHandler {
return; return;
} }
session.getPlayer().getScene().selectWorktopOptionWith(req); session.getPlayer().getScene().selectWorktopOptionWith(req);
session.getPlayer().getScene().getScriptManager().callEvent( session
new ScriptArgs(entity.getGroupId(), EventType.EVENT_SELECT_OPTION, entity.getConfigId(), req.getOptionId()) .getPlayer()
); .getScene()
session.getPlayer().getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_WORKTOP_SELECT, entity.getConfigId(), req.getOptionId()); .getScriptManager()
.callEvent(
new ScriptArgs(
entity.getGroupId(),
EventType.EVENT_SELECT_OPTION,
entity.getConfigId(),
req.getOptionId()));
session
.getPlayer()
.getQuestManager()
.queueEvent(
QuestContent.QUEST_CONTENT_WORKTOP_SELECT, entity.getConfigId(), req.getOptionId());
} finally { } finally {
// Always send packet // Always send packet
session.send(new PacketSelectWorktopOptionRsp(req.getGadgetEntityId(), req.getOptionId())); session.send(new PacketSelectWorktopOptionRsp(req.getGadgetEntityId(), req.getOptionId()));
} }
} }
} }

View File

@ -15,7 +15,8 @@ public class HandlerUpdateAbilityCreatedMovingPlatformNotify extends PacketHandl
var notify = UpdateAbilityCreatedMovingPlatformNotify.parseFrom(payload); var notify = UpdateAbilityCreatedMovingPlatformNotify.parseFrom(payload);
var entity = session.getPlayer().getScene().getEntityById(notify.getEntityId()); var entity = session.getPlayer().getScene().getEntityById(notify.getEntityId());
if (!(entity instanceof EntityGadget entityGadget) || !(entityGadget.getRouteConfig() instanceof AbilityRoute)) { if (!(entity instanceof EntityGadget entityGadget)
|| !(entityGadget.getRouteConfig() instanceof AbilityRoute)) {
return; return;
} }

View File

@ -9,7 +9,8 @@
// public PacketAddCustomTeamRsp(Retcode retcode) { // public PacketAddCustomTeamRsp(Retcode retcode) {
// super(PacketOpcodes.AddCustomTeamRsp); // super(PacketOpcodes.AddCustomTeamRsp);
// //
// AddCustomTeamRsp proto = AddCustomTeamRsp.newBuilder().setRetcode(retcode.getNumber()).build(); // AddCustomTeamRsp proto =
// AddCustomTeamRsp.newBuilder().setRetcode(retcode.getNumber()).build();
// //
// this.setData(proto); // this.setData(proto);
// } // }

View File

@ -5,7 +5,6 @@ import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.EntityFightPropUpdateNotifyOuterClass.EntityFightPropUpdateNotify; import emu.grasscutter.net.proto.EntityFightPropUpdateNotifyOuterClass.EntityFightPropUpdateNotify;
import java.util.Collection; import java.util.Collection;
public class PacketEntityFightPropUpdateNotify extends BasePacket { public class PacketEntityFightPropUpdateNotify extends BasePacket {
@ -24,8 +23,7 @@ public class PacketEntityFightPropUpdateNotify extends BasePacket {
public PacketEntityFightPropUpdateNotify(GameEntity entity, Collection<FightProperty> props) { public PacketEntityFightPropUpdateNotify(GameEntity entity, Collection<FightProperty> props) {
super(PacketOpcodes.EntityFightPropUpdateNotify); super(PacketOpcodes.EntityFightPropUpdateNotify);
var protoBuilder = EntityFightPropUpdateNotify.newBuilder() var protoBuilder = EntityFightPropUpdateNotify.newBuilder().setEntityId(entity.getId());
.setEntityId(entity.getId());
props.forEach(p -> protoBuilder.putFightPropMap(p.getId(), entity.getFightProperty(p))); props.forEach(p -> protoBuilder.putFightPropMap(p.getId(), entity.getFightProperty(p)));
this.setData(protoBuilder); this.setData(protoBuilder);

View File

@ -4,7 +4,6 @@ import emu.grasscutter.game.quest.GameMainQuest;
import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.FinishedParentQuestUpdateNotifyOuterClass.FinishedParentQuestUpdateNotify; import emu.grasscutter.net.proto.FinishedParentQuestUpdateNotifyOuterClass.FinishedParentQuestUpdateNotify;
import java.util.List; import java.util.List;
public class PacketFinishedParentQuestUpdateNotify extends BasePacket { public class PacketFinishedParentQuestUpdateNotify extends BasePacket {
@ -12,7 +11,8 @@ public class PacketFinishedParentQuestUpdateNotify extends BasePacket {
public PacketFinishedParentQuestUpdateNotify(GameMainQuest quest) { public PacketFinishedParentQuestUpdateNotify(GameMainQuest quest) {
super(PacketOpcodes.FinishedParentQuestUpdateNotify); super(PacketOpcodes.FinishedParentQuestUpdateNotify);
FinishedParentQuestUpdateNotify proto = FinishedParentQuestUpdateNotify.newBuilder() FinishedParentQuestUpdateNotify proto =
FinishedParentQuestUpdateNotify.newBuilder()
.addParentQuestList(quest.toProto(true)) .addParentQuestList(quest.toProto(true))
.build(); .build();

View File

@ -5,7 +5,6 @@ import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.GetAllMailResultNotifyOuterClass.GetAllMailResultNotify; import emu.grasscutter.net.proto.GetAllMailResultNotifyOuterClass.GetAllMailResultNotify;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import java.time.Instant; import java.time.Instant;
import java.util.List; import java.util.List;
@ -17,7 +16,8 @@ public final class PacketGetAllMailResultNotify extends BasePacket {
public PacketGetAllMailResultNotify(Player player, boolean gifts) { public PacketGetAllMailResultNotify(Player player, boolean gifts) {
super(PacketOpcodes.GetAllMailResultNotify); super(PacketOpcodes.GetAllMailResultNotify);
var packet = GetAllMailResultNotify.newBuilder() var packet =
GetAllMailResultNotify.newBuilder()
.setTransaction(player.getUid() + "-" + Utils.getCurrentSeconds() + "-" + 0) .setTransaction(player.getUid() + "-" + Utils.getCurrentSeconds() + "-" + 0)
.setIsCollected(gifts) .setIsCollected(gifts)
.setPacketBeSentNum(1) .setPacketBeSentNum(1)
@ -25,10 +25,12 @@ public final class PacketGetAllMailResultNotify extends BasePacket {
var inbox = player.getAllMail(); var inbox = player.getAllMail();
if (!gifts && inbox.size() > 0) { if (!gifts && inbox.size() > 0) {
packet.addAllMailList(inbox.stream() packet.addAllMailList(
inbox.stream()
.filter(mail -> mail.stateValue == 1) .filter(mail -> mail.stateValue == 1)
.filter(mail -> mail.expireTime > Instant.now().getEpochSecond()) .filter(mail -> mail.expireTime > Instant.now().getEpochSecond())
.map(mail -> mail.toProto(player)).toList()); .map(mail -> mail.toProto(player))
.toList());
} else { } else {
// Empty mailbox. // Empty mailbox.
// TODO: Implement the gift mailbox. // TODO: Implement the gift mailbox.

View File

@ -18,15 +18,16 @@ public class PacketMusicGameSettleRsp extends BasePacket {
this.setData(proto); this.setData(proto);
} }
public PacketMusicGameSettleRsp(RetcodeOuterClass.Retcode errorCode, MusicGameSettleReqOuterClass.MusicGameSettleReq req) { public PacketMusicGameSettleRsp(
RetcodeOuterClass.Retcode errorCode, MusicGameSettleReqOuterClass.MusicGameSettleReq req) {
super(PacketOpcodes.MusicGameSettleRsp); super(PacketOpcodes.MusicGameSettleRsp);
var proto = MusicGameSettleRspOuterClass.MusicGameSettleRsp.newBuilder() var proto =
MusicGameSettleRspOuterClass.MusicGameSettleRsp.newBuilder()
.setRetcode(errorCode.getNumber()) .setRetcode(errorCode.getNumber())
.setMusicBasicId(req.getMusicBasicId()) .setMusicBasicId(req.getMusicBasicId())
.setUgcGuid(req.getUgcGuid()); .setUgcGuid(req.getUgcGuid());
this.setData(proto); this.setData(proto);
} }
} }

View File

@ -10,7 +10,8 @@ public class PacketPlatformStartRouteNotify extends BasePacket {
public PacketPlatformStartRouteNotify(EntityGadget gadgetEntity) { public PacketPlatformStartRouteNotify(EntityGadget gadgetEntity) {
super(PacketOpcodes.PlatformStartRouteNotify); super(PacketOpcodes.PlatformStartRouteNotify);
val notify = PlatformStartRouteNotify.newBuilder() val notify =
PlatformStartRouteNotify.newBuilder()
.setEntityId(gadgetEntity.getId()) .setEntityId(gadgetEntity.getId())
.setSceneTime(gadgetEntity.getScene().getSceneTime()) .setSceneTime(gadgetEntity.getScene().getSceneTime())
.setPlatform(gadgetEntity.getPlatformInfo()); .setPlatform(gadgetEntity.getPlatformInfo());

View File

@ -9,7 +9,8 @@ public class PacketPlatformStopRouteNotify extends BasePacket {
public PacketPlatformStopRouteNotify(EntityGadget gadgetEntity) { public PacketPlatformStopRouteNotify(EntityGadget gadgetEntity) {
super(PacketOpcodes.PlatformStopRouteNotify); super(PacketOpcodes.PlatformStopRouteNotify);
var notify = PlatformStopRouteNotifyOuterClass.PlatformStopRouteNotify.newBuilder() var notify =
PlatformStopRouteNotifyOuterClass.PlatformStopRouteNotify.newBuilder()
.setPlatform(gadgetEntity.getPlatformInfo()) .setPlatform(gadgetEntity.getPlatformInfo())
.setSceneTime(gadgetEntity.getScene().getSceneTime()) .setSceneTime(gadgetEntity.getScene().getSceneTime())
.setEntityId(gadgetEntity.getId()) .setEntityId(gadgetEntity.getId())

View File

@ -10,6 +10,7 @@
// super(PacketOpcodes.RemoveCustomTeamRsp); // super(PacketOpcodes.RemoveCustomTeamRsp);
// //
// RemoveCustomTeamRsp proto = // RemoveCustomTeamRsp proto =
//
// RemoveCustomTeamRsp.newBuilder().setRetcode(retcode.getNumber()).setId(id).build(); // RemoveCustomTeamRsp.newBuilder().setRetcode(retcode.getNumber()).setId(id).build();
// //
// this.setData(proto); // this.setData(proto);