Skip to content

Instantly share code, notes, and snippets.

void Surface::listFriendlyEntities(const MapPosition& position,
ForceID forceID,
double maxDistance,
std::vector<EntityWithOwner*>& result,
bool onlyUnits)
{
BoundingBox searchingBox(-maxDistance, -maxDistance, maxDistance, maxDistance);
searchingBox += position;
ChunkPosition leftTop(TilePosition(searchingBox.leftTop));
ChunkPosition rightBottom(TilePosition(searchingBox.rightBottom));
@Rseding91
Rseding91 / FixedPointNumber.hpp
Created January 14, 2021 14:50
FixedPointNumber
#pragma once
#include <TypeTraitsExtensions.hpp>
#include <Util/FixedPointNumberTemplateForwards.hpp>
#include <cstdlib> // keep me
#include <limits> // keep me
#include <stdint.h>
class Deserialiser;
class Serialiser;
template<class T, uint32_t PrecisionBits>
void CraftingMachine::update()
{
assert(this->isActive());
assert(!this->isToBeDeconstructed());
/** Attempts to craft the current recipe (setting up the recipe if its a furnace) and returns the results of the attempt. */
ProductionResult result = this->useRecipeOnSource();
bool goToSleep = false;
switch (result)
{
@Rseding91
Rseding91 / Rail.cpp
Last active April 17, 2019 21:56
Factorio Rail bounding box logic
std::pair<BoundingBox, BoundingBox> Rail::calculateBoundingBoxes(MapPosition position,
Direction direction,
RailBendingType bendingType,
const BoundingBox& collisionBoundingBox,
const BoundingBox* secondaryCollisionBoundingBox)
{
std::pair<BoundingBox, BoundingBox> boundingBoxes;
if (bendingType == RailBendingType::Straight)
{

Deterministic save load in Factorio

One of the key parts of the save/load process in Factorio is that it must be deterministic. This means that for a given save file (when no external factors change) saving, exiting, and loading the save shouldn't change any observable behavior.

There are a few reasons and benefits for this strict requirement:

  • Without it: You couldn't join a running multiplayer game (and by proxy save, exit, and resume one)
  • Without it: the replay system wouldn't work if you ever saved, exited, and resumed playing.
  • With it: we can easily test that saving and loading produces no observable change letting us know we implemented save/load correctly.
  • With it: you won't see things change randomly as a result of "reloading" like you do in so many other games.
struct base
{
enum class Type
{
A,
B,
C
};
virtual ~base() = default;
@Rseding91
Rseding91 / MacroVariant.cpp
Created August 15, 2018 19:39
MacroVariant
#include <MacroVariant.hpp>
bool MacroVariant::isCorrectDataTypeForAction(MacroVariantType action, const std::type_info& type)
{
switch (action)
{
#define ADD_CASE(ACTION, PREFIX, TYPE, VALUE) \
case MacroVariantType::ACTION: return typeid(std::remove_cv<PREFIX TYPE>) == type;
CALL_ON_EVERY_TYPE_WITH_DATA(ADD_CASE)
#undef ADD_CASE
void Car::update()
{
if (this->tickOfLastUpdate == this->getEntityTick())
return;
this->tickOfLastUpdate = this->getEntityTick();
if (!this->hasBeltImmunity())
this->moveByTransportBelt();
const CarPrototype& prototype = *this->getPrototype();
Vector TransportBelt::calculateEntityMovement(MapPosition oldPosition) const
{
RotationDefinition rotationDefinition = this->rotationPoint;
if (rotationDefinition.empty())
return Vector(this->getPrototype()->speed, this->direction);
Vector originalVector(rotationDefinition.center, oldPosition);
double distance = originalVector.distance();
double orientation = originalVector.getOrientation().getFraction();
Direction PipeConnectionDefinition::calculateDirection(const Vector& offset, const BoundingBox& boundingBox)
{
// diagonal direction in order to fail when load is not successful
Direction direction(Direction::NorthEast);
MapPosition leftTop = boundingBox.getRotatedLeftTop();
MapPosition rightBottom = boundingBox.getRotatedRightBottom();
// calculate direction from the bounding box
if (leftTop.y < offset.dy && rightBottom.y > offset.dy)
{