<commit_before>package me.newyith.generator;

import me.newyith.memory.Memorable;
import me.newyith.memory.Memory;
import me.newyith.util.Debug;
import me.newyith.util.Point;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;

import java.util.*;

public class GeneratorCore implements Memorable {
	//saved in NBT
	private List<List<Point>> generatedLayers = new ArrayList<>(); //TODO: consider removing generatedLayer and using merge(alteredPoints, protectedPoints)
	private List<List<Point>> animationWallLayers = new ArrayList<>();
	private Set<Point> claimedPoints = new HashSet<>();
	private Set<Point> claimedWallPoints = new HashSet<>();
	private boolean isChangingGenerated;
	private boolean isGeneratingWall;
	private UUID placedByPlayerId = null; //set in onPlaced

	//new
	private HashMap<Point, Material> alteredPoints = new HashMap<>();
	private Set<Point> protectedPoints = new HashSet<>();

	private boolean animateGeneration = true;
	private long lastFrameTimestamp = 0;
	private long msPerFrame = 150;

	public static final int generationRangeLimit = 32;





	private Point anchorPoint = null;

	//------------------------------------------------------------------------------------------------------------------

	public void saveTo(Memory m) {
		m.save("anchorPoint", anchorPoint);
		//...
	}

	public static GeneratorCore loadFrom(Memory m) {
		Point anchorPoint = m.loadPoint("anchorPoint");
		boolean isChangingGenerated = m.loadBoolean("isChangingGenerated");
		//...
		GeneratorCore instance = new GeneratorCore(anchorPoint, isChangingGenerated);
		return instance;
	}

	private GeneratorCore(Point anchorPoint, boolean isChangingGenerated) {
		this.anchorPoint = anchorPoint;
		this.isChangingGenerated = isChangingGenerated;
		//...
	}

	//------------------------------------------------------------------------------------------------------------------




	/*
	protected:
		blocks made unbreakable but not changed to bedrock
	generated:
		blocks made unbreakable and blocks changed to bedrock
	claimed:
		points the generate thinks it owns
	//*/



	public GeneratorCore(Point anchorPoint) {
		this.anchorPoint = anchorPoint;
	}

	// - Events -

	public boolean onPlaced(Player placingPlayer) { //<--------- called by rune
		this.placedByPlayerId = placingPlayer.getUniqueId();

		//set overlapWithClaimed = true if placed generator is connected (by faces) to another generator's claimed points
		FortressGeneratorRune rune = FortressGeneratorRunesManager.getRune(this.anchorPoint);
		Set<Point> claimPoints = rune.getPoints();
		claimPoints.addAll(getLayerAround(claimPoints));
		Set<Point> alreadyClaimedPoints = this.getClaimedPointsOfNearbyGenerators();
		boolean overlapWithClaimed = !Collections.disjoint(alreadyClaimedPoints, claimPoints); //disjoint means no points in common

		boolean canPlace = !overlapWithClaimed;
		if (canPlace) {
			//claim wall + 1 layer (and 1 layer around generator)
			List<List<Point>> generatableWallLayers = this.getGeneratableWallLayers();
			this.updateClaimedPoints(generatableWallLayers); //updateClaimedPoints() will add in layer around wall + generator and layer around it

			//tell player how many wall blocks were found
			int foundWallPointsCount = Wall.flattenLayers(generatableWallLayers).size();
			this.sendMessage("Fortress generator found " + String.valueOf(foundWallPointsCount) + " wall blocks.");
		} else {
			this.sendMessage("Fortress generator is too close to another generator's wall.");
		}

		return canPlace;
	}

	public void onBroken() { //<--------- called by rune
		this.degenerateWall(false);
	}

	public void onStateChanged(FgState newState) { //<--------- called by rune
		if (newState == FgState.RUNNING) {
			this.generateWall();
		} else {
			this.degenerateWall(true);
		}
	}

	public void sendMessage(String msg) {
		msg = ChatColor.AQUA + msg;
		Bukkit.getPlayer(this.placedByPlayerId).sendMessage(msg);
	}

	public void tick() {
		if (this.isChangingGenerated) {
			long now = (new Date()).getTime();
			//if (ready to update to next frame)
			if (!this.animateGeneration  || now - this.lastFrameTimestamp > this.msPerFrame ) {
				this.lastFrameTimestamp  = now;

				//update to next frame
				boolean noNextFrame = !this.updateToNextFrame();
				if (noNextFrame) {
					this.isChangingGenerated = false;
				}

				//if (not animating) we finished all at once
				if (!this.animateGeneration) {
					this.isChangingGenerated = false;
				}
			}
		}
	}

	// --------- Internal Methods ---------

	//TODO: refactor animation handling to new class GeneratorCoreAnimation?

	private boolean updateToNextFrame() {
		boolean foundLayerToUpdate = false;

		Debug.msg("updateToNextFrame() called");

		//TODO: consider saving i as animationLayerIndex for increased execution speed
		for (int i = 0; i < this.animationWallLayers.size(); i++) {
			int layerIndex = i;
			//if (degenerating) start from the outer most layer
			if (!this.isGeneratingWall) {
				layerIndex = (animationWallLayers.size()-1) - i;
			}

			List<Point> layer = new ArrayList<>(this.animationWallLayers.get(layerIndex)); //make copy to avoid concurrent modification errors (recheck this is needed)

			//try to update layer
			foundLayerToUpdate = updateLayer(layer, layerIndex);
			Debug.msg("updated layerIndex " + layerIndex + ": " + foundLayerToUpdate);

			if (foundLayerToUpdate && this.animateGeneration) {
				//updated a layer so we're done with this frame
				break;
			}
		} // end for (List<Point> layer : this.wallPoints)

		return foundLayerToUpdate;
	}

	private boolean updateLayer(List<Point> layer, int layerIndex) {
		boolean updatedLayer = false;<commit_msg>Made debug messages spam less.<commit_after>package me.newyith.generator;

import me.newyith.memory.Memorable;
import me.newyith.memory.Memory;
import me.newyith.util.Debug;
import me.newyith.util.Point;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;

import java.util.*;

public class GeneratorCore implements Memorable {
	//saved in NBT
	private List<List<Point>> generatedLayers = new ArrayList<>(); //TODO: consider removing generatedLayer and using merge(alteredPoints, protectedPoints)
	private List<List<Point>> animationWallLayers = new ArrayList<>();
	private Set<Point> claimedPoints = new HashSet<>();
	private Set<Point> claimedWallPoints = new HashSet<>();
	private boolean isChangingGenerated;
	private boolean isGeneratingWall;
	private UUID placedByPlayerId = null; //set in onPlaced

	//new
	private HashMap<Point, Material> alteredPoints = new HashMap<>();
	private Set<Point> protectedPoints = new HashSet<>();

	private boolean animateGeneration = true;
	private long lastFrameTimestamp = 0;
	private long msPerFrame = 150;

	public static final int generationRangeLimit = 32;





	private Point anchorPoint = null;

	//------------------------------------------------------------------------------------------------------------------

	public void saveTo(Memory m) {
		m.save("anchorPoint", anchorPoint);
		//...
	}

	public static GeneratorCore loadFrom(Memory m) {
		Point anchorPoint = m.loadPoint("anchorPoint");
		boolean isChangingGenerated = m.loadBoolean("isChangingGenerated");
		//...
		GeneratorCore instance = new GeneratorCore(anchorPoint, isChangingGenerated);
		return instance;
	}

	private GeneratorCore(Point anchorPoint, boolean isChangingGenerated) {
		this.anchorPoint = anchorPoint;
		this.isChangingGenerated = isChangingGenerated;
		//...
	}

	//------------------------------------------------------------------------------------------------------------------




	/*
	protected:
		blocks made unbreakable but not changed to bedrock
	generated:
		blocks made unbreakable and blocks changed to bedrock
	claimed:
		points the generate thinks it owns
	//*/



	public GeneratorCore(Point anchorPoint) {
		this.anchorPoint = anchorPoint;
	}

	// - Events -

	public boolean onPlaced(Player placingPlayer) { //<--------- called by rune
		this.placedByPlayerId = placingPlayer.getUniqueId();

		//set overlapWithClaimed = true if placed generator is connected (by faces) to another generator's claimed points
		FortressGeneratorRune rune = FortressGeneratorRunesManager.getRune(this.anchorPoint);
		Set<Point> claimPoints = rune.getPoints();
		claimPoints.addAll(getLayerAround(claimPoints));
		Set<Point> alreadyClaimedPoints = this.getClaimedPointsOfNearbyGenerators();
		boolean overlapWithClaimed = !Collections.disjoint(alreadyClaimedPoints, claimPoints); //disjoint means no points in common

		boolean canPlace = !overlapWithClaimed;
		if (canPlace) {
			//claim wall + 1 layer (and 1 layer around generator)
			List<List<Point>> generatableWallLayers = this.getGeneratableWallLayers();
			this.updateClaimedPoints(generatableWallLayers); //updateClaimedPoints() will add in layer around wall + generator and layer around it

			//tell player how many wall blocks were found
			int foundWallPointsCount = Wall.flattenLayers(generatableWallLayers).size();
			this.sendMessage("Fortress generator found " + String.valueOf(foundWallPointsCount) + " wall blocks.");
		} else {
			this.sendMessage("Fortress generator is too close to another generator's wall.");
		}

		return canPlace;
	}

	public void onBroken() { //<--------- called by rune
		this.degenerateWall(false);
	}

	public void onStateChanged(FgState newState) { //<--------- called by rune
		if (newState == FgState.RUNNING) {
			this.generateWall();
		} else {
			this.degenerateWall(true);
		}
	}

	public void sendMessage(String msg) {
		msg = ChatColor.AQUA + msg;
		Bukkit.getPlayer(this.placedByPlayerId).sendMessage(msg);
	}

	public void tick() {
		if (this.isChangingGenerated) {
			long now = (new Date()).getTime();
			//if (ready to update to next frame)
			if (!this.animateGeneration  || now - this.lastFrameTimestamp > this.msPerFrame ) {
				this.lastFrameTimestamp  = now;

				//update to next frame
				boolean noNextFrame = !this.updateToNextFrame();
				if (noNextFrame) {
					this.isChangingGenerated = false;
				}

				//if (not animating) we finished all at once
				if (!this.animateGeneration) {
					this.isChangingGenerated = false;
				}
			}
		}
	}

	// --------- Internal Methods ---------

	//TODO: refactor animation handling to new class GeneratorCoreAnimation?

	private boolean updateToNextFrame() {
		boolean foundLayerToUpdate = false;

		Debug.msg("updateToNextFrame() called");

		//TODO: consider saving i as animationLayerIndex for increased execution speed
		for (int i = 0; i < this.animationWallLayers.size(); i++) {
			int layerIndex = i;
			//if (degenerating) start from the outer most layer
			if (!this.isGeneratingWall) {
				layerIndex = (animationWallLayers.size()-1) - i;
			}

			List<Point> layer = new ArrayList<>(this.animationWallLayers.get(layerIndex)); //make copy to avoid concurrent modification errors (recheck this is needed)

			//try to update layer
			foundLayerToUpdate = updateLayer(layer, layerIndex);
			if (foundLayerToUpdate) {
				Debug.msg("updated layerIndex " + layerIndex + ": " + foundLayerToUpdate);
			}

			if (foundLayerToUpdate && this.animateGeneration) {
				//updated a layer so we're done with this frame
				break;
			}
		} // end for (List<Point> layer : this.wallPoints)

		return foundLayerToUpdate;
	}

	private boolean updateLayer(List<Point> layer, int layerIndex) {
		boolean updatedLayer = false;
{'fraction_non_alphanumeric': 0.14529248875043269, 'fraction_numerical': 0.0017307026652821046, 'mean_word_length': 3.412752959144712, 'pattern_counts': {'":': 2, '<': 55, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6878072', 'n_tokens_mistral': 3635, 'n_tokens_neox': 3200, 'n_words': 909}