I have an issue where after I exit the world the capability data does not save when I reload the world. It will save the initial data such as village name but if I modify any data during gameplay theres a 5% chance the data saves when I exit then reload the world.
I read the docs and was told that chunks need to be marked dirty but the docs does not say how to mark the chunk dirty...
Heres the provider:
public class ChunkCapProvider implements ICapabilityProvider, ICapabilitySerializable<CompoundTag> {
private final Capability<IChunk> capability =
ChunkCapability.CHUNK_CAPABILITY;
private final ChunkCapability instance = new ChunkCapability();
private final LazyOptional lazy = LazyOptional.of(()->instance).cast();
public void invalidate(){
lazy.invalidate();
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction direction) {
if(cap == capability )
return lazy;
return LazyOptional.empty();
}
@Override
public CompoundTag serializeNBT() {
return instance.serializeNBT();
}
@Override
public void deserializeNBT(CompoundTag tag) {
instance.deserializeNBT(tag);
}
}
Heres the capability class:
public class ChunkCapability implements IChunk {
public static final ResourceLocation ID = new ResourceLocation(Main.MODID, "owner");
public static final String VILLAGE_NAME = "village_name";
public static final String SAVED_ROLES = "saved_roles";
public static final String SAVED_POINTS = "saved_points";
public static final String BAD_CHUNK = "BAD_VILLAGE_CHUNK";
public static Capability<IChunk> CHUNK_CAPABILITY = null;
private String villageName = "BAD_VILLAGE_CHUNK";
private String savedRoles = "";
private String savedPoints = "";
public ChunkCapability(){
this.getClass();
}
@Override
public CompoundTag serializeNBT() {
CompoundTag nbt = new CompoundTag();
nbt.putString(SAVED_ROLES, this.savedRoles);
nbt.putString(SAVED_POINTS, this.savedPoints);
nbt.putString(VILLAGE_NAME, this.villageName);
return nbt;
}
public void deserializeNBT(CompoundTag tag) {
this.setVillageName(tag.getString(VILLAGE_NAME));
this.setSavedRoles(tag.getString(SAVED_ROLES));
this.setSavedPoints(tag.getString(SAVED_POINTS));
}
public String getVillageName() {
return this.villageName;
}
public void setVillageName(String str) {
this.villageName = str;
}
public void setSavedRoles(String str) {
this.savedRoles = str;
}
public void setRole(String name, String role){
if(!this.hasRole(name)) {
this.savedRoles += (name + ":" + role + ",");
this.savedPoints += (name + ":" + 10 + ",");
return;
}
String roleName = this.getRole(name);
String firstStr = this.savedRoles.substring(0, this.savedRoles.indexOf(name + ":") + name.length() + 1);
String lastStr = this.savedRoles.substring(this.savedRoles.indexOf(name + ":") + ((name.length() + 1) + roleName.length()));
this.savedRoles = firstStr + role + lastStr;
}
public String getRole(String name){
if(this.savedRoles.isEmpty() || !this.savedRoles.contains(name)) {
this.setRole(name, Roles.Role.FOREIGNER.getName());
}
String fStr = this.savedRoles.substring(this.savedRoles.indexOf(name + ":"), this.savedRoles.indexOf(','));
return fStr.substring(fStr.indexOf(':') + 1);
}
public boolean hasRole(String name) {
if(this.savedRoles.isEmpty()) return false;
return this.savedRoles.contains(name);
}
public String getSavedRoles() {
return this.savedRoles;
}
public String getSavedPoints() {
return this.savedPoints;
}
public void setSavedPoints(String name) {
this.savedPoints = name;
}
public int getPoints(String name) {
if(this.savedPoints.isEmpty() || !this.savedRoles.contains(name))
this.setPoints(name, 10);
String fStr = this.savedPoints.substring(this.savedPoints.indexOf(name + ':'));
return Integer.parseInt(fStr.substring(fStr.indexOf(':') + 1, fStr.indexOf(',')));
}
public void setPoints(String name, int rV) {
if(!this.hasPoints(name)){
this.savedPoints += (name + ":" + rV + ",");
return;
}
String oldPoints = String.valueOf(this.getPoints(name));
String points = String.valueOf(rV);
String firstStr = this.savedPoints.substring(0, this.savedPoints.indexOf(name + ":") + name.length() + 1);
String lastStr = this.savedPoints.substring(this.savedPoints.indexOf(name + ":") + ((name.length() + 1) + oldPoints.length()));
Minecraft.getInstance().player.displayClientMessage(Component.nullToEmpty("Saved String: " + (firstStr + points + lastStr)), false);
this.savedPoints = (firstStr + points + lastStr);
}
public boolean hasPoints(String name) {
if(this.savedPoints.isEmpty()) return false;
return this.savedPoints.contains(name);
}
}
Heres where I attach/register:
@Mod.EventBusSubscriber(modid = Main.MODID)
public class CapabilityEvents {
@SubscribeEvent
public static void attachCapability(AttachCapabilitiesEvent<LevelChunk> event){
ChunkCapProvider provider = new ChunkCapProvider();
event.addCapability(ChunkCapability.ID, provider);
event.addListener(provider::invalidate);
}
}